Dark Bit Factory & Gravity
PROGRAMMING => Other languages => Blitz => Topic started by: Devils Child on June 30, 2007
-
hi!
it is my software render lib again. i have problems when i try to implement a freelook code.
i had these problems in all of my previous software renderer attempts and in my openGL engine i made some months ago.
http://www.dc.freecoder-portal.de/upload/files/Devils%20Child/VirtualGL.zip (479.56 KB)
i know i'm asking for a lot of help, but please help me :)
thanks a lot for a reply!
-
It's not working the way that you want yet because of the camera.
Jim put a lot of stuff together about this, you need to build matrices for the camera and objects and then multiply them together.
There are at least three other people here too that have done this so you'll get your answer soon I think.
Your car looks great by the way!
-
hmm i have the same functions as in the real openGL lib:
- vglMatrixIdentity()
- vglMatrixScale(x#, y#, z#)
- vglMatrixRotate(x#, y#, z#)
- vglMatrixTranslate(x#, y#, z#)
you can use these functions just like in openGL. if you put rotation behind scale, the matrices will be multiplicated and optimized internally
i have seen jims source code, of course!
but still, i dont see any differences talking about matrices. except that my matrix system is optimized...
btw: i didnt make the car. i found it on the web
-
In your FreeLook sample, you've got Rotate after Translate - surely that will cause it to rotate round the wrong place?
Jim
-
rotating after translating makes it look like the non-freelook sample...
also i posted that on my last software-rendering attempt here:
http://www.blitzbasic.com/Community/posts.php?topic=61719
I see what you mean, it is because the three angles affect each other. When Roll=180, the Yaw works upside down. As long as the three angles are not handled correctly, the function will give strange results.
-
OK. The problem is called gimbal lock. Once you've rotated by two axes it's possible to lose the 3rd axis of orientation altogether. This is insoluble using Euler rotation angles. Can you explain what FreeLook is meant to do - what you expect to see when you use it?
Cheers
Jim
-
well, actually, i mean this:
Graphics3D 800, 600, 32, 2
SetBuffer BackBuffer()
;Camera
Cam = CreateCamera()
RotateEntity CreateLight(), 70, 20, 0
;Cubes
Cube1 = CreateCube()
PositionEntity Cube1, -2, 0, 5
Cube2 = CreateCube()
PositionEntity Cube2, 2, 0, 5
SetFont LoadFont("Arial", 30, True)
While Not KeyHit(1)
;Cube 1 rotation (WRONG!)
rot = rot + 2
RotateEntity Cube1, rot, rot, rot
;Cube 2 rotation (RIGHT!)
TurnEntity Cube2, 2, 2, 2
RenderWorld
Text 40, 100, "Wrong:"
Text 40, 140, "(Like in my software renderer)"
Text 500, 100, "Right:"
Rect 400, 0, 1, 600
Flip
Wend
End
-
hm. i waited if someone makes a reply.. anyway: jim, i checked out your software renderer ant noticed that your rotation doesnt look like quaternion either. it looks more like euler.
also i have no idea what the "W" parameter does in a vector assignment..
-
The way I deal with this is to store the 3*3 matrix with the object, the 3*3 matrix is 3 vectors that initially point along each axis:
(x0,y0,z0)=(1,0,0)
(x1,y1,z1)=(0,1,0)
(x2,y2,z2)=(0,0,1)
to rotate the object you rotate the vectors around each axis but something I found that surprised me was that if you rotate your vectors as x0,y0,z0 x1,y1,z1 x2,y2,z2 then the object rotates around it's own axis BUT if you rotate your vectors as x0,x1,x2 y0,y1,y2 z0,z1,z2 then the object rotates around the world axis (or is it the other way round).
And by multiplying the object matrix by the camera matrix you can transform from object->world->camera space in one step (you need to calculate the objects origin in camera space too though).
I've never really seen anyone else doing it this way so I don't know if it's unpopular for any reason or not but I like it and it can be made to fit in with quaternions and loaded into opengl matrices with a little bit of messing around.
-
actually, i'm using 4x4 matrices (since the last column of the matrix is not necessairy i use 3x4 matrices)
hmh, blitz3d's rotation looks way better than my rotation
i still cant understand what a 4-float vector is...
my vectors are (x,y,z) ; but some vectors are (x,y,z,w)
the w must be some stuff arround quaternions, so i need to calculate the 'w' value somehow to get quaternions, right?
-
i never got as far as implementing it but here are some linke I found on it that mite be of use
http://dbfinteractive.com/index.php?topic=1843.msg27625#msg27625 (http://dbfinteractive.com/index.php?topic=1843.msg27625#msg27625)
-
The w in my engine is just 1/z. It has nothing to do with rotations. 1/z is a very useful thing to have around for wbuffering and perspective correct texturing. Quaternion rotations might solve your problem, but it's kind of using a sledgehammer to crack a walnut.
Your example code is just showing that
(pitch1,yaw1,roll1)+(pitch2,yaw2,roll2) is not the same as (pitch1+pitch2,yaw1+yaw2,roll1+roll2) which is what you would expect. To easily do those sums you either need to be working with matrices, axis angles, or quaternions.
Jim
-
seems like that if i take the vertex vector like w=1.0/z the whole thing starts to wobble even more.
quaternion rotation should be looking like this:, right?
Graphics3D 800, 600, 32, 2
SetBuffer BackBuffer()
;Camera
Cam = CreateCamera()
RotateEntity CreateLight(), 70, 20, 0
;Cubes
Cube = CreateCube()
PositionEntity Cube, 0, 0, 3
SetFont LoadFont("Arial", 30, True)
While Not KeyHit(1)
TurnEntity Cube, 2, 2, 2
RenderWorld
Flip
Wend
End
-
seems like that if i take the vertex vector like w=1.0/z the whole thing starts to wobble even more.[/quute]
I don't understand this.
quaternion rotation should be looking like this:, right?
Theoretically, yes. They're tough to implement though. I should be able to help you out if you want.
I'm still not absolutely sure what problem you are trying to solve. I can see the obvious differences/problems in your sample code. Are you trying to use several 3-angle rotations in a row to orient something, and that's what's wrong? If so, why are you trying to do that? If you're just trying to point the camera at an object (which is what I understand by 'freelook') then it's simpler than you're making it.
Jim
-
actually, i'm not trying to imitate a PointEntity. also i know how that works. i'm rather trying to make my rotation look like in the b3d sample i posted above. this would solve several other problems i'm facing.
i would really appreciate your help, tho :)
btw: my matrix system looks weird, but these over complicated maths there are just matrix rotation/pos/scale and multiplication in one step...
-
This is a simplified version of what I use, I came up with it while trying to emulate what B3D does. The directions of rotations are probably different and one of the rotation functions in B3D resets the rotation first which mine doesn't (I find it more useful that way).
Type vertex
Field x#,y#,z#
Field rx#,ry#,rz#
Field sx,sy
End Type
Type triangle
Field vertex.vertex[3]
End Type
Type entity
Field x#,y#,z#
Field ux0#,uy0#,uz0#
Field ux1#,uy1#,uz1#
Field ux2#,uy2#,uz2#
Field vertex.vertex[8]
Field vertex_count
Field triangle.triangle[12]
Field triangle_count
End Type
;*******************************************************************************************************************************
;entity creation functions
Function add_vertex(entity_h,x#,y#,z#)
entity.entity=Object.entity(entity_h)
entity\vertex[entity\vertex_count]=New vertex
entity\vertex[entity\vertex_count]\x=x
entity\vertex[entity\vertex_count]\y=y
entity\vertex[entity\vertex_count]\z=z
entity\vertex_count=entity\vertex_count+1
Return Handle(entity\vertex[entity\vertex_count-1])
End Function
Function add_triangle(entity_h,v0_h,v1_h,v2_h)
entity.entity=Object.entity(entity_h)
entity\triangle[entity\triangle_count]=New triangle
entity\triangle[entity\triangle_count]\vertex[0]=Object.vertex(v0_h)
entity\triangle[entity\triangle_count]\vertex[1]=Object.vertex(v1_h)
entity\triangle[entity\triangle_count]\vertex[2]=Object.vertex(v2_h)
entity\triangle_count=entity\triangle_count+1
End Function
Function create_entity()
new_entity.entity=New entity
;set up the initial matrix (1,0,0),(0,1,0),(0,0,1)
new_entity\ux0=1.0
new_entity\uy1=1.0
new_entity\uz2=1.0
Return Handle(new_entity)
End Function
;*******************************************************************************************************************************
;entity control functions
;rotate the entity relative to it's own axis
Function rotate_entity(entity_h,a#,b#,c#)
entity.entity=Object.entity(entity_h)
csa#=Cos(-a)
sna#=Sin(-a)
csb#=Cos(-b)
snb#=Sin(-b)
csc#=Cos(c)
snc#=Sin(c)
x#=entity\ux0*csb+entity\ux2*snb
z#=entity\ux2*csb-entity\ux0*snb
entity\ux2=z*csa+entity\ux1*sna
y#=entity\ux1*csa-z*sna
entity\ux0=x*csc+y*snc
entity\ux1=y*csc-x*snc
x=entity\uy0*csb+entity\uy2*snb
z=entity\uy2*csb-entity\uy0*snb
entity\uy2=z*csa+entity\uy1*sna
y=entity\uy1*csa-z*sna
entity\uy0=x*csc+y*snc
entity\uy1=y*csc-x*snc
x=entity\uz0*csb+entity\uz2*snb
z=entity\uz2*csb-entity\uz0*snb
entity\uz2=z*csa+entity\uz1*sna
y=entity\uz1*csa-z*sna
entity\uz0=x*csc+y*snc
entity\uz1=y*csc-x*snc
End Function
;rotate the entity relative to the world axis
Function turn_entity(entity_h,a#,b#,c#)
entity.entity=Object.entity(entity_h)
csa#=Cos(a)
sna#=Sin(a)
csb#=Cos(b)
snb#=Sin(b)
csc#=Cos(-c)
snc#=Sin(-c)
x#=entity\ux0*csb+entity\uz0*snb
z#=entity\uz0*csb-entity\ux0*snb
entity\uz0=z*csa+entity\uy0*sna
y#=entity\uy0*csa-z*sna
entity\ux0=x*csc+y*snc
entity\uy0=y*csc-x*snc
x=entity\ux1*csb+entity\uz1*snb
z=entity\uz1*csb-entity\ux1*snb
entity\uz1=z*csa+entity\uy1*sna
y=entity\uy1*csa-z*sna
entity\ux1=x*csc+y*snc
entity\uy1=y*csc-x*snc
x=entity\ux2*csb+entity\uz2*snb
z=entity\uz2*csb-entity\ux2*snb
entity\uz2=z*csa+entity\uy2*sna
y=entity\uy2*csa-z*sna
entity\ux2=x*csc+y*snc
entity\uy2=y*csc-x*snc
End Function
;move the entity to world coordinates
Function position_entity(entity_h,x#,y#,z#)
entity.entity=Object.entity(entity_h)
entity\x=x
entity\y=y
entity\z=z
End Function
;move the entity relative to the world axis
Function translate_entity(entity_h,x#,y#,z#)
entity.entity=Object.entity(entity_h)
entity\x=entity\x+x
entity\y=entity\y+y
entity\z=entity\z+z
End Function
;move the entity relative to it's own axis
Function move_entity(entity_h,x#,y#,z#)
entity.entity=Object.entity(entity_h)
entity\x=entity\x+x*entity\ux0+y*entity\ux1+z*entity\ux2
entity\y=entity\y+x*entity\uy0+y*entity\uy1+z*entity\uy2
entity\z=entity\z+x*entity\uz0+y*entity\uz1+z*entity\uz2
End Function
;********************************************************************************************************************************
;entity rendering functions
Function rotate_vertices(entity.entity)
i=0
While i<entity\vertex_count
vertex.vertex=entity\vertex[i]
vertex\rx= vertex\x*entity\ux0 + vertex\y*entity\ux1 + vertex\z*entity\ux2 + entity\x
vertex\ry= vertex\x*entity\uy0 + vertex\y*entity\uy1 + vertex\z*entity\uy2 + entity\y
vertex\rz= vertex\x*entity\uz0 + vertex\y*entity\uz1 + vertex\z*entity\uz2 + entity\z
zr#=640.0/vertex\rz
vertex\sx=320.0+vertex\rx*zr
vertex\sy=240.0-vertex\ry*zr
i=i+1
Wend
End Function
Function draw_triangles(entity.entity)
i=0
While i<entity\triangle_count
triangle.triangle=entity\triangle[i]
v0.vertex=triangle\vertex[0]
v1.vertex=triangle\vertex[1]
v2.vertex=triangle\vertex[2]
If ((v1\sx-v0\sx)*(v2\sy-v0\sy))-((v2\sx-v0\sx)*(v1\sy-v0\sy))>0.0 Then
Line v0\sx,v0\sy,v1\sx,v1\sy
Line v1\sx,v1\sy,v2\sx,v2\sy
Line v2\sx,v2\sy,v0\sx,v0\sy
End If
i=i+1
Wend
End Function
Function draw_entity(entity_h)
entity.entity=Object.entity(entity_h)
rotate_vertices(entity)
draw_triangles(entity)
End Function
;*****************************************************************************************************************************
;main code
Function create_cube(size#)
cube=create_entity()
v0=add_vertex(cube,-size,-size,-size)
v1=add_vertex(cube,-size,-size, size)
v2=add_vertex(cube, size,-size, size)
v3=add_vertex(cube, size,-size,-size)
v4=add_vertex(cube,-size, size,-size)
v5=add_vertex(cube,-size, size, size)
v6=add_vertex(cube, size, size, size)
v7=add_vertex(cube, size, size,-size)
add_triangle cube,v0,v1,v5
add_triangle cube,v5,v4,v0
add_triangle cube,v1,v2,v6
add_triangle cube,v6,v5,v1
add_triangle cube,v2,v3,v7
add_triangle cube,v7,v6,v2
add_triangle cube,v3,v0,v4
add_triangle cube,v4,v7,v3
add_triangle cube,v0,v3,v2
add_triangle cube,v2,v1,v0
add_triangle cube,v4,v5,v6
add_triangle cube,v6,v7,v4
Return cube
End Function
Function main()
Graphics 640,480,32,2
cube=create_cube(100.0)
position_entity cube,0,0,1000
SetBuffer BackBuffer()
Color 255,255,255
While Not(KeyHit(1))
rotate_entity cube,2,2,2
;turn_entity cube,0.1,0,0
;move_entity cube,0,0,10
draw_entity cube
Flip
Cls
Wend
End Function
main()
end
-
whats that?
-
A wireframe cube.
-
->Devils Child
Here's a possible fix for you. Instead of rotating by angles again and again which is causing the problem, create a matrix of the rotation you want, and then apply the matrix to the object's matrix each frame.
Jim
-
Am I barking up the totally wrong tree here? As I think that's almost what my code does.
-
The difficulty is still - what's the question/problem? - not what the answer is :)
Jim
-
aaaah now i see it. it's a wireframe cube! sry my dumbness, i thought it was an engline without sample.
thats exactly what i need!
thank you :updance:
edit: this is compatible with 4x4 matrices?
or do i actually need 4x4 matrices or do i just need 3x3 matrices?
i need {rot/scale/pos}
-
Glad you see it now :) If you want you can use create_entity to create a camera in main() too, then you need to send that through to the rotate_vertices function where you can multiply the camera and the object matrices and use the result to do the rotation (along with some calcs for the position of the object in camera space), you can put scaling into that matrix too. That matrix can be used for the top-left 9 elements of the opengl matrix and the position is put into either the right column or the bottom row (can't remember which) but you might need to negate z somehow.
I don't have any blitz code, I put this together from bits and pieces from other languages but if you want I can add in some more of that stuff.
-
now, i see EXACTLY what this is all about!
instead of:
vglMatrixRotate(rotation, rotation, rotation)i do:
for i = 1 to rotation
vglMatrixRotate(1, 1, 1)
next
now i only have to do a dynamic matrix system in which the user can create more matrices (for each entity one) now i really got it! thanks a lot guys! i will write it down right away!!!
:inspired:
-
That would be slightly different, it would work but you'd only be able to rotate in fixed step sizes (e.g. 1 degree steps). Whichever way though, I think you do need to store the whole matrix for each object.