Simple function to rotate 3D objects over given axis
- Psychophanta
- Addict
- Posts: 4997
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Lípetsk, Russian Federation
- Contact:
Simple function to rotate 3D objects over given axis
Current function RotateEntity(#Entity, x, y, z [, Mode]) does not accept an axis of the rotation, but 3 angle values: an angle in the 'x' axis, another in the 'y' axis and another in the 'z' axis.
Besides, those axis are not global (world axis), but local to de object.
The angle for de 'x' axis is in fact a vector wich defines an axis of rotation V(x,0,0), where x value is the angular amount to rotate in the pure 'x' axis.
The angle for de 'y' axis is in fact a vector wich defines an axis of rotation V(0,y,0), where y value is the angular amount to rotate in the pure 'y' axis.
The angle for de 'z' axis is in fact a vector wich defines an axis of rotation V(0,0,z), where z value is the angular amount to rotate in the pure 'z' axis.
Those are a pitch , yaw and roll, i.e., the so called Euler values.
EntityDirection() function does not establish a rotation axis for the object, but its 'x', 'y' and 'z' arguments are just the orientation axis for the object, same as LookAt function.
SetOrientation(ObjectID, x, y, z, w) function just the same, it stablish the axis for the orientation, but this one does it via a simple quaternion instead a simple vector.
Lets have defined a free global (world) vector V=(a,b,c).
There is not a native function to rotate it an angle of |V| and over the world axis defined by (a,b,c).
To perform professional and not professional tasks in an easy way i strongly request for a
Simple function which allows to just rotate 3D objects around a given arbitrary world axis.
The format of a function like that can be RotateByAxis(ObjectID, x, y, z [, Mode]), where (x,y,z) is the vector which defines the axis and direction of the angular rotation, and its modulo is the amount of degrees (or radians) to rotate.
Besides, those axis are not global (world axis), but local to de object.
The angle for de 'x' axis is in fact a vector wich defines an axis of rotation V(x,0,0), where x value is the angular amount to rotate in the pure 'x' axis.
The angle for de 'y' axis is in fact a vector wich defines an axis of rotation V(0,y,0), where y value is the angular amount to rotate in the pure 'y' axis.
The angle for de 'z' axis is in fact a vector wich defines an axis of rotation V(0,0,z), where z value is the angular amount to rotate in the pure 'z' axis.
Those are a pitch , yaw and roll, i.e., the so called Euler values.
EntityDirection() function does not establish a rotation axis for the object, but its 'x', 'y' and 'z' arguments are just the orientation axis for the object, same as LookAt function.
SetOrientation(ObjectID, x, y, z, w) function just the same, it stablish the axis for the orientation, but this one does it via a simple quaternion instead a simple vector.
Lets have defined a free global (world) vector V=(a,b,c).
There is not a native function to rotate it an angle of |V| and over the world axis defined by (a,b,c).
To perform professional and not professional tasks in an easy way i strongly request for a
Simple function which allows to just rotate 3D objects around a given arbitrary world axis.
The format of a function like that can be RotateByAxis(ObjectID, x, y, z [, Mode]), where (x,y,z) is the vector which defines the axis and direction of the angular rotation, and its modulo is the amount of degrees (or radians) to rotate.
http://www.zeitgeistmovie.com
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
Re: Simple function to rotate 3D objects over given axis
I second Psychophanta in his demand, even if this feature is often lacking in common 3D tools.
Here's an old matrix code with rotation around a given axis that could give inspiration to the team. I did it because I haven't found such a code anywhere... Not optimised at all, it is a compilation of several matrix codes from different sources and some by me. Feel free to use it, but don't forget to link to this forum, thank you
Here's an old matrix code with rotation around a given axis that could give inspiration to the team. I did it because I haven't found such a code anywhere... Not optimised at all, it is a compilation of several matrix codes from different sources and some by me. Feel free to use it, but don't forget to link to this forum, thank you
Code: Select all
;*************************************************************************************************************************************
;* By djes for PureBasic
;* Compilation of several matrix codes
;* from different sources and by myself
;* 18 oct 2006
;* Credits desired, or a link to the forum
;* https://www.purebasic.fr/english/viewtopic.php?f=3&t=72270
;* thank you ;)
;*
;* Note for french readers
;* pitch : tangage
;* yaw : cap
;* roll : roulis
;*************************************************************************************************************************************
Structure matrix
mat.f[9]
EndStructure
Structure vector
x.f
y.f
z.f
EndStructure
;*************************************************************************************************************************************
Procedure matrix_by_matrix_multiply(*a.matrix, *b.matrix) ; / * Return To a * /
Define.matrix tmp
For i.l = 0 To 2
For j.l = 0 To 2
tmp\mat[i + j*3] = *a\mat[i + 0*3] * *b\mat[0 + j*3] + *a\mat[i + 1*3] * *b\mat[1 + j*3] + *a\mat[i + 2*3] * *b\mat[2 + j*3]
Next
Next
For i = 0 To 2
For j = 0 To 2
*a\mat[i + j*3] = tmp\mat[i + j*3];
Next j
Next i
; / * 3dica :
; ¦ a b c ¦ ¦ k l m ¦ ¦ ak + bn + cq al + bo + cr am + bp + cs ¦
; ¦ d e f ¦ * ¦ n o p ¦ = ¦ dk + en + fq dl + eo + fr dm + ep + fs ¦
; ¦ h i j ¦ ¦ q r s ¦ ¦ hk + in + jq hl + io + jr hm + ip + js ¦
;* /
EndProcedure
;*************************************************************************************************************************************
Procedure matrix_copy(*a.matrix, *b.matrix) ; / * Return To a * /
For i = 0 To 8
*a\mat[i] = *b\mat[i]
Next i
EndProcedure
;*************************************************************************************************************************************
Procedure matrix_by_vector_multiply(*vekto.vector, *result.vector, *mat.matrix)
vekx.f = *vekto\x
veky.f = *vekto\y
vekz.f = *vekto\z
*result\x = *mat\mat[0] * vekx + *mat\mat[1] * veky + *mat\mat[2] * vekz
*result\y = *mat\mat[3] * vekx + *mat\mat[4] * veky + *mat\mat[5] * vekz
*result\z = *mat\mat[6] * vekx + *mat\mat[7] * veky + *mat\mat[8] * vekz
; / *
; 3dica :
; ¦ a b c 0 ¦
; (Xi + Yj + Zk) * ¦ e f g 0 ¦ = (aX + eY + iZ + m)i + (bX + fY + jZ + n)j +
; ¦ i j k 0 ¦ (cX + gY + kZ + o)k
; ¦ m n o 1 ¦
;* /
EndProcedure
Macro mac_matrix_by_vector_multiply(vekto, result, matrix)
result\x = matrix\mat[0] * vekto\x + matrix\mat[1] * vekto\y + matrix\mat[2] * vekto\z
result\y = matrix\mat[3] * vekto\x + matrix\mat[4] * vekto\y + matrix\mat[5] * vekto\z
result\z = matrix\mat[6] * vekto\x + matrix\mat[7] * vekto\y + matrix\mat[8] * vekto\z
; / *
; 3dica :
; ¦ a b c 0 ¦
; (Xi + Yj + Zk) * ¦ e f g 0 ¦ = (aX + eY + iZ + m)i + (bX + fY + jZ + n)j +
; ¦ i j k 0 ¦ (cX + gY + kZ + o)k
; ¦ m n o 1 ¦
;* /
EndMacro
Procedure matrix_by_vector_multiply_and_perspective(*vekto.vector, *persp.vector, *mat.matrix,screen_dist.f,screen_ppd.f)
vekx.f = *vekto\x
veky.f = *vekto\y
vekz.f = *vekto\z
x.f = *mat\mat[0] * vekx + *mat\mat[1] * veky + *mat\mat[2] * vekz
y.f = *mat\mat[3] * vekx + *mat\mat[4] * veky + *mat\mat[5] * vekz
z.f = *mat\mat[6] * vekx + *mat\mat[7] * veky + *mat\mat[8] * vekz
*persp\x = screen_x_center + (x*screen_dist) / (screen_ppd + z)
*persp\y = screen_y_center + (y*screen_dist) / (screen_ppd + z)
; *persp\x = (x*screen_dist) / (screen_ppd + z)
; *persp\y = (y*screen_dist) / (screen_ppd + z)
; / *
; 3dica :
; ¦ a b c 0 ¦
; (Xi + Yj + Zk) * ¦ e f g 0 ¦ = (aX + eY + iZ + m)i + (bX + fY + jZ + n)j +
; ¦ i j k 0 ¦ (cX + gY + kZ + o)k
; ¦ m n o 1 ¦
;* /
EndProcedure
Macro mac_matrix_by_vector_multiply_and_perspective(vekto, persp, matrix)
xf.f = matrix\mat[0] * vekto\x + matrix\mat[1] * vekto\y + matrix\mat[2] * vekto\z
yf.f = matrix\mat[3] * vekto\x + matrix\mat[4] * vekto\y + matrix\mat[5] * vekto\z
zf.f = matrix\mat[6] * vekto\x + matrix\mat[7] * vekto\y + matrix\mat[8] * vekto\z
persp\x = screen_x_center + (xf*screen_dist) / (screen_ppd + zf)
persp\y = screen_y_center + (yf*screen_dist) / (screen_ppd + zf)
persp\z = zf
; persp\x = (xf*d) / (d + ppd + zf)
; persp\y = (yf*d) / (d + ppd + zf)
; / *
; 3dica :
; ¦ a b c 0 ¦
; (Xi + Yj + Zk) * ¦ e f g 0 ¦ = (aX + eY + iZ + m)i + (bX + fY + jZ + n)j +
; ¦ i j k 0 ¦ (cX + gY + kZ + o)k
; ¦ m n o 1 ¦
;* /
EndMacro
;*************************************************************************************************************************************
Procedure matrix_rotation(*m.matrix, pitch.f, yaw.f, roll.f)
sx.f = Sin(pitch)
sy.f = Sin(yaw)
sz.f = Sin(roll)
cx.f = Cos(pitch)
cy.f = Cos(yaw)
cz.f = Cos(roll)
*m\mat[0 + 0*3] = cy * cz
*m\mat[0 + 1*3] = cy * sz
*m\mat[0 + 2*3] = - sy
*m\mat[1 + 0*3] = sx * sy * cz - cx * sz
*m\mat[1 + 1*3] = sx * sy * sz + cx * cz
*m\mat[1 + 2*3] = sx * cy
*m\mat[2 + 0*3] = cx * sy * cz + sx * sz
*m\mat[2 + 1*3] = cx * sy * sz - sx * cz
*m\mat[2 + 2*3] = cx * cy
; / *3dica :
; ¦ cy*cz cy*sz - sy 0 ¦
; ¦ sx*sy*cz - cx*sz sx*sy*sz + cx*cz sx*cy 0 ¦
; [X]*[Y]*[Z] = ¦ cx*sy*cz + sx*sz cx*sy*sz - sx*cz cx*cy 0 ¦
; ¦ 0 0 0 1 ¦
;* /
EndProcedure
;*************************************************************************************************************************************
Procedure matrix_rotation_around_axis(*m.matrix, *axis.vector, angle.f)
nx.f = *axis\x
ny.f = *axis\y
nz.f = *axis\z
;normalize axis
length.f = Sqr(nx*nx + ny*ny + nz*nz)
; / / too close to 0, can't make a normalized vector
If (length < 0.000001)
length = 0.000001
EndIf
nx = nx / length
ny = ny / length
nz = nz / length
sina.f = Sin(angle)
cosa.f = Cos(angle)
nx2.f = nx*nx
ny2.f = ny*ny
nz2.f = nz*nz
nx3.f = nx*ny*(1 - cosa)
ny3.f = ny*nz*(1 - cosa)
nx5.f = nx*nz*(1 - cosa)
nx4.f = nx*sina
ny4.f = ny*sina
nz2.f = nz*sina
*m\mat[0] = nx2 + (1 - nx2) * cosa
*m\mat[3] = nx3 + nz2
*m\mat[6] = nx5 - ny4
*m\mat[1] = nx3 - nz2
*m\mat[4] = ny2 + (1 - ny2) * cosa
*m\mat[7] = ny3 + nx4
*m\mat[2] = nx5 + ny4
*m\mat[5] = ny3 - nx4
*m\mat[8] = nz2 + (1 - nz2) * cosa
; nx2.f = nx*nx
; ny2.f = ny*ny
; nz2.f = nz*nz
; *m\mat[0 + 0*3] = nx2 + (1 - nx2)*cosa
; *m\mat[0 + 1*3] = nx*ny*(1 - cosa) + nz*sina
; *m\mat[0 + 2*3] = nx*nz*(1 - cosa) - ny*sina
; *m\mat[1 + 0*3] = nx*ny*(1 - cosa) - nz*sina
; *m\mat[1 + 1*3] = ny2 + (1 - ny2)*cosa
; *m\mat[1 + 2*3] = ny*nz*(1 - cosa) + nx*sina
; *m\mat[2 + 0*3] = nx*nz*(1 - cosa) + ny*sina
; *m\mat[2 + 1*3] = ny*nz*(1 - cosa) - nx*sina
; *m\mat[2 + 2*3] = nz2 + (1 - nz2)*cosa
EndProcedure
;*************************************************************************************************************************************
Procedure matrix_identity(*m.matrix)
*m\mat[0 + 0*3] = 1 : *m\mat[1 + 0*3] = 0 : *m\mat[2 + 0*3] = 0
*m\mat[0 + 1*3] = 0 : *m\mat[1 + 1*3] = 1 : *m\mat[2 + 1*3] = 0
*m\mat[0 + 2*3] = 0 : *m\mat[1 + 2*3] = 0 : *m\mat[2 + 2*3] = 1
; / * 3dica :
; ¦ 1 0 0 0 ¦
; ¦ 0 1 0 0 ¦
; ¦ 0 0 1 0 ¦
; ¦ 0 0 0 1 ¦
;* /
EndProcedure
;*************************************************************************************************************************************
;* => obj_rotation_matrix.
Procedure matrix_rotate_around_object_axis(*obj_rotation_matrix.matrix, pitch.f, yaw.f, roll.f)
Protected axis_x.vector, axis_y.vector, axis_z.vector
Protected axis_x_rotation_matrix.matrix, axis_y_rotation_matrix.matrix, axis_z_rotation_matrix.matrix
;rotation around x object axis
axis_x\x = *obj_rotation_matrix\mat[0]
axis_x\y = *obj_rotation_matrix\mat[3]
axis_x\z = *obj_rotation_matrix\mat[6]
matrix_rotation_around_axis(@axis_x_rotation_matrix, @axis_x, pitch)
;rotation around y object axis
axis_y\x = *obj_rotation_matrix\mat[1]
axis_y\y = *obj_rotation_matrix\mat[4]
axis_y\z = *obj_rotation_matrix\mat[7]
matrix_rotation_around_axis(@axis_y_rotation_matrix, @axis_y, yaw)
;rotation around z object axis
axis_z\x = *obj_rotation_matrix\mat[2]
axis_z\y = *obj_rotation_matrix\mat[5]
axis_z\z = *obj_rotation_matrix\mat[8]
matrix_rotation_around_axis(@axis_z_rotation_matrix, @axis_z, roll)
matrix_by_matrix_multiply(@axis_x_rotation_matrix, @axis_y_rotation_matrix)
matrix_by_matrix_multiply(@axis_x_rotation_matrix, @axis_z_rotation_matrix)
matrix_by_matrix_multiply(*obj_rotation_matrix, @axis_x_rotation_matrix)
EndProcedure
;*************************************************************************************************************************************
Procedure vector_define(*vertex.vector, x, y, z)
*vertex\x = x
*vertex\y = y
*vertex\z = z
EndProcedure
;*************************************************************************************************************************************
Procedure vectors_add(*vertex.vector, *vertex2add.vector)
*vertex\x + *vertex2add\x
*vertex\y + *vertex2add\y
*vertex\z + *vertex2add\z
EndProcedure
;*************************************************************************************************************************************
Procedure vectors_sub(*vertex.vector, *vertex2sub.vector)
*vertex\x - *vertex2sub\x
*vertex\y - *vertex2sub\y
*vertex\z - *vertex2sub\z
EndProcedure
;*************************************************************************************************************************************
Procedure vector_copy(*vertexsrc.vector, *vertexdest.vector)
*vertexdest\x = *vertexsrc\x
*vertexdest\y = *vertexsrc\y
*vertexdest\z = *vertexsrc\z
EndProcedure
;*************************************************************************************************************************************
Procedure vector_rotate(*vertex.vector, *pivot.vector, pitch.f, yaw.f, roll.f)
vectors_sub(*vertex, *pivot)
If roll <> 0
x.f = Cos(roll) * *vertex\x - Sin(roll) * *vertex\z
*vertex\z = Sin(roll) * *vertex\x + Cos(roll) * *vertex\z
*vertex\x = x
EndIf
If pitch <> 0
y.f = Cos(pitch) * *vertex\y - Sin(pitch) * *vertex\z
*vertex\z = Sin(pitch) * *vertex\y + Cos(pitch) * *vertex\z
*vertex\y = y
EndIf
If yaw <> 0
x.f = Cos(yaw) * *vertex\x - Sin(yaw) * *vertex\y
*vertex\y = Sin(yaw) * *vertex\x + Cos(yaw) * *vertex\y
*vertex\x = x
EndIf
vectors_add(*vertex, *pivot)
EndProcedure
;*************************************************************************************************************************************
Procedure vector_rotate2(*vertex.vector, *pivot.vector, pitch.f, yaw.f, roll.f)
cr.f = Cos(pitch)
sr.f = Sin(pitch)
cp.f = Cos(roll)
sp.f = Sin(roll)
cy.f = Cos(yaw)
sy.f = Sin(yaw)
Dim m.f(12)
m(0) = (cp*cy)
m(1) = (cp*sy)
m(2) = ( - sp)
srsp.f = sr*sp
crsp.f = cr*sp
m(4) = (srsp*cy - cr*sy)
m(5) = (srsp*sy + cr*cy)
m(6) = (sr*cp);
m(8) = (crsp*cy + sr*sy)
m(9) = (crsp*sy - sr*cy)
m(10) = (cr*cp);
tmpx.f = *vertex\x
tmpy.f = *vertex\y
tmpz.f = *vertex\z
*vertex\x = tmpx*m(0) + tmpy*m(1) + tmpz*m(2)
*vertex\y = tmpx*m(4) + tmpy*m(5) + tmpz*m(6)
*vertex\z = tmpx*m(8) + tmpy*m(9) + tmpz*m(10)
EndProcedure
Re: Simple function to rotate 3D objects over given axis
Not sure what you mean, but try this
Code: Select all
EntityFixedYawAxis(0, #True, axis\x, axis\y, axis\z)
RotateEntity(0, 0, 1, 0, #PB_Relative)
Please correct my english
http://purebasic.developpez.com/
http://purebasic.developpez.com/
- Psychophanta
- Addict
- Posts: 4997
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Lípetsk, Russian Federation
- Contact:
Re: Simple function to rotate 3D objects over given axis
It seems not to do with the explained issue.
Really I suspect the requested function is not hard using the correct way with quaternions.
However, i must say that quaternions DO NOT use less computing resources than matrix, as is written in some texts.
And also some texts say that matrix also lacks about the known problem of "gimbal lock", but that is absolutely incorrect; "gimbal lock" problem is only for the use of Euler angles, i.e. Pitch, Yaw and Roll.
And moreover: quaternions use for 3D engines lacks when dealing with multi-turn rotations, which matrix do not.
Hopefully, not all academic texts about 3D engines, and robotics, talks nice about quaternions in front of homogeneous matrix.
In my own observations, I have founded suspects that there is nor matrix neither quaternions the ideal or optimal way to manage rotations. But nowadays is the tool used everywhere.
Well, time ago I wrote a tip to show it, using the MP3D lib:
If you do not have that lib installed then this is the compiled executeable an should work for you there, it is a normal windows 32bit executeable.
Moving the mouse can rotate the object. With left CTRL + mouse moving orbitates the eye over the object.
The program is able to perform the object rotation ALWAYS over the eye view plane, this is, with the rotation axis contained inside de front view plane.
https://mega.nz/#!QpgSVKDB!HNlntXQCuwNF ... cjAwvEzlhE
In that code, i just replaced conversion functions (quaternion--->rotation matrix) and viceversa, in order it works in the native PB.
Result:
No success.
Previous MP3D code converted to PB native code. Here can see the used functions conversions for quaternion--->rotation matrix and viceversa:
Really I suspect the requested function is not hard using the correct way with quaternions.
However, i must say that quaternions DO NOT use less computing resources than matrix, as is written in some texts.
And also some texts say that matrix also lacks about the known problem of "gimbal lock", but that is absolutely incorrect; "gimbal lock" problem is only for the use of Euler angles, i.e. Pitch, Yaw and Roll.
And moreover: quaternions use for 3D engines lacks when dealing with multi-turn rotations, which matrix do not.
Hopefully, not all academic texts about 3D engines, and robotics, talks nice about quaternions in front of homogeneous matrix.
In my own observations, I have founded suspects that there is nor matrix neither quaternions the ideal or optimal way to manage rotations. But nowadays is the tool used everywhere.
Well, time ago I wrote a tip to show it, using the MP3D lib:
Code: Select all
; Rota una entidad sobre su centro geométrico (rotación intrínseca si ese centro corresponde con su centro de masas). Diciembre 2014
MP_Graphics3D(640,480,0,3)
SetWindowTitle(0,"TurnEntity over relative to eye axis")
maincam.i=MP_CreateCamera()
pivotcam.i=MP_CreateMesh():MP_EntitySetParent(maincam,pivotcam,0):MP_PositionEntity(maincam,0,0,-4)
light.i=MP_CreateLight(1)
If CreateImage(0,255,255)
Font.i=LoadFont(#PB_Any,"Arial",138)
StartDrawing(ImageOutput(0))
Box(0, 0, 128, 128,RGB(255,0,0))
Box(128, 0, 128, 128,RGB(0,255,0))
Box(0, 128, 128, 128,RGB(0,0,255))
Box(128, 128, 128, 128,RGB(255,255,0))
DrawingFont(FontID(Font))
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(73,35,"5",RGB(0,0,0))
StopDrawing()
EndIf
Structure D3DMATRIX
StructureUnion
_11.f
Xi.f
EndStructureUnion
StructureUnion
_12.f
Xj.f
EndStructureUnion
StructureUnion
_13.f
Xk.f
EndStructureUnion
_14.f
StructureUnion
_21.f
Yi.f
EndStructureUnion
StructureUnion
_22.f
Yj.f
EndStructureUnion
StructureUnion
_23.f
Yk.f
EndStructureUnion
_24.f
StructureUnion
_31.f
Zi.f
EndStructureUnion
StructureUnion
_32.f
Zj.f
EndStructureUnion
StructureUnion
_33.f
Zk.f
EndStructureUnion
_34.f
StructureUnion
_41.f
Pi.f
EndStructureUnion
StructureUnion
_42.f
Pj.f
EndStructureUnion
StructureUnion
_43.f
Pk.f
EndStructureUnion
_44.f
EndStructure
Structure D3DXVECTOR3
x.f
y.f
z.f
EndStructure
Structure Vector3D Extends D3DXVECTOR3
m.f;<-length(modulo)
EndStructure
Macro ProductoEscalar(a,b,ax=x,ay=y,az=z,bx=x,by=y,bz=z)
(a#\ax#*b#\bx#+a#\ay#*b#\by#+a#\az#*b#\bz#)
EndMacro
Macro getmodulo(v,vx=x,vy=y,vz=z)
(Sqr#ProductoEscalar(v#,v#,vx#,vy#,vz#,vx#,vy#,vz#))
EndMacro
Procedure.i Matriz3x3xMatriz3x3(*a.D3DMATRIX,*b.D3DMATRIX,*o.D3DMATRIX); producto
*o\_11=*a\_11**b\_11+*a\_12**b\_21+*a\_13**b\_31:*o\_12=*a\_11**b\_12+*a\_12**b\_22+*a\_13**b\_32:*o\_13=*a\_11**b\_13+*a\_12**b\_23+*a\_13**b\_33
*o\_21=*a\_21**b\_11+*a\_22**b\_21+*a\_23**b\_31:*o\_22=*a\_21**b\_12+*a\_22**b\_22+*a\_23**b\_32:*o\_23=*a\_21**b\_13+*a\_22**b\_23+*a\_23**b\_33
*o\_31=*a\_31**b\_11+*a\_32**b\_21+*a\_33**b\_31:*o\_32=*a\_31**b\_12+*a\_32**b\_22+*a\_33**b\_32:*o\_33=*a\_31**b\_13+*a\_32**b\_23+*a\_33**b\_33
ProcedureReturn *o
EndProcedure
Procedure.i Matriz4x4xMatriz4x4(*a.D3DMATRIX,*b.D3DMATRIX,*o.D3DMATRIX); producto
*o\_11=*a\_11**b\_11+*a\_12**b\_21+*a\_13**b\_31+*a\_14**b\_41:*o\_12=*a\_11**b\_12+*a\_12**b\_22+*a\_13**b\_32+*a\_14**b\_42:*o\_13=*a\_11**b\_13+*a\_12**b\_23+*a\_13**b\_33+*a\_14**b\_43:*o\_14=*a\_11**b\_14+*a\_12**b\_24+*a\_13**b\_34+*a\_14**b\_44
*o\_21=*a\_21**b\_11+*a\_22**b\_21+*a\_23**b\_31+*a\_24**b\_41:*o\_22=*a\_21**b\_12+*a\_22**b\_22+*a\_23**b\_32+*a\_24**b\_42:*o\_23=*a\_21**b\_13+*a\_22**b\_23+*a\_23**b\_33+*a\_24**b\_43:*o\_24=*a\_21**b\_14+*a\_22**b\_24+*a\_23**b\_34+*a\_24**b\_44
*o\_31=*a\_31**b\_11+*a\_32**b\_21+*a\_33**b\_31+*a\_34**b\_41:*o\_32=*a\_31**b\_12+*a\_32**b\_22+*a\_33**b\_32+*a\_34**b\_42:*o\_33=*a\_31**b\_13+*a\_32**b\_23+*a\_33**b\_33+*a\_34**b\_43:*o\_34=*a\_31**b\_14+*a\_32**b\_24+*a\_33**b\_34+*a\_34**b\_44
*o\_41=*a\_41**b\_11+*a\_42**b\_21+*a\_43**b\_31+*a\_44**b\_41:*o\_42=*a\_41**b\_12+*a\_42**b\_22+*a\_43**b\_32+*a\_44**b\_42:*o\_43=*a\_41**b\_13+*a\_42**b\_23+*a\_43**b\_33+*a\_44**b\_43:*o\_44=*a\_41**b\_14+*a\_42**b\_24+*a\_43**b\_34+*a\_44**b\_44
ProcedureReturn *o
EndProcedure
Procedure.i flecha(x.f=1,y.f=0,z.f=0,color.l=$EE3333,lados.a=8)
Protected mod.f=Sqr(x*x+y*y+z*z)
If mod>0.0001
Protected cil.i=MP_CreateCylinder(lados,mod),cono.i=MP_CreateCone(lados,mod/8),ciltexture.i=MP_CreateTextureColor(8,8,color)
MP_ResizeMesh(cil,mod/80,mod/80,mod-mod/20)
MP_TranslateMesh(cil,0,0,(mod-mod/20)/2)
mod*7/8
MP_RotateMesh(cono,180,0,180)
MP_ResizeMesh(cono,mod/20,mod/20,mod/10)
MP_TranslateMesh(cono,0,0,mod+mod/10)
MP_AddMesh(cono,cil):MP_FreeEntity(cono)
MP_EntityLookAt(cil,x+0.000001,y,z,0,0)
MP_EntitySetTexture(cil,ciltexture,0,0)
ProcedureReturn cil
EndIf
ProcedureReturn 0
EndProcedure
Procedure.i BaseSistemaCoordenadas(size.f=1,lados.a=8,color.l=$22AADD)
Protected cil.i=MP_CreateCylinder(lados,size),cono.i=MP_CreateCone(lados,size/8),cil2.i
MP_ResizeMesh(cil,size/80,size/80,size-size/20)
MP_TranslateMesh(cil,0,0,(size-size/20)/2)
size*7/8
MP_RotateMesh(cono,180,0,180)
MP_ResizeMesh(cono,size/20,size/20,size/10)
MP_TranslateMesh(cono,0,0,size+size/10)
MP_AddMesh(cono,cil):MP_FreeEntity(cono)
cil2.i=MP_CopyEntity(cil)
MP_RotateMesh(cil2,-90,0,0)
MP_AddMesh(cil2,cil):MP_FreeEntity(cil2)
cil2.i=MP_CopyEntity(cil)
MP_RotateMesh(cil2,0,90,0)
MP_AddMesh(cil2,cil):MP_FreeEntity(cil2)
MP_EntitySetTexture(cil,MP_CreateTextureColor(8,8,color),0,0)
ProcedureReturn cil
EndProcedure
Procedure.i BaseSistemaCoordenadas0(px.f=0,py.f=0,pz.f=0,size.f=1,lados.a=8,colorx.l=$DD3333,colory.l=$99DD99,colorz.l=$2299DD)
Protected vx.i=flecha(size,0,0,colorx,lados)
Protected vy.i=flecha(0,size,0,colory,lados)
Protected vz.i=flecha(0,0,size,colorz,lados)
MP_AddMesh(vx.i,vy.i);:MP_FreeEntity(vx.i)
MP_AddMesh(vz.i,vy.i);:MP_FreeEntity(vz.i)
MP_PositionEntity(vy,px,py,pz)
ProcedureReturn vy.i
EndProcedure
Procedure.i Turn_Body_by_Angle_adding(Body.i,*fi.Vector3D,*matriz.D3DMATRIX=0,vx.f=0,vy.f=0,vz.f=0); <- usar esta cuando no disponemos del módulo angular de antemano (antes de llamar a la función), sino solo del propio vector ángulo
;Rotar una entity (una matriz) un ángulo dado '*fi.Vector3D':
Protected rot.D3DMATRIX,rot1.D3DMATRIX,cos.f,sen.f,coss.f,*u.Vector3D
*fi\m=getmodulo(*fi)
If *fi\m
*u.Vector3D=AllocateMemory(SizeOf(Vector3D)):CopyMemory(*fi,*u,SizeOf(Vector3D))
*u\x/*u\m:*u\y/*u\m:*u\z/*u\m; <- obtener vector unidad (llamado "vector normalizado")
If *matriz=0
*matriz=MP_EntityGetMatrix(Body)
EndIf
cos=Cos(*u\m):sen=Sin(*u\m):coss=1.0-cos
;Matriz de Rotación de un ángulo dado 'A' alrededor de un eje dado definido por el vector unidad (*u\x,*u\y,*u\z)
rot1\Xi=cos+*u\x**u\x*coss:rot1\Xj=*u\x**u\y*coss-*u\z*sen:rot1\Xk=*u\x**u\z*coss+*u\y*sen
rot1\Yi=*u\y**u\x*coss+*u\z*sen:rot1\Yj=cos+*u\y**u\y*coss:rot1\Yk=*u\y**u\z*coss-*u\x*sen
rot1\Zi=*u\z**u\x*coss-*u\y*sen:rot1\Zj=*u\z**u\y*coss+*u\x*sen:rot1\Zk=cos+*u\z**u\z*coss
CopyMemory(*matriz,@rot,SizeOf(D3DMATRIX))
rot\_41+vx:rot\_42+vy:rot\_43+vz
MP_EntitySetMatrix(Body,Matriz3x3xMatriz3x3(*matriz,@rot1,@rot)); <- se multiplica la matriz de inclinación del entity por la matriz rotación y se obtiene la matriz original rotada
FreeMemory(*u)
ProcedureReturn @rot
EndIf
ProcedureReturn 0
EndProcedure
Procedure.i MatrizRotacionaldeunAngulodadoalrededordeunejedefinidoporunvectorunidad(Body.i,*u.Vector3D,A.f,*matriz.D3DMATRIX=0,vx.f=0,vy.f=0,vz.f=0); <- usar esta cuando disponemos de antemano (antes de llamar a la función) del módulo angular y del vector unitario del ángulo
;Rotar un entity un ángulo dado cuya dirección viene dada por el vector unidad '*u.Vector3D' y además por un módulo 'A'
Protected rot.D3DMATRIX,rot1.D3DMATRIX,cos.f,sen.f,coss.f
If A
If *matriz=0
*matriz=MP_EntityGetMatrix(Body)
EndIf
cos=Cos(A):sen=Sin(A):coss=1.0-cos
;Matriz de Rotación de un ángulo dado 'A' alrededor de un eje dado definido por el vector unidad (*u\x,*u\y,*u\z)
rot1\Xi=cos+*u\x**u\x*coss:rot1\Xj=*u\x**u\y*coss-*u\z*sen:rot1\Xk=*u\x**u\z*coss+*u\y*sen
rot1\Yi=*u\y**u\x*coss+*u\z*sen:rot1\Yj=cos+*u\y**u\y*coss:rot1\Yk=*u\y**u\z*coss-*u\x*sen
rot1\Zi=*u\z**u\x*coss-*u\y*sen:rot1\Zj=*u\z**u\y*coss+*u\x*sen:rot1\Zk=cos+*u\z**u\z*coss
CopyMemory(*matriz,@rot,SizeOf(D3DMATRIX))
rot\_41+vx:rot\_42+vy:rot\_43+vz
MP_EntitySetMatrix(Body,Matriz3x3xMatriz3x3(*matriz,@rot1,@rot)); <- se multiplica la matriz de inclinación del entity por la matriz rotación y se obtiene la matriz original rotada
ProcedureReturn @rot
EndIf
ProcedureReturn 0
EndProcedure
; Object0.i=MP_CreateSkySphere(20)
; Object0.i=BaseSistemaCoordenadas()
; Object0.i=MP_CreateSphere(20)
Object0.i=MP_CreateCube()
MP_EntitySetTexture(Object0,MP_ImageToTexture(0),0,0)
baseglobal.i=BaseSistemaCoordenadas():MP_PositionEntity(baseglobal,-2,0.5,0)
*rot.D3DMATRIX=MP_EntityGetMatrix(pivotcam)
rot.D3DMATRIX
rot1.D3DMATRIX
rotx.D3DMATRIX
roty.D3DMATRIX
rotz.D3DMATRIX
; MP_RotateEntity(Object0,Random(360),Random(360),Random(360),0)
MP_MouseInWindow()
MP_UseCursor(0)
While MP_KeyDown(#PB_Key_Escape)=0 And WindowEvent()<>#PB_Event_CloseWindow
mdz.f=MP_MouseDeltaWheel()/400
If MP_KeyDown(#PB_Key_Up):mdy.f=-0.01
ElseIf MP_KeyDown(#PB_Key_Down):mdy.f=0.01
ElseIf MP_KeyDown(#PB_Key_Left):mdx.f=-0.01
ElseIf MP_KeyDown(#PB_Key_Right):mdx.f=0.01
Else
mdx.f=MP_MouseDeltaX()/200:mdy.f=MP_MouseDeltaY()/200
EndIf
If MP_KeyDown(#PB_Key_LeftControl) Or MP_MouseButtonDown(1); <- mover el punto de vista
MP_TurnEntity(pivotcam,mdy.f*60,mdx.f*60,0,0)
If mdz.f
MP_EntitySetZ(maincam,MP_EntityGetZ(maincam)+mdz); <- MP_MoveEntity(cam,0,0,mdz)
EndIf
*rot=MP_EntityGetMatrix(pivotcam)
ElseIf MP_KeyDown(#PB_Key_RightShift); <- rotar el objeto sobre eje 'x' global y sobre eje 'y' global
;Para rotar la entidad alrededor del eje, en el plano XY del mundo, que define el desplazamiento del raton
;matriz de rotación sobre eje x del mundo:
rotx\_11=1:rotx\_12=0:rotx\_13=0:rotx\_14=0
rotx\_21=0:rotx\_22=Cos(-mdy):rotx\_23=Sin(-mdy):rotx\_24=0
rotx\_31=0:rotx\_32=-Sin(-mdy):rotx\_33=Cos(-mdy):rotx\_34=0
rotx\_41=0:rotx\_42=0:rotx\_43=0:rotx\_44=1
;matriz de rotación sobre eje y del mundo:
roty\_11=Cos(mdx):roty\_12=0:roty\_13=Sin(mdx):roty\_14=0
roty\_21=0:roty\_22=1:roty\_23=0:roty\_24=0
roty\_31=-Sin(mdx):roty\_32=0:roty\_33=Cos(mdx):roty\_34=0
roty\_41=0:roty\_42=0:roty\_43=0:roty\_44=1
;matriz de rotación sobre eje z del mundo:
rotz\_11=Cos(mdz):rotz\_12=0:rotz\_13=Sin(mdz):rotz\_14=0
rotz\_21=0:rotz\_22=1:rotz\_23=0:rotz\_24=0
rotz\_31=-Sin(mdz):rotz\_32=0:rotz\_33=Cos(mdz):rotz\_34=0
rotz\_41=0:rotz\_42=0:rotz\_43=0:rotz\_44=1
;obtener matriz de rotación sobre eje, en el plano XY del mundo, que define el desplazamiento del raton:
Matriz4x4xMatriz4x4(@rotx,@roty,@rot1); o lo que es lo mismo: Matriz4x4xMatriz4x4(@roty,@rotx,@rot1)
MP_EntitySetMatrix(Object0,Matriz4x4xMatriz4x4(MP_EntityGetMatrix(Object0),@rot1,@rot))
Else; <- rotar el objeto sobre eje 'x' y 'y' relativo al ojo.
;Para rotar la entidad alrededor del eje, en el plano XY del ojo, que define el desplazamiento del raton.
;El tema está en que el raton se mueve en 2 dimensiones, es decir en el plano, entonces de la entrada del raton obtenemos:
;1. de su desplazamiento vertical un vector en dirección X, cuya amplitud y sentido nos indica el ángulo a rotar alrededor de ese eje X
;2. de su desplazamiento horizontal un vector en dirección Y, cuya amplitud y sentido nos indica el ángulo a rotar alrededor de ese eje Y
;Tenemos pues un vector definido por el movimiento del ratón.
;El ojo se puede mover en el espacio del mundo y apuntar la vista hacia cualquier parte,
;por lo que el plano frontal del ojo puede variar y no coincidir con el plano XY del mundo.
;Entonces el vector que obtenemos del movimiento del ratón ha de estar contenido en el plano frontal del ojo.
;Hay que disponer el vector (mdx,mdy,mdz) sobre el plano XY de la base de coordenadas del pivotcam (plano frontal del ojo), no del mundo.
;Para ello, el vector (0,mdx,0) hay que ponerlo sobre el eje Y del plano frontal de ojo
;y el vector (mdy,0,0) hay que ponerlo sobre el eje X del plano frontal de ojo:
;Tenemos en *rot la dirección del eje X, a través del vector X-> del plano frontal del ojo ( *rot\_11,*rot\_12,*rot\_13 )
;y la dirección del eje Y, a través del vector Y-> del plano frontal del ojo ( *rot\_21,*rot\_22,*rot\_23 )
;Por tanto procedemos a obtener ambos vectores unidad:
;el colineal al eje de abscisas en el plano frontal del ojo y el colineal al eje de ordenadas en este plano:
THETA.d=Sqr(mdx.f*mdx.f+mdy.f*mdy.f+mdz.f*mdz.f)
If THETA.d>0
ux_m.d=Sqr(*rot\_11**rot\_11+*rot\_12**rot\_12+*rot\_13**rot\_13)
If ux_m.d>0
;los cosenos directores de un vector cualquiera son las coordenadas escalares de ese mismo vector con módulo unidad, es decir,
;son las proyecciones de ese vector unitario sobre cada uno de los ejes principales
ux_x.d=*rot\_11/ux_m:ux_y.d=*rot\_12/ux_m:ux_z.d=*rot\_13/ux_m; <- son los cosenos directores
;ahora multiplicando este vector unitario, por el modulo de (mdy,0,0) obtenemos ya la componente X pero en el plano frontal del ojo:
ux_x*mdy:ux_y*mdy:ux_z*mdy
EndIf
;Hacemos lo mismo para obtener la componente Y del movimiento del ratón pero en el plano frontal del ojo
uy_m.d=Sqr(*rot\_21**rot\_21+*rot\_22**rot\_22+*rot\_23**rot\_23)
If uy_m>0
;los cosenos directores de un vector cualquiera son las coordenadas escalares de ese mismo vector con módulo unidad, es decir,
;son las proyecciones de ese vector unitario sobre cada uno de los ejes principales
uy_x.d=*rot\_21/uy_m:uy_y.d=*rot\_22/uy_m:uy_z.d=*rot\_23/uy_m; <- son los cosenos directores.
;ahora multiplicando este vector unitario, por el modulo de (0,mdx,0) obtenemos ya la componente Y pero en el plano frontal del ojo:
uy_x*mdx:uy_y*mdx:uy_z*mdx
EndIf
;Hacemos lo mismo para obtener la componente Z del movimiento del ratón pero en el plano frontal del ojo
uz_m.d=Sqr(*rot\_31**rot\_31+*rot\_32**rot\_32+*rot\_33**rot\_33)
If uz_m>0
;los cosenos directores de un vector cualquiera son las coordenadas escalares de ese mismo vector con módulo unidad, es decir,
;son las proyecciones de ese vector unitario sobre cada uno de los ejes principales
uz_x.d=*rot\_31/uz_m:uz_y.d=*rot\_32/uz_m:uz_z.d=*rot\_33/uz_m; <- son los cosenos directores.
;ahora multiplicando este vector unitario, por el modulo de (0,0,mdz) obtenemos ya la componente Z pero en el plano frontal del ojo:
uz_x*mdz:uz_y*mdz:uz_z*mdz
EndIf
;Para obtener el vector que define la recta alrededor de la cual ha de rotar el objeto, basta con sumar esas 2 componentes obtenidas,
;y dado que ambas componentes están contenidas en el plano frontal del ojo, la suma de ambas también lo estará:
u.Vector3D
u\x=ux_x.d+uy_x.d+uz_x.d:u\y=ux_y.d+uy_y.d+uz_y.d:u\z=ux_z.d+uy_z.d+uz_z.d
If MP_KeyDown(#PB_Key_LeftShift)=0; <- METODO MIO
Turn_Body_by_Angle_adding(Object0.i,@u.Vector3D,0,0.0,0.0,0.0)
Else ; METODO 2:
;el módulo del vector original en el plano XY del mundo (THETA) es el mismo al vector rotado al plano XY frontal del ojo, así que: Sqr(u\x*u\x+u\y*u\y+u\z*u\z) = THETA
;Convertimos este vector en unitario:
u\x/THETA:u\y/THETA:u\z/THETA
MatrizRotacionaldeunAngulodadoalrededordeunejedefinidoporunvectorunidad(Object0.i,@u.Vector3D,THETA,0,0.0,0.0,0.0)
EndIf
EndIf
EndIf
MP_RenderWorld()
MP_Flip():Delay(8)
Wend
Moving the mouse can rotate the object. With left CTRL + mouse moving orbitates the eye over the object.
The program is able to perform the object rotation ALWAYS over the eye view plane, this is, with the rotation axis contained inside de front view plane.
https://mega.nz/#!QpgSVKDB!HNlntXQCuwNF ... cjAwvEzlhE
In that code, i just replaced conversion functions (quaternion--->rotation matrix) and viceversa, in order it works in the native PB.
Result:
No success.
Previous MP3D code converted to PB native code. Here can see the used functions conversions for quaternion--->rotation matrix and viceversa:
Code: Select all
; Rota una entidad sobre su centro geométrico (rotación intrínseca si ese centro corresponde con su centro de masas). Diciembre 2014
;/ inits
Global pantallacompleta.b=0,Titulo$="Par secundario en los cuerpos celestes"
Select MessageRequester("Pantalla para graficos 3D:","¿Usar pantalla completa?",#PB_MessageRequester_YesNoCancel)
Case #PB_MessageRequester_Yes:pantallacompleta.b=1
Case #PB_MessageRequester_Cancel:End
EndSelect
inicio:
If ExamineDesktops()=0:End:EndIf
Global bitplanes.a=DesktopDepth(0),FRX.u=DesktopWidth(0),FRY.u=DesktopHeight(0),RX.u=FRX,RY.u=FRY,FrecuenciadeMuestreo.u=60
If pantallacompleta
RX=FRX:RY=FRY
Else
If FRX<1280 Or FRY<720:RX=FRX*2/3:RY=FRY*2/3:Else:RX=1280:RY=720:EndIf
EndIf
If InitEngine3D()=0
MessageRequester("Error","The 3D Engine can't be initialized",0):End
EndIf
;AntialiasingMode(#PB_AntialiasingMode_None)
;AntialiasingMode(#PB_AntialiasingMode_x2)
AntialiasingMode(#PB_AntialiasingMode_x4)
;AntialiasingMode(#PB_AntialiasingMode_x6)
;
InitSprite():InitKeyboard():InitMouse()
If pantallacompleta.b=2
OpenScreen(RX,RY,bitplanes.a,Titulo$,#PB_Screen_WaitSynchronization,FrecuenciadeMuestreo.u)
Else
OpenWindow(0,0,0,RX,RY,Titulo$,#PB_Window_BorderLess|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,RX,RY,1,0,0,#PB_Screen_WaitSynchronization)
EndIf
Add3DArchive(#PB_Compiler_Home+"examples/3D/Data/Textures",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"examples/3D/Data/fonts",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"examples/3D/Data/Models",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"examples/3D/Data/Packs/desert.zip",#PB_3DArchive_Zip)
Add3DArchive(#PB_Compiler_Home+"examples/3D/Data/Scripts",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"examples/3D/Data/Packs/skybox.zip",#PB_3DArchive_Zip)
Add3DArchive(#PB_Compiler_Home+"examples/3D/Data/GUI",#PB_3DArchive_FileSystem)
Add3DArchive("media/",#PB_3DArchive_FileSystem)
Add3DArchive("media/cielo1.zip",#PB_3DArchive_Zip)
Add3DArchive("media/cielo2.zip",#PB_3DArchive_Zip)
Add3DArchive("media/cielo3.zip",#PB_3DArchive_Zip)
Add3DArchive("media/cielo4.zip",#PB_3DArchive_Zip)
Parse3DScripts()
; Lo que sigue es una plantilla de los elementos de un mundo 3D que ofrecen las bibliotecas nativas el PureBasic:
Enumeration; Camaras
#Camara
EndEnumeration
Enumeration; Luces
#Luz
EndEnumeration
Enumeration; Texturas
#Textura
EndEnumeration
Enumeration; Materiales
#Material
EndEnumeration
Enumeration; Mallas
#Object0malla
EndEnumeration
Enumeration; Entidades
#Object0
EndEnumeration
Enumeration; Nodos
#Nodo
#Pivotcam
EndEnumeration
Global ventanaprincipalx.l=10,ventanaprincipaly.l=10,ventanaprincipalw.l=RX/2.5,ventanaprincipalh.l=RY/2
;\
CreateLight(#luz,$EEEEEE,4,4,2,#PB_Light_Point)
CreateCamera(#Camara,0,0,100,100):CreateNode(#Pivotcam,0,0,0):AttachNodeObject(#Pivotcam,CameraID(#Camara)):CameraRange(#Camara,0.1,10000):CameraBackColor(#Camara,$181911)
MoveCamera(#Camara,0,0,3,#PB_Absolute)
Structure D3DMATRIX
StructureUnion
_11.f
Xi.f
EndStructureUnion
StructureUnion
_12.f
Xj.f
EndStructureUnion
StructureUnion
_13.f
Xk.f
EndStructureUnion
_14.f
StructureUnion
_21.f
Yi.f
EndStructureUnion
StructureUnion
_22.f
Yj.f
EndStructureUnion
StructureUnion
_23.f
Yk.f
EndStructureUnion
_24.f
StructureUnion
_31.f
Zi.f
EndStructureUnion
StructureUnion
_32.f
Zj.f
EndStructureUnion
StructureUnion
_33.f
Zk.f
EndStructureUnion
_34.f
StructureUnion
_41.f
Pi.f
EndStructureUnion
StructureUnion
_42.f
Pj.f
EndStructureUnion
StructureUnion
_43.f
Pk.f
EndStructureUnion
_44.f
EndStructure
Structure D3DXVECTOR3
x.f
y.f
z.f
EndStructure
Structure Vector3D Extends D3DXVECTOR3
m.f;<-length(modulo)
EndStructure
Macro ProductoEscalar(a,b,ax=x,ay=y,az=z,bx=x,by=y,bz=z)
(a#\ax#*b#\bx#+a#\ay#*b#\by#+a#\az#*b#\bz#)
EndMacro
Macro getmodulo(v,vx=x,vy=y,vz=z)
(Sqr#ProductoEscalar(v#,v#,vx#,vy#,vz#,vx#,vy#,vz#))
EndMacro
Procedure.i EntityGetMatrixFromQuaternion(objeto.i,*matriz.D3DMATRIX,modo.i=#PB_Absolute)
FetchOrientation(objeto,modo):Protected x.f=GetX(),y.f=GetY(),z.f=GetZ(),w.f=GetW(),s.f=2.0/(x*x+y*y+z*z+w*w)
*matriz\Xi=1-s*(y*y+z*z); <- 0,0
*matriz\Xj=s*(x*y-z*w); <- 0,1
*matriz\Xk=s*(x*z+y*w); <- 0,2
*matriz\Yi=s*(x*y+z*w); <- 1,0
*matriz\Yj=1-s*(x*x+z*z); <- 1,1
*matriz\Yk=s*(y*z-x*w); <- 1,2
*matriz\Zi=s*(x*z-y*w); <- 2,0
*matriz\Zj=s*(y*z+x*w); <- 2,1
*matriz\Zk=1-s*(x*x+y*y); <- 2,2
ProcedureReturn *matriz
EndProcedure
Procedure EntityGetQuaternionFromMatrix1(objeto.i,*matriz.D3DMATRIX)
Protected x.f,y.f,z.f,w.f
w=Sqr(*matriz\Xi+*matriz\Yj+*matriz\Zk+1)/2
x=Sign(*matriz\Zj-*matriz\Yk)*Sqr(*matriz\Xi-*matriz\Yj-*matriz\Zk+1)/2
y=Sign(*matriz\Xk-*matriz\Zi)*Sqr(*matriz\Yj-*matriz\Xi-*matriz\Zk+1)/2
z=Sign(*matriz\Yi-*matriz\Xj)*Sqr(*matriz\Zk-*matriz\Xi-*matriz\Yj+1)/2
SetOrientation(objeto,x,y,z,w)
EndProcedure
Procedure EntityGetQuaternionFromMatrix(objeto.i,*matriz.D3DMATRIX)
Protected x.f,y.f,z.f,w.f,tr.f=*matriz\Xi+*matriz\Yj+*matriz\Zk,S.f
If tr>0
S=Sqr(tr+1)*2; S=4*w
w=S/4
x=(*matriz\Zj-*matriz\Yk)/S
y=(*matriz\Xk-*matriz\Zi)/S
z=(*matriz\Yi-*matriz\Xj)/S
ElseIf *matriz\Xi>*matriz\Yj And *matriz\Xi>*matriz\Zk
S=Sqr(1+*matriz\Xi-*matriz\Yj-*matriz\Zk)*2; S=4*x
w=(*matriz\Zj-*matriz\Yk)/S
x=S/4
y=(*matriz\Xj+*matriz\Yi)/S
z=(*matriz\Xk+*matriz\Zi)/S
ElseIf *matriz\Yj>*matriz\Zk
S=Sqr(1+*matriz\Yj-*matriz\Xi-*matriz\Zk)*2; S=4*y
w=(*matriz\Xk-*matriz\Zi)/S
x=(*matriz\Xj+*matriz\Yi)/S
y=S/4
z=(*matriz\Yk+*matriz\Zj)/S
Else
S=Sqr(1+*matriz\Zk-*matriz\Xi-*matriz\Yj)*2; S=4*z
w=(*matriz\Yi-*matriz\Xj)/S
x=(*matriz\Xk+*matriz\Zi)/S
y=(*matriz\Yk+*matriz\Zj)/S
z=S/4
EndIf
SetOrientation(objeto,x,y,z,w)
EndProcedure
Procedure.i Matriz3x3xMatriz3x3(*a.D3DMATRIX,*b.D3DMATRIX,*o.D3DMATRIX); producto
*o\_11=*a\_11**b\_11+*a\_12**b\_21+*a\_13**b\_31:*o\_12=*a\_11**b\_12+*a\_12**b\_22+*a\_13**b\_32:*o\_13=*a\_11**b\_13+*a\_12**b\_23+*a\_13**b\_33
*o\_21=*a\_21**b\_11+*a\_22**b\_21+*a\_23**b\_31:*o\_22=*a\_21**b\_12+*a\_22**b\_22+*a\_23**b\_32:*o\_23=*a\_21**b\_13+*a\_22**b\_23+*a\_23**b\_33
*o\_31=*a\_31**b\_11+*a\_32**b\_21+*a\_33**b\_31:*o\_32=*a\_31**b\_12+*a\_32**b\_22+*a\_33**b\_32:*o\_33=*a\_31**b\_13+*a\_32**b\_23+*a\_33**b\_33
ProcedureReturn *o
EndProcedure
Procedure.i Matriz4x4xMatriz4x4(*a.D3DMATRIX,*b.D3DMATRIX,*o.D3DMATRIX); producto
*o\_11=*a\_11**b\_11+*a\_12**b\_21+*a\_13**b\_31+*a\_14**b\_41:*o\_12=*a\_11**b\_12+*a\_12**b\_22+*a\_13**b\_32+*a\_14**b\_42:*o\_13=*a\_11**b\_13+*a\_12**b\_23+*a\_13**b\_33+*a\_14**b\_43:*o\_14=*a\_11**b\_14+*a\_12**b\_24+*a\_13**b\_34+*a\_14**b\_44
*o\_21=*a\_21**b\_11+*a\_22**b\_21+*a\_23**b\_31+*a\_24**b\_41:*o\_22=*a\_21**b\_12+*a\_22**b\_22+*a\_23**b\_32+*a\_24**b\_42:*o\_23=*a\_21**b\_13+*a\_22**b\_23+*a\_23**b\_33+*a\_24**b\_43:*o\_24=*a\_21**b\_14+*a\_22**b\_24+*a\_23**b\_34+*a\_24**b\_44
*o\_31=*a\_31**b\_11+*a\_32**b\_21+*a\_33**b\_31+*a\_34**b\_41:*o\_32=*a\_31**b\_12+*a\_32**b\_22+*a\_33**b\_32+*a\_34**b\_42:*o\_33=*a\_31**b\_13+*a\_32**b\_23+*a\_33**b\_33+*a\_34**b\_43:*o\_34=*a\_31**b\_14+*a\_32**b\_24+*a\_33**b\_34+*a\_34**b\_44
*o\_41=*a\_41**b\_11+*a\_42**b\_21+*a\_43**b\_31+*a\_44**b\_41:*o\_42=*a\_41**b\_12+*a\_42**b\_22+*a\_43**b\_32+*a\_44**b\_42:*o\_43=*a\_41**b\_13+*a\_42**b\_23+*a\_43**b\_33+*a\_44**b\_43:*o\_44=*a\_41**b\_14+*a\_42**b\_24+*a\_43**b\_34+*a\_44**b\_44
ProcedureReturn *o
EndProcedure
Procedure.i MatrizRotacionaldeunAngulodadoalrededordeunejedefinidoporunvectorunidad(Body.i,*u.Vector3D,A.f,*matriz.D3DMATRIX); <- usar esta cuando disponemos de antemano (antes de llamar a la función) del módulo angular y del vector unitario del ángulo
;Rotar un entity un ángulo dado cuya dirección viene dada por el vector unidad '*u.Vector3D' y además por un módulo 'A'
Protected rot.D3DMATRIX,rot1.D3DMATRIX,cos.f,sen.f,coss.f
If A
cos=Cos(A):sen=Sin(A):coss=1.0-cos
;Matriz de Rotación de un ángulo dado 'A' alrededor de un eje dado definido por el vector unidad (*u\x,*u\y,*u\z)
rot1\Xi=cos+*u\x**u\x*coss:rot1\Xj=*u\x**u\y*coss-*u\z*sen:rot1\Xk=*u\x**u\z*coss+*u\y*sen
rot1\Yi=*u\y**u\x*coss+*u\z*sen:rot1\Yj=cos+*u\y**u\y*coss:rot1\Yk=*u\y**u\z*coss-*u\x*sen
rot1\Zi=*u\z**u\x*coss-*u\y*sen:rot1\Zj=*u\z**u\y*coss+*u\x*sen:rot1\Zk=cos+*u\z**u\z*coss
CopyMemory(*matriz,@rot,SizeOf(D3DMATRIX))
EntityGetQuaternionFromMatrix(Body,Matriz3x3xMatriz3x3(*matriz,@rot1,@rot)); <- se multiplica la matriz de inclinación del entity por la matriz rotación y se obtiene la matriz original rotada
ProcedureReturn @rot
EndIf
ProcedureReturn 0
EndProcedure
Procedure.b KeyEdgeDetection(key.a)
Static pka.a
If KeyboardPushed(key);<-if current key status is PUSHED
If pka=0:pka=key:ProcedureReturn 1:EndIf;<-if previous key status was NOT PUSHED, then assign previous state to current one, and EXIT.
ElseIf pka=key;<-else (if previous key status was PUSHED and current key status is NOT PUSHED):
pka=0;:ProcedureReturn -1;<-set previous key status to NOT PUSHED.
EndIf
ProcedureReturn 0
EndProcedure
CreateCube(#Object0malla,1)
LoadTexture(#textura,"soil_wall.jpg")
CreateMaterial(#material,TextureID(#textura))
CreateEntity(#Object0,MeshID(#Object0malla),MaterialID(#material),0,0,0)
; BaseSistemaCoordenadas(#baseglobal):MoveEntity(#baseglobal,-2,0.5,0,#PB_Absolute)
matrizpivot.D3DMATRIX
EntityGetMatrixFromQuaternion(NodeID(#pivotcam),@matrizpivot)
matrizobjeto.D3DMATRIX
EntityGetMatrixFromQuaternion(EntityID(#Object0),@matrizobjeto)
rot.D3DMATRIX
rot1.D3DMATRIX
rotx.D3DMATRIX
roty.D3DMATRIX
rotz.D3DMATRIX
Macro TeclaControldecamara(tecla=LeftControl)
If KeyEdgeDetection(#PB_Key_#tecla#); <- inicia control camara
pasocam.f=0.001:pasocamincr.f=0.0001
ElseIf KeyboardReleased(#PB_Key_#tecla#)
ElseIf KeyboardPushed(#PB_Key_#tecla#); <- mover el punto de vista
;para desplazar la camara hacia delante, atras, arriba, abajo, izq o der
If mdx Or mdy Or mdz
If mmb.b
MoveNode(#Pivotcam,mdx,-mdy,0,#PB_Local); o MoveCamera(0,mdx,-mdy,0,#PB_Local) o MoveCamera(0,mdx,-mdy,0,#PB_Relative)
Else
RotateNode(#Pivotcam,-mdy*60,-mdx*60,0,#PB_Relative)
If mdz
MoveCamera(#Camara,0,0,-mdz,#PB_Relative)
EndIf
EndIf
ElseIf KeyboardPushed(#PB_Key_Add)
MoveCamera(#Camara,0,0,-pasocam,#PB_Relative)
pasocam+pasocamincr
ElseIf KeyboardPushed(#PB_Key_Subtract)
MoveCamera(#Camara,0,0,pasocam,#PB_Relative)
pasocam+pasocamincr
ElseIf KeyboardPushed(#PB_Key_Pad8)
MoveCamera(#Camara,0,pasocam,0,#PB_Relative)
pasocam+pasocamincr
ElseIf KeyboardPushed(#PB_Key_Pad2)
MoveCamera(#Camara,0,-pasocam,0,#PB_Relative)
pasocam+pasocamincr
ElseIf KeyboardPushed(#PB_Key_Pad6)
MoveCamera(#Camara,pasocam,0,0,#PB_Relative)
pasocam+pasocamincr
ElseIf KeyboardPushed(#PB_Key_Pad4)
MoveCamera(#Camara,-pasocam,0,0,#PB_Relative)
pasocam+pasocamincr
ElseIf KeyboardPushed(#PB_Key_Pad1)
RotateNode(#Pivotcam,0,-0.5,0,#PB_Relative)
ElseIf KeyboardPushed(#PB_Key_Pad7)
RotateNode(#Pivotcam,0,0.5,0,#PB_Relative)
ElseIf KeyboardPushed(#PB_Key_Pad3) Or lmb.b
RotateNode(#Pivotcam,0,0,-0.5,#PB_Relative)
ElseIf KeyboardPushed(#PB_Key_Pad9) Or rmb.b
RotateNode(#Pivotcam,0,0,0.5,#PB_Relative)
EndIf
EndMacro
Repeat
ExamineMouse():ExamineKeyboard()
WaitWindowEvent()
CursorX.f=MouseX():CursorY.f=MouseY():lmb.b=MouseButton(#PB_MouseButton_Left):rmb.b=MouseButton(#PB_MouseButton_Right):mmb.b=MouseButton(#PB_MouseButton_Middle)
mdx.f=MouseDeltaX()/200:mdy.f=MouseDeltaY()/200:mdz.f=MouseWheel()/20
If KeyboardPushed(#PB_Key_Up):mdy.f=-0.01
ElseIf KeyboardPushed(#PB_Key_Down):mdy.f=0.01
ElseIf KeyboardPushed(#PB_Key_Left):mdx.f=-0.01
ElseIf KeyboardPushed(#PB_Key_Right):mdx.f=0.01
EndIf
TeclaControldecamara(LeftControl)
ElseIf KeyboardPushed(#PB_Key_RightShift); <- rotar el objeto sobre eje 'x' global y sobre eje 'y' global
;Para rotar la entidad alrededor del eje, en el plano XY del mundo, que define el desplazamiento del raton
;matriz de rotación sobre eje x del mundo:
rotx\_11=1:rotx\_12=0:rotx\_13=0:rotx\_14=0
rotx\_21=0:rotx\_22=Cos(-mdy):rotx\_23=Sin(-mdy):rotx\_24=0
rotx\_31=0:rotx\_32=-Sin(-mdy):rotx\_33=Cos(-mdy):rotx\_34=0
rotx\_41=0:rotx\_42=0:rotx\_43=0:rotx\_44=1
;matriz de rotación sobre eje y del mundo:
roty\_11=Cos(mdx):roty\_12=0:roty\_13=Sin(mdx):roty\_14=0
roty\_21=0:roty\_22=1:roty\_23=0:roty\_24=0
roty\_31=-Sin(mdx):roty\_32=0:roty\_33=Cos(mdx):roty\_34=0
roty\_41=0:roty\_42=0:roty\_43=0:roty\_44=1
;matriz de rotación sobre eje z del mundo:
rotz\_11=Cos(mdz):rotz\_12=0:rotz\_13=Sin(mdz):rotz\_14=0
rotz\_21=0:rotz\_22=1:rotz\_23=0:rotz\_24=0
rotz\_31=-Sin(mdz):rotz\_32=0:rotz\_33=Cos(mdz):rotz\_34=0
rotz\_41=0:rotz\_42=0:rotz\_43=0:rotz\_44=1
;obtener matriz de rotación sobre eje, en el plano XY del mundo, que define el desplazamiento del raton:
Matriz4x4xMatriz4x4(@rotx,@roty,@rot1); o lo que es lo mismo: Matriz4x4xMatriz4x4(@roty,@rotx,@rot1)
EntityGetQuaternionFromMatrix(EntityID(#Object0),Matriz4x4xMatriz4x4(EntityGetMatrixFromQuaternion(EntityID(#Object0),@matrizobjeto),@rot1,@rot))
Else; <- rotar el objeto sobre eje 'x' y 'y' relativo al ojo.
EntityGetMatrixFromQuaternion(NodeID(#pivotcam),@matrizpivot)
;Para rotar la entidad alrededor del eje, en el plano XY del ojo, que define el desplazamiento del raton.
;El tema está en que el raton se mueve en 2 dimensiones, es decir en el plano, entonces de la entrada del raton obtenemos:
;1. de su desplazamiento vertical un vector en dirección X, cuya amplitud y sentido nos indica el ángulo a rotar alrededor de ese eje X
;2. de su desplazamiento horizontal un vector en dirección Y, cuya amplitud y sentido nos indica el ángulo a rotar alrededor de ese eje Y
;Tenemos pues un vector definido por el movimiento del ratón.
;El ojo se puede mover en el espacio del mundo y apuntar la vista hacia cualquier parte,
;por lo que el plano frontal del ojo puede variar y no coincidir con el plano XY del mundo.
;Entonces el vector que obtenemos del movimiento del ratón ha de estar contenido en el plano frontal del ojo.
;Hay que disponer el vector (mdx,mdy,mdz) sobre el plano XY de la base de coordenadas del pivotcam (plano frontal del ojo), no del mundo.
;Para ello, el vector (0,mdx,0) hay que ponerlo sobre el eje Y del plano frontal de ojo
;y el vector (mdy,0,0) hay que ponerlo sobre el eje X del plano frontal de ojo:
;Tenemos en matrizpivot la dirección del eje X, a través del vector X-> del plano frontal del ojo ( matrizpivot\_11,matrizpivot\_12,matrizpivot\_13 )
;y la dirección del eje Y, a través del vector Y-> del plano frontal del ojo ( matrizpivot\_21,matrizpivot\_22,matrizpivot\_23 )
;Por tanto procedemos a obtener ambos vectores unidad:
;el colineal al eje de abscisas en el plano frontal del ojo y el colineal al eje de ordenadas en este plano:
THETA.d=Sqr(mdx.f*mdx.f+mdy.f*mdy.f+mdz.f*mdz.f)
If THETA.d>0
ux_m.d=Sqr(matrizpivot\_11*matrizpivot\_11+matrizpivot\_12*matrizpivot\_12+matrizpivot\_13*matrizpivot\_13)
If ux_m.d>0
;los cosenos directores de un vector cualquiera son las coordenadas escalares de ese mismo vector con módulo unidad, es decir,
;son las proyecciones de ese vector unitario sobre cada uno de los ejes principales
ux_x.d=matrizpivot\_11/ux_m:ux_y.d=matrizpivot\_12/ux_m:ux_z.d=matrizpivot\_13/ux_m; <- son los cosenos directores
;ahora multiplicando este vector unitario, por el modulo de (mdy,0,0) obtenemos ya la componente X pero en el plano frontal del ojo:
ux_x*mdy:ux_y*mdy:ux_z*mdy
EndIf
;Hacemos lo mismo para obtener la componente Y del movimiento del ratón pero en el plano frontal del ojo
uy_m.d=Sqr(matrizpivot\_21*matrizpivot\_21+matrizpivot\_22*matrizpivot\_22+matrizpivot\_23*matrizpivot\_23)
If uy_m>0
;los cosenos directores de un vector cualquiera son las coordenadas escalares de ese mismo vector con módulo unidad, es decir,
;son las proyecciones de ese vector unitario sobre cada uno de los ejes principales
uy_x.d=matrizpivot\_21/uy_m:uy_y.d=matrizpivot\_22/uy_m:uy_z.d=matrizpivot\_23/uy_m; <- son los cosenos directores.
;ahora multiplicando este vector unitario, por el modulo de (0,mdx,0) obtenemos ya la componente Y pero en el plano frontal del ojo:
uy_x*mdx:uy_y*mdx:uy_z*mdx
EndIf
;Hacemos lo mismo para obtener la componente Z del movimiento del ratón pero en el plano frontal del ojo
uz_m.d=Sqr(matrizpivot\_31*matrizpivot\_31+matrizpivot\_32*matrizpivot\_32+matrizpivot\_33*matrizpivot\_33)
If uz_m>0
;los cosenos directores de un vector cualquiera son las coordenadas escalares de ese mismo vector con módulo unidad, es decir,
;son las proyecciones de ese vector unitario sobre cada uno de los ejes principales
uz_x.d=matrizpivot\_31/uz_m:uz_y.d=matrizpivot\_32/uz_m:uz_z.d=matrizpivot\_33/uz_m; <- son los cosenos directores.
;ahora multiplicando este vector unitario, por el modulo de (0,0,mdz) obtenemos ya la componente Z pero en el plano frontal del ojo:
uz_x*mdz:uz_y*mdz:uz_z*mdz
EndIf
;Para obtener el vector que define la recta alrededor de la cual ha de rotar el objeto, basta con sumar esas 2 componentes obtenidas,
;y dado que ambas componentes están contenidas en el plano frontal del ojo, la suma de ambas también lo estará:
u.Vector3D
u\x=ux_x.d+uy_x.d+uz_x.d:u\y=ux_y.d+uy_y.d+uz_y.d:u\z=ux_z.d+uy_z.d+uz_z.d
;el módulo del vector original en el plano XY del mundo (THETA) es el mismo al vector rotado al plano XY frontal del ojo, así que: Sqr(u\x*u\x+u\y*u\y+u\z*u\z) = THETA
;Convertimos este vector en unitario:
u\x/THETA:u\y/THETA:u\z/THETA
EntityGetMatrixFromQuaternion(EntityID(#Object0),@matrizobjeto)
MatrizRotacionaldeunAngulodadoalrededordeunejedefinidoporunvectorunidad(EntityID(#Object0),@u.Vector3D,THETA,@matrizobjeto)
;Beep_(200,5)
EndIf
EndIf
TimeSinceLastFrame.i=RenderWorld(50)
; If IsSprite(#Sprite2D):showhelpsprite():EndIf
FlipBuffers():Delay(9)
Until KeyboardPushed(#PB_Key_Escape)
http://www.zeitgeistmovie.com
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
Re: Simple function to rotate 3D objects over given axis
Is it what you are looking for ?
Code: Select all
#CameraSpeed = 1
IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"
Define.f MouseX, MouseY
If InitEngine3D()
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/skybox.zip", #PB_3DArchive_Zip)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts", #PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite()
InitKeyboard()
InitMouse()
Global Attached = #False
If Screen3DRequester()
CreateMaterial(0, LoadTexture(0, "r2skin.jpg"))
CreateCube(0,1)
CreateEntity(0, MeshID(0), MaterialID(0))
LoadMesh(1, "axes.mesh")
CreateMaterial(1, LoadTexture(1, "axes.png"))
CreateEntity(1, MeshID(1), MaterialID(1), -1, 1, -1)
ScaleEntity(1,0.1,0.1,0.1)
SkyBox("stevecube.jpg")
AttachEntityObject(0,"",EntityID(1))
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0, 5, 5, 5, #PB_Absolute)
CameraLookAt(0, 0, 0, 0)
Repeat
Screen3DEvents()
ExamineMouse()
MouseX = -MouseDeltaX() * #CameraSpeed * 0.5
MouseY = -MouseDeltaY() * #CameraSpeed * 0.5
ExamineKeyboard()
RotateEntity(0, Mousey, Mousex, 0, #PB_Relative)
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
EndIf
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End
Please correct my english
http://purebasic.developpez.com/
http://purebasic.developpez.com/
- pf shadoko
- Enthusiast
- Posts: 291
- Joined: Thu Jul 09, 2015 9:07 am
Re: Simple function to rotate 3D objects over given axis
I wanted to add the parameter w to the Entitydirection function, but I don't see how to specify the origin of the angle
don't forget the Engine3D lib functions:
Yaw, pitch and roll, usable with all 3d objects
maybe this example will meet your needs
don't forget the Engine3D lib functions:
Yaw, pitch and roll, usable with all 3d objects
maybe this example will meet your needs
Code: Select all
Define.f rz,dx,dy,dz,a,ya, r=0.8
InitEngine3D():InitSprite():InitKeyboard():InitMouse()
ExamineDesktops()
ex=DesktopWidth(0)*r
ey=DesktopHeight(0)*r
OpenWindow(0, 0, 0,ex,ey, "Test 3d >>> cursor up/down - Esc to quit",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, ex, ey, 0, 0, 0)
WorldShadows(#PB_Shadow_Additive)
CreateLight(0,$888888, 5000, 3000, 2000)
AmbientColor($777777)
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0,0,10,-20)
CameraLookAt(0,0,0,0)
CameraBackColor(0,$888888)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
CreateMaterial(0, LoadTexture(0, "MRAMOR6X6.jpg"))
CreateMaterial(1, LoadTexture(1, "flaretrail.png"))
CreatePlane(0,100,100,16,16,16,16)
CreateEntity(0,MeshID(0),MaterialID(0),0,0,0)
CreateCube(1,1):TransformMesh(1,0,2,0,1,4,2,0,0,0)
CreateEntity(1,MeshID(1),MaterialID(1),0,0,0)
Macro KBdep(k1,k2)
(Bool(KeyboardPushed(k1)<>0)-Bool(KeyboardPushed(k2)<>0))
EndMacro
Repeat
WindowEvent()
ExamineMouse()
ExamineKeyboard()
dx+KBdep(#PB_Key_Left,#PB_Key_Right)*0.02
dy=2
dz+KBdep(#PB_Key_Up,#PB_Key_Down)*0.02
rz+KBdep(#PB_Key_PageUp,#PB_Key_PageDown)*2
MoveEntity(1,0,0,0,#PB_Absolute)
EntityDirection(1,dx,dy,dz,#PB_World,1)
ya=EntityYaw(1):Yaw(EntityID(1),-ya+rz,#PB_Local)
;ya=EntityYaw(1):Yaw(EntityID(1),rz,#PB_World)
Debug rz
CreateLine3D(100,0,0,0,$ff00,dx*4,dy*4,dz*4,$ff)
CameraLookAt(0,EntityX(1),EntityY(1),EntityZ(1))
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
- Psychophanta
- Addict
- Posts: 4997
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Lípetsk, Russian Federation
- Contact:
Re: Simple function to rotate 3D objects over given axis
@Comtois: no dear, that's not. Can't you see the behaviour of the .exe I pointed to?
@pf shadoko: your tip hangs here.
As soon as I have a functional tip, I will post. At the moment i continue with no success.
@pf shadoko: your tip hangs here.
As soon as I have a functional tip, I will post. At the moment i continue with no success.
http://www.zeitgeistmovie.com
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
Re: Simple function to rotate 3D objects over given axis
Well my code does the same behaviour (just add DetachEntityObject() to be more complete)Psychophanta wrote:@Comtois: no dear, that's not. Can't you see the behaviour of the .exe I pointed to?
I do not understand what difference there is
Please correct my english
http://purebasic.developpez.com/
http://purebasic.developpez.com/
Re: Simple function to rotate 3D objects over given axis
One should be able to rotate an entity around any axis : in a local (object) system or in a global system, for example to work with multiples cameras and points of view.
More than that, one should be able to transform any entity with any referential. For example, to scale/move/rotate several objects relatively to any defined axis : useful if you want to create a 3D tool.
If you create working EntityFixedYawAxis(), EntityFixedRollAxis() and EntityFixedPitchAxis() functions, it should be OK for rotation, but if would be more complete to add a function to give full control with something like a "pivot point" or "referential".
I think the way to go is to complete the "node" functions. There's several relative possibilities with MoveEntity(), why no scale and rotate ?
Edit: to simplify and typo
More than that, one should be able to transform any entity with any referential. For example, to scale/move/rotate several objects relatively to any defined axis : useful if you want to create a 3D tool.
If you create working EntityFixedYawAxis(), EntityFixedRollAxis() and EntityFixedPitchAxis() functions, it should be OK for rotation, but if would be more complete to add a function to give full control with something like a "pivot point" or "referential".
I think the way to go is to complete the "node" functions. There's several relative possibilities with MoveEntity(), why no scale and rotate ?
Edit: to simplify and typo
Last edited by djes on Mon Feb 18, 2019 1:07 pm, edited 2 times in total.
- pf shadoko
- Enthusiast
- Posts: 291
- Joined: Thu Jul 09, 2015 9:07 am
Re: Simple function to rotate 3D objects over given axis
Sorry, I didn't understand your answer.
I forgot to mention that, in my sample, you can change the direction with the arrow keys, and w with PageUp and PageDown
I forgot to mention that, in my sample, you can change the direction with the arrow keys, and w with PageUp and PageDown
Re: Simple function to rotate 3D objects over given axis
The entity in your example doesn't rotate around fixed "world" axis. I've edited my previous post.pf shadoko wrote:Sorry, I didn't understand your answer.
I forgot to mention that, in my sample, you can change the direction with the arrow keys, and w with PageUp and PageDown
- Psychophanta
- Addict
- Posts: 4997
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Lípetsk, Russian Federation
- Contact:
Re: Simple function to rotate 3D objects over given axis
Comtois, really?Comtois wrote:Well my code does the same behaviour (just add DetachEntityObject() to be more complete)Psychophanta wrote:@Comtois: no dear, that's not. Can't you see the behaviour of the .exe I pointed to?
I do not understand what difference there is
Are you joking?
Don't you really understand?
Please answer, because i don't believe. And sorry.
Djes DOES understand perfectly, it is so simple in fact. And i sent you tips and an executeable.
To rotate around a given "world" axis. Sorry but, is it so hard to get?
None of your tip are accepting a world axis.
May be my tips are not enough clear, because they accept axis contained in the front plane of the view (the orientation of the node where the camera is attached to), which is an axis depending on the x AND y of the mouse move, but ALWAYS contained in the front plane of the camera view.
Well, please allow me to repeat the above post in other words:
I know to rotate an element around a given arbitrary "world" axis, using its orientation matrix and the rotation matrix which i derive from just an unique vector (tip above ilustrates), which i call the angle-vector, because in a single vector is contained the rotation axis, the amount angle to rotate and the direction of the rotation (this is just the Euler law of rotation).
But: Making use of the native PB 3D engine i am not able to do it: even I tried converting the quaternion to the rotation-matrix and viceversa (the other tip above), there is no success.
I know how does work a quaternion, and i am working on a funtion to do that. I know a quaternion from an object is just its current orientation, so to rotate the object in any axis, we must to perform some calculations starting from its current orientation, ... which is a real headache, because a quaternion is not exactly a 3D vector, but a rare thing to me, and i am in use to work with vectors and matrix.
At the moment, there is at least one thing very sure: the resources of computing when working with quaternions IS NOT lower than working with matrix, as is stated in some texts.
Thanks!
(Of course @djes, thanks, great)
http://www.zeitgeistmovie.com
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
Re: Simple function to rotate 3D objects over given axis
And now spheres turn around world axis (code show 2 ways) ? Or i dont understand again ?
Code: Select all
Structure Vector3
x.f
y.f
z.f
EndStructure
Structure Quaternion
x.f
y.f
z.f
w.f
EndStructure
#CameraSpeed = 1
IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"
Define.f MouseX, MouseY, Angle
Define.Vector3 Axis, AxisN
Define.Quaternion Q
Declare QuaternionFromAngleAxis (*Q.Quaternion, Angle.f, *Axis.Vector3)
Declare.f normalise(*V.Vector3)
Axis\x = -3
Axis\y = 5
Axis\z = 2
CopyStructure(@Axis, @AxisN, Vector3)
normalise(@AxisN)
If InitEngine3D()
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/skybox.zip", #PB_3DArchive_Zip)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts", #PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite()
InitKeyboard()
InitMouse()
If Screen3DRequester()
CreateMaterial(0, LoadTexture(0, "r2skin.jpg"))
CreateSphere(0,1)
CreateEntity(1, MeshID(0), MaterialID(0),5,3,0)
CreateEntity(2, MeshID(0), MaterialID(0),5,4,0)
CreateNode(0,0,0,0)
AttachNodeObject(0,EntityID(1))
CreateNode(1,0,0,0)
AttachNodeObject(1,EntityID(2))
NodeFixedYawAxis(0, #True, AxisN\x, AxisN\y, AxisN\z)
;Ribbon
GetScriptMaterial(2, "Examples/LightRibbonTrail")
CreateRibbonEffect(0, MaterialID(2), 1, 2800, 180)
RibbonEffectColor(0, 0, RGBA(0, 255*0.8, 255*0.8, 255), RGBA(0, 255, 0, 5))
RibbonEffectWidth(0, 0, 0.1, 0.001)
AttachRibbonEffect(0, EntityParentNode(1))
CreateRibbonEffect(1, MaterialID(2), 1, 2800, 180)
RibbonEffectColor(1, 0, RGBA(255*0.8, 255*0.8, 0, 255), RGBA(0, 255, 0, 5))
RibbonEffectWidth(1, 0, 0.1, 0.001)
AttachRibbonEffect(1, EntityParentNode(2))
CreateLine3D(5,NodeX(0),NodeY(0),NodeZ(0), RGB(255,0,0), NodeX(0) + Axis\x,NodeY(0) + Axis\y,NodeZ(0) + Axis\z, RGB(255,0,0))
SkyBox("stevecube.jpg")
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0, 0, 0, 30, #PB_Absolute)
CameraLookAt(0, 0, 0, 0)
Repeat
Screen3DEvents()
ExamineKeyboard()
RotateNode(0,0,0.4,0, #PB_Relative)
QuaternionFromAngleAxis(@Q, Radian(Angle), @AxisN)
SetOrientation(NodeID(1), Q\x, Q\y, Q\z, Q\w)
Angle + 0.4
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
EndIf
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End
Procedure.f normalise(*V.Vector3)
Length.f = Sqr( *V\x * *V\x + *V\y * *V\y + *V\z * *V\z)
If Length > 0.0
InvLength.f = 1.0 / Length
*V\x * InvLength
*V\y * InvLength
*V\z * InvLength
EndIf
ProcedureReturn Length
EndProcedure
;Axis (normalisé)
;Angle (en radian)
Procedure QuaternionFromAngleAxis (*Q.Quaternion, Angle.f, *Axis.Vector3)
HalfAngle.f = 0.5*Angle
Sin.f = Sin(HalfAngle)
*Q\w = Cos(HalfAngle)
*Q\x = Sin * *Axis\x
*Q\y = Sin * *Axis\y
*Q\z = Sin * *Axis\z
EndProcedure
Please correct my english
http://purebasic.developpez.com/
http://purebasic.developpez.com/
- Psychophanta
- Addict
- Posts: 4997
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Lípetsk, Russian Federation
- Contact:
Re: Simple function to rotate 3D objects over given axis
Hi Comtois,
firstly thanks for your patience.
Awesomely I see you got it.
However, your tip again does not do the thing.
Just modify the axis in real time in the loop, and you will see the chaos begins for the 2 cases: the fixedYaw one, and also with the SetOrientation() (via quaternion) one.
By the way i did functions to get a quaternion form an axis vector and viceversa:
And also from Quaternion to rot matrix and viceversa:
But still no success. I've researched in the web but no success.
firstly thanks for your patience.
Awesomely I see you got it.
However, your tip again does not do the thing.
Just modify the axis in real time in the loop, and you will see the chaos begins for the 2 cases: the fixedYaw one, and also with the SetOrientation() (via quaternion) one.
Code: Select all
Structure Vector3
x.f
y.f
z.f
EndStructure
Structure Quaternion
x.f
y.f
z.f
w.f
EndStructure
#CameraSpeed = 1
IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"
Angle.f
Axis.Vector3:AxisN.Vector3
Q.Quaternion
Procedure QuaternionFromAngleAxis (*Q.Quaternion, Angle.f, *Axis.Vector3)
HalfAngle.f = 0.5*Angle
Sin.f = Sin(HalfAngle)
*Q\w = Cos(HalfAngle)
*Q\x = Sin * *Axis\x
*Q\y = Sin * *Axis\y
*Q\z = Sin * *Axis\z
EndProcedure
Macro GetItNormalized()
CopyStructure(@Axis, @AxisN, Vector3)
;AxisN=Axis
len.f=Sqr(AxisN\x*AxisN\x+AxisN\y*AxisN\y+AxisN\z*AxisN\z)
AxisN\x/len:AxisN\y/len:AxisN\z/len
EndMacro
Macro SetFixedandDisplayline()
NodeFixedYawAxis(0,#True,AxisN\x,AxisN\y,AxisN\z)
CreateLine3D(5,NodeX(0),NodeY(0),NodeZ(0),RGB(255,0,0),NodeX(0)+Axis\x,NodeY(0)+Axis\y,NodeZ(0)+Axis\z,RGB(255,0,0))
EndMacro
Axis\x=-1.7
Axis\y=0.0
Axis\z=0.0
GetItNormalized()
If InitEngine3D()
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/skybox.zip", #PB_3DArchive_Zip)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts", #PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite():InitKeyboard():InitMouse()
If Screen3DRequester()
CreateCamera(0,0,0,100,100):MoveCamera(0,0,0,10,#PB_Absolute):CameraLookAt(0,0,0,0)
CreateMaterial(0,LoadTexture(0,"r2skin.jpg"))
CreateCube(0,1)
CreateEntity(1,MeshID(0),MaterialID(0),1,1,0)
CreateEntity(2,MeshID(0),MaterialID(0),1,2,0)
CreateNode(0,0,0,0):AttachNodeObject(0,EntityID(1))
CreateNode(1,0,0,0):AttachNodeObject(1,EntityID(2))
SetFixedandDisplayline()
Repeat
Screen3DEvents()
ExamineKeyboard():ExamineMouse()
mdx.f=MouseDeltaX()/20:mdy.f=MouseDeltaY()/20:mdz.f=MouseWheel()/20
Axis\x+mdx:Axis\y-mdy:Axis\z+mdz
GetItNormalized()
SetFixedandDisplayline()
RotateNode(0,0,0.4,0,#PB_Relative)
QuaternionFromAngleAxis(@Q,Radian(Angle),@AxisN)
SetOrientation(NodeID(1),Q\x,Q\y,Q\z,Q\w)
Angle+0.4
RenderWorld()
FlipBuffers():delay(10)
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
EndIf
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
Code: Select all
Procedure.d ObtenerCuaternioDesdeVectorangulo(*fi.Vector3D,*q.cuaternio); <- usar esta cuando no disponemos del módulo angular de antemano (antes de llamar a la función), sino solo del propio vector ángulo
Protected u.Vector3D
With *q
*fi\m=getmodulo(*fi); <- incluye el numero de vueltas completas (Int(*fi\m/2/#Pi)) más el resto de esa división (Mod(*fi\m,2*#Pi))
u\m=Mod(*fi\m,2*#Pi); <- pero para obtener el cuaternio se debe trabajar con un angulo inferior a 2*#Pi, es decir con el resto de esa division (Mod(*fi\m,2*#Pi))
If u\m
u\x=*fi\x/u\m:u\y=*fi\y/u\m:u\z=*fi\z/u\m
u\m/2
\w=Cos(u\m)
\v\z=Sin(u\m)
\v\x=u\x*\v\z
\v\y=u\y*\v\z
\v\z*u\z
Else
\w=1.0
\v\x=0.0
\v\y=0.0
\v\z=0.0
EndIf
ProcedureReturn u\m
EndWith
EndProcedure
Procedure.d ObtenerVectoranguloDesdeCuaternio(*q.cuaternio,*fi.Vector3D); <- usar esta cuando no disponemos del módulo angular de antemano (antes de llamar a la función), sino solo del propio vector ángulo
With *fi
\m=ACos(*q\w)
If \m
\x=*q\v\x/Sin(\m)
\y=*q\v\y/Sin(\m)
\z=*q\v\z/Sin(\m)
\m*2
\x*\m
\y*\m
\z*\m
Else
\m=0.0; <- obviamente
\x=0.0
\y=0.0
\z=0.0
EndIf
ProcedureReturn \m
EndWith
EndProcedure
Code: Select all
Macro ProductoEscalar(a,b,ax=x,ay=y,az=z,bx=x,by=y,bz=z)
(a#\ax#*b#\bx#+a#\ay#*b#\by#+a#\az#*b#\bz#)
EndMacro
Macro getmodulo(v,vx=x,vy=y,vz=z)
(Sqr#ProductoEscalar(v#,v#,vx#,vy#,vz#,vx#,vy#,vz#))
EndMacro
Macro ProductoVectorial(in1,in2,out,in1x=x,in1y=y,in1z=z,in2x=x,in2y=y,in2z=z,outx=x,outy=y,outz=z); <- Calculates the vectorial product of two 3D vectors. Just modify this procedure to get the vectorial product for 4D, 5D, 6D or any dimension you need.
out#\outx#=in1#\in1y#*in2#\in2z#-in1#\in1z#*in2#\in2y#
out#\outy#=in1#\in1z#*in2#\in2x#-in1#\in1x#*in2#\in2z#
out#\outz#=in1#\in1x#*in2#\in2y#-in1#\in1y#*in2#\in2x#
EndMacro
Macro QuaternionPorQuaternion(q0,q1,o); Composicion de 2 cuaterniones
o#\w=q0#\w*q1#\w-ProductoEscalar(q0#\v,q1#\v)
ProductoVectorial(q0#\v,q1#\v,vr.D3DXVECTOR3)
o#\v\x=q0#\w*q1#\v\x+q1#\w*q0#\v\x+vr\x
o#\v\y=q0#\w*q1#\v\y+q1#\w*q0#\v\y+vr\y
o#\v\z=q0#\w*q1#\v\z+q1#\w*q0#\v\z+vr\z
EndMacro
Macro qpq_(q,p,o); Composicion de 2 cuaterniones
QuaternionPorQuaternion(q#,p#,o#)
p#=o#
q#\v\x=-q#\v\x
q#\v\y=-q#\v\y
q#\v\z=-q#\v\z
QuaternionPorQuaternion(p#,q#,o#)
EndMacro
Procedure.i ObtenerMatrizDesdeCuaternio(objeto.i,*matriz.D3DMATRIX,modo.i=#PB_Absolute)
FetchOrientation(objeto,modo):Protected x.f=GetX(),y.f=GetY(),z.f=GetZ(),w.f=GetW(),s.f=2.0/(x*x+y*y+z*z+w*w)
*matriz\Xi=1-s*(y*y+z*z); <- 0,0
*matriz\Xj=s*(x*y-z*w); <- 0,1
*matriz\Xk=s*(x*z+y*w); <- 0,2
*matriz\Yi=s*(x*y+z*w); <- 1,0
*matriz\Yj=1-s*(x*x+z*z); <- 1,1
*matriz\Yk=s*(y*z-x*w); <- 1,2
*matriz\Zi=s*(x*z-y*w); <- 2,0
*matriz\Zj=s*(y*z+x*w); <- 2,1
*matriz\Zk=1-s*(x*x+y*y); <- 2,2
ProcedureReturn *matriz
EndProcedure
Procedure ObtenerCuaternioDesdeMatriz0(objeto.i,*matriz.D3DMATRIX)
Protected q.cuaternio
q\w=Sqr(*matriz\Xi+*matriz\Yj+*matriz\Zk+1)/2
q\v\x=Sign(*matriz\Zj-*matriz\Yk)*Sqr(*matriz\Xi-*matriz\Yj-*matriz\Zk+1)/2
q\v\y=Sign(*matriz\Xk-*matriz\Zi)*Sqr(*matriz\Yj-*matriz\Xi-*matriz\Zk+1)/2
q\v\z=Sign(*matriz\Yi-*matriz\Xj)*Sqr(*matriz\Zk-*matriz\Xi-*matriz\Yj+1)/2
SetOrientation(objeto,q\v\x,q\v\y,q\v\z,q\w)
EndProcedure
Procedure ObtenerCuaternioDesdeMatriz(objeto.i,*matriz.D3DMATRIX)
Protected q.cuaternio,tr.f=*matriz\Xi+*matriz\Yj+*matriz\Zk,S.f
If tr>0
S=Sqr(tr+1)*2; S=4*w
q\w=S/4
q\v\x=(*matriz\Zj-*matriz\Yk)/S
q\v\y=(*matriz\Xk-*matriz\Zi)/S
q\v\z=(*matriz\Yi-*matriz\Xj)/S
ElseIf *matriz\Xi>*matriz\Yj And *matriz\Xi>*matriz\Zk
S=Sqr(1+*matriz\Xi-*matriz\Yj-*matriz\Zk)*2; S=4*x
q\w=(*matriz\Zj-*matriz\Yk)/S
q\v\x=S/4
q\v\y=(*matriz\Xj+*matriz\Yi)/S
q\v\z=(*matriz\Xk+*matriz\Zi)/S
ElseIf *matriz\Yj>*matriz\Zk
S=Sqr(1+*matriz\Yj-*matriz\Xi-*matriz\Zk)*2; S=4*y
q\w=(*matriz\Xk-*matriz\Zi)/S
q\v\x=(*matriz\Xj+*matriz\Yi)/S
q\v\y=S/4
q\v\z=(*matriz\Yk+*matriz\Zj)/S
Else
S=Sqr(1+*matriz\Zk-*matriz\Xi-*matriz\Yj)*2; S=4*z
q\w=(*matriz\Yi-*matriz\Xj)/S
q\v\x=(*matriz\Xk+*matriz\Zi)/S
q\v\y=(*matriz\Yk+*matriz\Zj)/S
q\v\z=S/4
EndIf
SetOrientation(objeto,q\v\x,q\v\y,q\v\z,q\w)
EndProcedure
Procedure ObtenerCuaternioDesdeMatriz2(objeto.i,*matriz.D3DMATRIX)
Protected Dim m.f(2,2),c.cuaternio,tr.f,s.f,Dim q.f(3),i.l,j.l,k.l,Dim nxt.l(2):nxt.l(0)=1:nxt.l(1)=2:nxt.l(2)=0
m(0,0)=*matriz\Xi:m(0,1)=*matriz\Xj:m(0,2)=*matriz\Xk
m(1,0)=*matriz\Yi:m(1,1)=*matriz\Yj:m(1,2)=*matriz\Yk
m(2,0)=*matriz\Zi:m(2,1)=*matriz\Zj:m(2,2)=*matriz\Zk
tr=m(0,0)+m(1,1)+m(2,2)
; check the diagonal
If tr>0.0
s=Sqr(tr+1.0)
c\w=s/2.0
s=0.5/s
c\v\x=(m(1,2)-m(2,1))*s
c\v\y=(m(2,0)-m(0,2))*s
c\v\z=(m(0,1)-m(1,0))*s
Else; diagonal is negative
i=0
If m(1,1)>m(0,0):i=1:EndIf
If m(2,2)>m(i,i):i=2:EndIf
j=nxt(i)
k=nxt(j)
s=Sqr(m(i,i)-m(j,j)-m(k,k)+1.0)
q(i)=s*0.5
If s<>0.0:s=0.5/s:EndIf
q(3)=(m(j,k)-m(k,j))*s
q(j)=(m(i,j)+m(j,i))*s
q(k)=(m(i,k)+m(k,i))*s
c\v\x=q(0)
c\v\y=q(1)
c\v\z=q(2)
c\w=q(3)
EndIf
SetOrientation(objeto,c\v\x,c\v\y,c\v\z,c\w)
EndProcedure
http://www.zeitgeistmovie.com
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB
Re: Simple function to rotate 3D objects over given axis
You don't get it because this is not only maths, but global thinking.
A tip is to think by object and world, keeping axis in the structures and applying transformations on it also.
Basically, the original object can be transformed in a local context (as pb does). It can also be transformed in a world context (lacking). Finally, it can be transformed in camera context (done). Eventually, it can transformed in a node context (partially done) giving access to bones and objects hierarchy.
Additionally, you may also think on two representations : the original object, and the transformed. Object data could be altered, leading to a new geometry. If you (-1) transform the axis, you may keep the history.
Btw, you may also keep a track of all tranformations in a list.
The code I've given was basically for this purpose even if it's incomplete.
A tip is to think by object and world, keeping axis in the structures and applying transformations on it also.
Basically, the original object can be transformed in a local context (as pb does). It can also be transformed in a world context (lacking). Finally, it can be transformed in camera context (done). Eventually, it can transformed in a node context (partially done) giving access to bones and objects hierarchy.
Additionally, you may also think on two representations : the original object, and the transformed. Object data could be altered, leading to a new geometry. If you (-1) transform the axis, you may keep the history.
Btw, you may also keep a track of all tranformations in a list.
The code I've given was basically for this purpose even if it's incomplete.