Closed define-private-public closed 6 years ago
I'm working on this right now (it will help with debugging stuff down the road). Currently I'm trying to work on that "line segment," part. This is what I've got right now:
But it doesn't seem to be working right. The debug code I have should be rotating that blue box (which points in Z+) 15 degrees about the Y+ axis. It's doing nothing. What am I doing wrong here?
I need to push up a commit to fix this. Please ping me in gitter / irc and we can talk through the fix.
I saw your latest commit. Is this good now?
Okay, I can now rotate the cube, but that's only using the tuple parameter. But why Can't I push matricies on top first before drawing the cube? They don't seem to be applied to the model.
The same seems to happen w/ zglTranslatef()
calls. I've tried putting them before and after the drawCube
call.
I'm not that familiar with the old fixed function pipeline for OpenGL. I understand that ZGL is trying to emulate this.
Sorry I'm battling a cold.
drawCubes and other primitive drawing operations push matrices onto the stack already, so you shouldn't push a matrix onto the stack and then call one of these operations.
The basic idea is you push a matrix onto the stack, make whatever transformation calls you want and then issue draw calls for that matrix, then pop it off. When you call zglEnd, the matrix will be applied to all the draw calls.
Here's an example -
# Minimal example to open up a zengine window
import zengine, sdl2, opengl, glm
type
Entity3D = object
position: Vec3f
origin: Vec3f
orientation: Quatf
var rot = 0.0
proc newEntity3D(): Entity3D =
result = Entity3D()
# TODO colors (default)
# Does a debug drawi of the `Entity3D` object's parameters
proc debugDraw(self: Entity3D; levelOfDetail: int=10)=
# TODO is the origin and position stuff correct?
drawsphereWires(self.position, 0.15, levelOfDetail, levelOfDetail, WHITE)
drawsphereWires(self.position + self.origin, 0.1, levelOfDetail, levelOfDetail, RED)
# drawCube(self.position, (rot, 0.0, 1.0, 0.0), 0.1, 0.1, 1.0, BLUE) # don't call this here as you already pushed a matrix onto the stack
let
x = self.position.x
y = self.position.y
z = self.position.z
width, height, length = 1.0
color = BLUE
zglPushMatrix() # push a matrix onto the stack
# drawCube(self.position, (rot, 0.0, 1.0, 0.0), 0.1, 0.1, 1.0, BLUE) # don't call this here as you already pushed a matrix onto the stack - it does the same thing
# perform whatever transformations you want here
zglTranslatef(0.5, 1.5, 0.5)
zglRotatef(rot, 0, 1, -1)
zglBegin(DrawMode.ZGLTriangles)
zglColor4ub(color.r, color.g, color.b, color.a)
# ZGL Draw calls here
# Front Face
zglVertex3f(x-width/2, y-height/2, z+length/2)
zglVertex3f(x+width/2, y-height/2, z+length/2)
zglVertex3f(x-width/2, y+height/2, z+length/2)
zglVertex3f(x+width/2, y+height/2, z+length/2)
zglVertex3f(x-width/2, y+height/2, z+length/2)
zglVertex3f(x+width/2, y-height/2, z+length/2)
# Back Face
zglVertex3f(x-width/2, y-height/2, z-length/2)
zglVertex3f(x-width/2, y+height/2, z-length/2)
zglVertex3f(x+width/2, y-height/2, z-length/2)
zglVertex3f(x+width/2, y+height/2, z-length/2)
zglVertex3f(x+width/2, y-height/2, z-length/2)
zglVertex3f(x-width/2, y+height/2, z-length/2)
# Top Face
zglVertex3f(x-width/2, y+height/2, z-length/2)
zglVertex3f(x-width/2, y+height/2, z+length/2)
zglVertex3f(x+width/2, y+height/2, z+length/2)
zglVertex3f(x+width/2, y+height/2, z-length/2)
zglVertex3f(x-width/2, y+height/2, z-length/2)
zglVertex3f(x+width/2, y+height/2, z+length/2)
# Bottom Face
zglVertex3f(x-width/2, y-height/2, z-length/2)
zglVertex3f(x+width/2, y-height/2, z+length/2)
zglVertex3f(x-width/2, y-height/2, z+length/2)
zglVertex3f(x+width/2, y-height/2, z-length/2)
zglVertex3f(x+width/2, y-height/2, z+length/2)
zglVertex3f(x-width/2, y-height/2, z-length/2)
# Right Face
zglVertex3f(x+width/2, y-height/2, z-length/2)
zglVertex3f(x+width/2, y+height/2, z-length/2)
zglVertex3f(x+width/2, y+height/2, z+length/2)
zglVertex3f(x+width/2, y-height/2, z+length/2)
zglVertex3f(x+width/2, y-height/2, z-length/2)
zglVertex3f(x+width/2, y+height/2, z+length/2)
# Left Face
zglVertex3f(x-width/2, y-height/2, z-length/2)
zglVertex3f(x-width/2, y+height/2, z+length/2)
zglVertex3f(x-width/2, y+height/2, z-length/2)
zglVertex3f(x-width/2, y-height/2, z+length/2)
zglVertex3f(x-width/2, y+height/2, z+length/2)
zglVertex3f(x-width/2, y-height/2, z-length/2)
# This call is where the current matrix is applied to all of the above calls
zglEnd()
# Pop the matrix off the stack since we're done with it
zglPopMatrix()
# Constants
const
ScreenWidth = 960
ScreenHeight = 540
# Init zengine
zengine.init(ScreenWidth, ScreenHeight, "DebugDraw for Entity3D test")
zengine.gui.init()
# State variables
var
# Window control
evt = sdl2.defaultEvent
running = true
# Camera control
camera = Camera(
position: vec3f(0, 1, 2),
target: vec3f(0, 1, 0),
up: vec3f(0, 1, 0),
fovY: 60
)
mouseXRel: int
mouseYRel: int
obj = newEntity3D()
# Set the location
obj.position.y += 1
#obj.orientation *= quatf(vec3f(0, 1, 0), 45)
obj.orientation = quatf(vec3f(0, 0, 1), 45)
# Use a first person camera
camera.setMode(CameraMode.FirstPerson)
var clock = Timer()
clock.start()
# Main Game loop
while running:
# Reset
mouseXRel = 0
mouseYRel = 0
clock.tick()
rot += 45.0 * clock.deltaTime()
# Check for new input
pollInput()
# Poll for events
while sdl2.pollEvent(evt):
case evt.kind:
# Shutdown if X button clicked
of QuitEvent:
running = false
of KeyUp:
let keyEvent = cast[KeyboardEventPtr](addr evt)
# Shutdown if ESC pressed
if keyEvent.keysym.sym == K_ESCAPE:
running = false
# Get some info about the camera state
if keyEvent.keysym.sym == K_C:
echo("camera.position=" & $camera.position)
echo("camera.target=" & $camera.target)
echo("camera.up=" & $camera.up)
# Update camera if mouse moved
of MouseMotion:
let mouseMoveEvent = cast[MouseMotionEventPtr](addr evt)
mouseXRel = mouseMoveEvent.xrel
mouseYRel = mouseMoveEvent.yrel
else:
discard
# Update the camera's position
# camera.update(0, -mouseXrel, -mouseYRel)
# Start drawing
beginDrawing()
clearBackground(BLACK)
begin3dMode(camera)
drawPlane(vec3f(0, 0, 0), vec2f(32, 32), GRAY)
debugDraw(obj)
end3dMode()
# done with drawing, display the screen
endDrawing()
swapBuffers()
# Shutdown
zengine.core.shutdown()
Hopefully that helps - if not please ping me in gitter and I'll reply asap.
Okay, I think I understand this a bit better, but this leads me to believe that ZGL's pushMatrix()
might be incorrect when it comes to emulating old OpenGL. Take for example this snippet:
proc zglPushMatrix*() =
if stackCounter == MATRIX_STACK_SIZE - 1:
error("Stack Buffer Overflow (MAX $1 Matrix)" % $MATRIX_STACK_SIZE)
stack[stackCounter] = currentMatrix[]
zglLoadIdentity()
inc(stackCounter)
if currentMatrixMode == MatrixMode.ZGLModelView:
useTempBuffer = true
And take a look at this link: https://stackoverflow.com/a/23971843/778628
That answer says the the previous matrix is cloned when a new matrix is pushed onto the stack. Where as zglPushMatrix
is loading the identity matrix. This is why things didn't work like I expected them to.
It would be nice if I could have a
proc
that will render some debug-drawing ofEntity3D
. Mostly something to visualize theposition
andorientation
values.position
should be a sphereorientation
should be a line segmentI'm also not 100% sure if I set the
orientation
to the correct value. I wanted it to be pointing down towards the user.