Explorar o código

try to add camera 3d :eyes:

Ethosa %!s(int64=4) %!d(string=hai) anos
pai
achega
bc8022584f

+ 2 - 1
README.md

@@ -61,7 +61,7 @@ This section contains links to documentation for all nodes.
 |:--:            |:--:                 |:--:                  |  :--:              |:--:                |:--:                |
 |[Anchor][]      |[Node][]             |[Control][]           |[Node2D][]          |[Node3D][]          |[Drawable][]        |
 |[Color][]       |[Canvas][]           |[ColorRect][]         |[Sprite][]          |[GeometryInstance][]|[GradientDrawable][]|
-|[Font][]        |[Scene][]            |[TextureRect][]       |[AnimatedSprite][]  |                    |                    |
+|[Font][]        |[Scene][]            |[TextureRect][]       |[AnimatedSprite][]  |[Camera3D][]        |                    |
 |[Enums][]       |[AudioStreamPlayer][]|[Label][]             |[YSort][]           |                    |                    |
 |[Exceptions][]  |[AnimationPlayer][]  |[Button][]            |[CollisionShape2D][]|                    |                    |
 |[Image][]       |                     |[EditText][]          |[Camera2D][]        |                    |                    |
@@ -184,6 +184,7 @@ Use the [`Nim compiler user guide`](https://nim-lang.org/docs/nimc.html#dynlibov
 
 [Node3D]:https://ethosa.github.io/nodesnim/nodesnim/nodes3d/node3d.html
 [GeometryInstance]:https://ethosa.github.io/nodesnim/nodesnim/nodes3d/geometry_instance.html
+[Camera3D]:https://ethosa.github.io/nodesnim/nodesnim/nodes3d/camera3d.html
 
 [Drawable]:https://ethosa.github.io/nodesnim/nodesnim/graphics/drawable.html
 [GradientDrawable]:https://ethosa.github.io/nodesnim/nodesnim/graphics/gradient_drawable.html

+ 3 - 4
src/nodesnim/core/enums.nim

@@ -26,6 +26,7 @@ type
     ANIMATED_SPRITE_NODE,
     NODE2D_NODE,
     KINEMATIC_BODY_2D_NODE,
+    TILEMAP_NODE,
     # Control nodes
     BOX_NODE,
     BUTTON_NODE,
@@ -45,13 +46,11 @@ type
     TEXTURE_PROGRESS_BAR_NODE,
     TEXTURE_RECT_NODE,
     VBOX_NODE,
-    VPROGRESS_BAR_NODE,
-    VSLIDER_NODE,
     SUB_WINDOW_NODE,
-    LINE_EDIT_NODE,
     # 3D nodes
     NODE3D_NODE,
-    GEOMETRY_INSTANCE_NODE
+    GEOMETRY_INSTANCE_NODE,
+    CAMERA_3D_NODE
   NodeTypes* {.pure.} = enum
     NODE_TYPE_DEFAULT,
     NODE_TYPE_CONTROL,

+ 8 - 2
src/nodesnim/core/vector3.nim

@@ -37,8 +37,10 @@ proc abs*(a: Vector3Obj): Vector3Obj =
     assert vec3.z == 3
   Vector3Obj(x: abs(a.x), y: abs(a.y), z: abs(a.z))
 
-proc cross*(a, b: Vector3Obj): float {.inline.} =
-  a.x*b.x - a.y*b.y - a.z*b.z
+proc cross*(a, b: Vector3Obj): Vector3Obj {.inline.} =
+  Vector3(a.y*b.z-b.y*a.z,
+          a.z*b.x-b.z*a.x,
+          a.x*b.y-b.x*a.y)
 
 proc cross*(a: Vector3Obj, x, y, z: float): float {.inline.} =
   a.x*x - a.y*y - a.z*z
@@ -64,6 +66,10 @@ proc normalized*(a: Vector3Obj): Vector3Obj =
   result = Vector3(a)
   result.normalize()
 
+proc directionTo*(a, b: Vector3Obj): Vector3Obj =
+  result = Vector3(b.x - a.x, b.y - a.y, b.z - a.z)
+  result.normalize()
+
 proc len*(a: Vector3Obj): float {.inline.} =
   runnableExamples:
     var vec3 = Vector3(1, 5, 7)

+ 17 - 4
src/nodesnim/nodes/scene.nim

@@ -8,7 +8,11 @@ import
   ../core/enums,
   ../core/input,
   ../core/vector2,
-  ../nodes3d/node3d
+  ../core/vector3,
+  ../nodes3d/node3d,
+  ../nodes3d/camera3d,
+  times,
+  math
 
 
 type
@@ -54,9 +58,18 @@ method drawScene*(scene: SceneRef, w, h: GLfloat, paused: bool) {.base.} =
       elif child.type_of_node == NODE_TYPE_3D:
         child.Node3DRef.calcGlobalPosition3()
         gluPerspective(45.0, w/h, 1.0, 5000.0)
-        gluLookAt(0, 0, -1,
-                  0, 0, 1,
-                  0, 1, 0)
+        if current_camera.isNil():
+          gluLookAt(0, 0, -1,
+                    0, 0, 1,
+                    0, 1, 0)
+        else:
+          let
+            pos = current_camera.global_translation
+            front = current_camera.front + pos
+            up = current_camera.up
+          gluLookAt(pos.x, pos.y, pos.z,
+                    front.x, front.y, front.z,
+                    up.x, up.y, up.z)
 
       if not child.is_ready:
         child.on_ready(child)

+ 1 - 0
src/nodesnim/nodes2d/tilemap.nim

@@ -26,6 +26,7 @@ proc TileMap*(name: string = "TileMap"): TileMapRef =
   nodepattern(TileMapRef)
   node2dpattern()
   result.map_size = (x: 25, y: 25)
+  result.kind = TILEMAP_NODE
   newSeq(result.map, result.map_size.x*result.map_size.y)
 
 

+ 3 - 2
src/nodesnim/nodes3d.nim

@@ -1,6 +1,7 @@
 import
   nodes3d/node3d,
-  nodes3d/geometry_instance
+  nodes3d/geometry_instance,
+  nodes3d/camera3d
 
 export
-  node3d, geometry_instance
+  node3d, geometry_instance, camera3d

+ 71 - 0
src/nodesnim/nodes3d/camera3d.nim

@@ -0,0 +1,71 @@
+# author: Ethosa
+import
+  ../thirdparty/opengl,
+
+  ../core/vector3,
+  ../core/input,
+  ../core/enums,
+
+  ../nodes/node,
+  node3d,
+  math
+
+type
+  Camera3DObj* = object of Node3DObj
+    current*: bool
+    pitch*, yaw*: float
+    target*: Node3DRef
+    front*: Vector3Obj
+    up*: Vector3Obj
+  Camera3DRef* = ref Camera3DObj
+
+
+var
+  nodes: seq[Camera3DRef] = @[]
+  current_camera*: Camera3DRef = nil
+
+
+proc Camera3D*(name: string = "Camera3D"): Camera3DRef =
+  ## Creates a new Camera3D.
+  ##
+  ## Arguments:
+  ## - `name` is a node name.
+  runnableExamples:
+    var node = Camera3D("Camera3D")
+  nodepattern(Camera3DRef)
+  node3dpattern()
+  result.current = false
+  result.kind = CAMERA_3D_NODE
+  result.front = Vector3(0, 0, 1)
+  result.up = Vector3(0, 1, 0)
+  result.pitch = 0f
+  result.yaw = 90f
+  nodes.add(result)
+
+
+method changeTarget*(self: Camera3DRef, target: Node3DRef) {.base.} =
+  ## Changes camera target (without camera position.)
+  self.target = target
+
+method draw*(self: Camera3DRef, w, h: GLfloat) =
+  ## this method uses in the `window.nim`.
+  {.warning[LockLevel]: off.}
+  self.calcGlobalPosition3()
+
+  if self.pitch < -89f:
+    self.pitch = -89f
+  elif self.pitch > 89f:
+    self.pitch = 89f
+
+  self.front = Vector3(
+    cos(degToRad(self.yaw)) * cos(degToRad(self.pitch)),
+    sin(degToRad(self.pitch)),
+    sin(degToRad(self.yaw)) * cos(degToRad(self.pitch)))
+  self.front.normalize()
+
+method setCurrent*(self: Camera3DRef) {.base.} =
+  ## Changes the current camera. It also automatically disable other cameras.
+  for c in nodes:
+    c.current = false
+  self.current = true
+  current_camera = self

+ 1 - 0
tests/README.md

@@ -47,3 +47,4 @@
 - [Use TileMap node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test45.nim)
 - [Use padding.](https://github.com/Ethosa/nodesnim/blob/master/tests/test46.nim)
 - [Use margin.](https://github.com/Ethosa/nodesnim/blob/master/tests/test47.nim)
+- [Use Camera3D node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test48.nim)

+ 54 - 0
tests/test48.nim

@@ -0,0 +1,54 @@
+# --- Test 48. Use Camera3D node. --- #
+import nodesnim
+
+Window("camera 3d test")
+
+
+build:
+  - Scene main:
+    - Node3D root:
+      call translate(2, 2, -5)
+      - Camera3D camera:
+        call setCurrent()
+        call changeTarget(root)
+    - GeometryInstance cube:
+      translation: Vector3(-1, 0, 2)
+      color: Color(122, 133, 144, 0.8)
+    - GeometryInstance cube1:
+      translation: Vector3(2, 0, -2)
+      color: Color(144, 144, 122, 0.8)
+    - GeometryInstance cube2:
+      translation: Vector3(1, 2.5, 1)
+      color: Color(144, 111, 144, 0.8)
+    - GeometryInstance sphere:
+      translation: Vector3(-1, -1, 1)
+      color: Color(144, 77, 144, 1.0)
+      geometry: GEOMETRY_SPHERE
+    - ProgressBar health:
+      call resize(256, 48)
+      call setAnchor(0, 1, 0, 1)
+      call setProgress(50)
+      call setProgressColor(Color("#a77"))
+      call setBackgroundColor(Color(222, 222, 222, 0.5))
+
+Input.addKeyAction("forward", "w")
+Input.addKeyAction("back", "s")
+Input.addKeyAction("left", "a")
+Input.addKeyAction("right", "d")
+
+root@on_input(self, event):
+  if event.isInputEventMouseMotion() and event.pressed:
+    camera.pitch += event.yrel*0.1  # Y
+    camera.yaw -= event.xrel*0.1    # X
+  if Input.isActionPressed("left"):
+    root.translate(camera.front.cross(camera.up).normalized() * -0.1)
+  if Input.isActionPressed("right"):
+    root.translate(camera.front.cross(camera.up).normalized() * 0.1)
+  if Input.isActionPressed("forward"):
+    root.translate(camera.front*0.1)
+  if Input.isActionPressed("back"):
+    root.translate(camera.front*(-0.1))
+
+
+addMainScene(main)
+windowLaunch()