Simple function to rotate 3D objects over given axis

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
Psychophanta
Addict
Addict
Posts: 4996
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Simple function to rotate 3D objects over given axis

Post by Psychophanta »

To syntetize it:
If you get the cone in this tip to always rotating in the same way respect the red axis, then you succeed, and you built the workaround for the issue:

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
Procedure QuaternionFromAngleAxis (*Q.Quaternion, Angle.f, *Axis.Vector3)
  Angle/2
  Sin.f=Sin(Angle)
  *Q\w=Cos(Angle)
  *Q\x=Sin**Axis\x
  *Q\y=Sin**Axis\y
  *Q\z=Sin**Axis\z
EndProcedure
Macro GetItNormalized()
  len.f=Sqr(Axis\x*Axis\x+Axis\y*Axis\y+Axis\z*Axis\z)
  AxisN=Axis
  AxisN\x/len:AxisN\y/len:AxisN\z/len
EndMacro
Axis\x=-1
Axis\y=0
Axis\z=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"))    
    CreateCone(0,1,1,8,1)
    CreateEntity(2,MeshID(0),MaterialID(0),1,0,0):RotateEntity(2,0,0,90,#PB_Absolute)
    CreateNode(1,0,0,0):AttachNodeObject(1,EntityID(2))
    CreateLine3D(5,NodeX(1),NodeY(1),NodeZ(1),RGB(255,0,0),NodeX(1)+Axis\x,NodeY(1)+Axis\y,NodeZ(1)+Axis\z,RGB(255,0,0))
    Repeat
      Screen3DEvents()
      ExamineKeyboard():ExamineMouse()
      mdx.f=MouseDeltaX()/60:mdy.f=MouseDeltaY()/60:mdz.f=MouseWheel()/2
      Axis\x+mdx:Axis\y-mdy:Axis\z+mdz
      GetItNormalized()
      CreateLine3D(5,NodeX(1),NodeY(1),NodeZ(1),RGB(255,0,0),NodeX(1)+Axis\x,NodeY(1)+Axis\y,NodeZ(1)+Axis\z,RGB(255,0,0))
      QuaternionFromAngleAxis(@Q,Angle,@AxisN)
      SetOrientation(NodeID(1),Q\x,Q\y,Q\z,Q\w)
      Angle+0.04
      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
The tip is obtained from the Comtois one.
The goal is a function that (as stated in first post) accepts a 3D object and a global 3D vector as axis, and turns an angle (angle given in the vector as its lenght) that object around that given world axis.

By the way:
In the powerful programs like Cinema4D, Blender, etc. this issue is hard, and to perform it, the user is always forced to use more than one element in animation, even the animated element is just only one.

By the way 2nd part:
Looks like no info about this simple issue here:
http://wiki.ogre3d.org/Quaternion+and+Rotation+Primer
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 290
Joined: Thu Jul 09, 2015 9:07 am

Re: Simple function to rotate 3D objects over given axis

Post by pf shadoko »

I will add 'NodeDirection' function

Code: Select all

Structure Vector3
  x.f
  y.f
  z.f
EndStructure

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"
Define.f  MouseX, MouseY, Angle
Define.vector3 axis
Axis\x=-1
Axis\y=0
Axis\z=0

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"))    
    CreateCone(0,1,1)
    CreateEntity(2,MeshID(0),MaterialID(0))
    RotateEntity(2,0,0,180)
    RotateEntity(2,90,0,0)
    MoveEntity(2,0,0,0.5)
    CreateNode(1,0,0,0):AttachNodeObject(1,EntityID(2))
    CreateLine3D(5,NodeX(1),NodeY(1),NodeZ(1),RGB(255,0,0),NodeX(1)+Axis\x,NodeY(1)+Axis\y,NodeZ(1)+Axis\z,RGB(255,0,0))
    Repeat
      Screen3DEvents()
      ExamineKeyboard():ExamineMouse()
      mdx.f=MouseDeltaX()/60:mdy.f=MouseDeltaY()/60:mdz.f=MouseWheel()/2
      Axis\x+mdx:Axis\y-mdy:Axis\z+mdz
      NodeLookAt(1,Axis\x+NodeX(1),Axis\y+NodeY(1),Axis\z+NodeZ(1))
      CreateLine3D(5,NodeX(1),NodeY(1),NodeZ(1),RGB(255,0,0),NodeX(1)+Axis\x,NodeY(1)+Axis\y,NodeZ(1)+Axis\z,RGB(255,0,0))
      delta_angle=1  ;Angle+delata_angle
      Roll(NodeID(1),delta_angle,#PB_Local)
      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
User avatar
Psychophanta
Addict
Addict
Posts: 4996
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Simple function to rotate 3D objects over given axis

Post by Psychophanta »

Thank you pf shadoko.

As you can see in your tip: while changing orientation of the axis, the body ALSO turns like the axis, and that must not happen: the body must rotate only around the axis.
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
User avatar
Psychophanta
Addict
Addict
Posts: 4996
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Simple function to rotate 3D objects over given axis

Post by Psychophanta »

May be an approaching for a workaround for it. But still fails :(
However , it is very descriptive to understand the idea.
Use cursor keys and av-pag/re-pag to orientate the axis arrow.
Uses mouse left/right movement to turn around the axis arrow.

Code: Select all

InitEngine3D()
InitSprite():InitKeyboard():InitMouse()
OpenWindow(0,0,0,800,600,Titulo$,#PB_Window_BorderLess|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,800,600,1,0,0,#PB_Screen_WaitSynchronization)
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/Scripts",#PB_3DArchive_FileSystem)
Parse3DScripts()
Enumeration; Camaras
  #Camara
EndEnumeration
Enumeration; Luces
  #Luz
EndEnumeration
Enumeration; Texturas
  #Textura
EndEnumeration
Enumeration; Materiales
  #Material
EndEnumeration
Enumeration; Mallas
  #conomalla
  #Object0malla
EndEnumeration
Enumeration; Entidades
  #Object0
  #Flechaorientacion
  #Flecharotacion
EndEnumeration
Enumeration; Nodos
  #Pivotcam
  #NodoFlecharotacion
EndEnumeration
Enumeration; Texto3D
  #Texto3D
  #Texto3D_2
EndEnumeration
Structure D3DXVECTOR3
  x.f
  y.f
  z.f
EndStructure
Structure Vector3D Extends D3DXVECTOR3
  m.f;<-length(modulo)
EndStructure
Structure cuaternio
  w.f
  v.D3DXVECTOR3
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
Macro ObtenerModuloCuaternio(q)
  (Sqr(q#\w*q#\w+q#\v\x*q#\v\x+q#\v\y*q#\v\y+q#\v\z*q#\v\z))
EndMacro
Procedure.d NormalizarVector3D(*v.D3DXVECTOR3)
  Protected m.d=getmodulo(*v)
  If m
    *v\x/m:*v\y/m:*v\z/m
    Procedurereturn m
  Endif
  *v\x=0.0:*v\y=0.0:*v\z=-1.0
  Procedurereturn 0.0
EndProcedure
Procedure.d NormalizarCuaternio(*q.cuaternio)
  Protected m.d=ObtenerModuloCuaternio(*q)
  If m
    *q\w/m:*q\v\x/m:*q\v\y/m:*q\v\z/m
    Procedurereturn m
  Endif
  *q\w=1.0:*q\v\x=0.0:*q\v\y=0.0:*q\v\z=-1.0
  Procedurereturn 0.0
EndProcedure
Procedure AddMesh(mallaorigen.i,mallaobtenida.i)
  Protected Dim mallaorigenDataV.PB_MeshVertex(0),Dim mallaorigenDataF.PB_MeshFace(0),Dim mallaobtenidaDataV.PB_MeshVertex(0),Dim mallaobtenidaDataF.PB_MeshFace(0),i.i,maxindex.i
  GetMeshData(mallaorigen,0,mallaorigenDataV(), #PB_Mesh_Vertex | #PB_Mesh_UVCoordinate| #PB_Mesh_Normal|#PB_Mesh_Color, 0, MeshVertexCount(mallaorigen, 0)-1)
  GetMeshData(mallaorigen,0,mallaorigenDataF(), #PB_Mesh_Face, 0, MeshIndexCount(mallaorigen, 0)-1)
  GetMeshData(mallaobtenida,0,mallaobtenidaDataV(), #PB_Mesh_Vertex | #PB_Mesh_UVCoordinate| #PB_Mesh_Normal|#PB_Mesh_Color, 0, MeshVertexCount(mallaobtenida, 0)-1)
  GetMeshData(mallaobtenida,0,mallaobtenidaDataF(), #PB_Mesh_Face, 0, MeshIndexCount(mallaobtenida, 0)-1)
  FreeMesh(mallaobtenida)
  mallaobtenida.i=CreateMesh(#PB_Any,#PB_Mesh_TriangleList,#PB_Mesh_Static)
  For i=0 To ArraySize(mallaobtenidaDataV())
    With mallaobtenidaDataV(i)
    MeshVertexPosition(\x,\y,\z)
    MeshVertexNormal(\NormalX,\NormalY,\NormalZ)
    MeshVertexTextureCoordinate(\u,\v) 
    MeshVertexColor(\Color)
    EndWith
  Next
  For i=0 To ArraySize(mallaorigenDataV())
    With mallaorigenDataV(i)
    MeshVertexPosition(\x,\y,\z)
    MeshVertexNormal(\NormalX,\NormalY,\NormalZ)
    MeshVertexTextureCoordinate(\u,\v) 
    MeshVertexColor(\Color)
    EndWith
  Next
  For i=0 To ArraySize(mallaobtenidaDataF()) Step 3
    MeshFace(mallaobtenidaDataF(i)\Index,mallaobtenidaDataF(i+1)\Index,mallaobtenidaDataF(i+2)\Index)
    If mallaobtenidaDataF(i)\Index>maxindex:maxindex=mallaobtenidaDataF(i)\Index:EndIf
    If mallaobtenidaDataF(i+1)\Index>maxindex:maxindex=mallaobtenidaDataF(i+1)\Index:EndIf
    If mallaobtenidaDataF(i+2)\Index>maxindex:maxindex=mallaobtenidaDataF(i+2)\Index:EndIf
  Next
  maxindex+1
  For i=0 To ArraySize(mallaorigenDataF()) Step 3
    MeshFace(mallaorigenDataF(i)\Index+maxindex,mallaorigenDataF(i+1)\Index+maxindex,mallaorigenDataF(i+2)\Index+maxindex)
  Next
  FinishMesh(1)
  NormalizeMesh(mallaobtenida)
  UpdateMeshBoundingBox(mallaobtenida)
EndProcedure
Procedure.i flecha(flecha.i,color.l=$00FBFD49,letra$="",TransTextX=1/2,TransTextY=0,TransTextZ=0,ResizeTextX=1/5,ResizeTextY=1/3,ResizeTextZ=1/30)
  Protected malla.i=CreateCylinder(#PB_Any,0.02,1,20,1,1),conomalla.i=CreateCone(#PB_Any,0.05,0.1,15,1),material.i,textura.i=CreateTexture(#PB_Any,32,32)
  StartDrawing(TextureOutput(textura.i))
  Box(0,0,32,32,color.l)
  StopDrawing()
  material.i=CreateMaterial(#PB_Any,TextureID(textura.i))
  SetMaterialColor(material,#PB_Material_AmbientColor,color.l)
  TransformMesh(conomalla,0,0.525,0,1,1,1,0,0,0,0)
  AddMesh(conomalla,malla):FreeMesh(conomalla)
  TransformMesh(malla,0,0,0,1,1,1,-90,0,0,0)
  If flecha.i=#PB_Any
    flecha.i=CreateEntity(#PB_Any,MeshID(malla.i),MaterialID(material.i),0,0,0)
  Else
    CreateEntity(flecha.i,MeshID(malla.i),MaterialID(material.i),0,0,0)
  EndIf
  If letra$
    letra.i=CreateText3D(#PB_Any,letra$)
    Text3DColor(letra.i,RGBA(251,30,40,95))
    Text3DAlignment(letra.i,#PB_Text3D_HorizontallyCentered)
    ScaleText3D(letra.i,mod*ResizeTextX,mod*ResizeTextY,mod*ResizeTextZ,#PB_Relative)
    MoveText3D(letra.i,mod*TransTextX,mod*TransTextY,mod*TransTextZ,#PB_Relative)
    AttachEntityObject(flecha.i,"",Text3DID(letra.i))
  EndIf
  FreeMesh(malla)
  FreeMaterial(material)
  FreeTexture(textura)
  ProcedureReturn flecha
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
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
Macro SumarAnguloACuaternio(q,deltaang=0.0); <- deja un cuaternio con un valor determinado de 'angulo'
  ;Si q#\w=0.0; => angulo=180.0 grados. Si q#\w>0.0; => angulo<180.0 grados. Si q#\w<0.0; => angulo>180.0 grados
  If deltaang#
    valor.d=2*ACos(q#\w)+deltaang#
    If valor<0.0
      valor=Mod(valor,-2*#PI)+2*#PI
    Else
      valor=Mod(valor,2*#PI)
    EndIf
    valor/2
    q#\w=Cos(valor)
    valor=Sin(valor)
    If q#\w
      NormalizarVector3D(@q#\v)
    Endif
    q#\v\x*valor
    q#\v\y*valor
    q#\v\z*valor
  Endif
EndMacro
Procedure.b Rotar_Vector3D_por_adicion_Angular(*fi.Vector3D,*R0.Vector3D)
  ;Esta funcion halla un vector resultado de una rotacion en el espacio de otro vector inicial.
  ;Esta funcion admite entonces, como parametros de entrada, 2 vectores:
  ; - 'Vector radio' ( *R0-> ) que se desea rotar. Este vector tiene direccion no colineal con el eje de rotación.
  ; - 'Vector angulo' ( *fi-> 'velocidad angular'-> * 'tiempo'), es el angulo en el que se rota el 'Vector radio' dado.
  ;     Su modulo indica el numero de radianes a rotar, su direccion indica el angulo en el espacio en el que se rota (eje de rotación)
  ;     su sentido indica el sentido de la rotacion
  ;NOTA: la funcion extrae el vector velocidad rectilinea y el nuevo vector radio.
  ;       se devuelve nuevo radio en el mismo parametro de entrada ( *R0-> )
  Protected Rt.Vector3D,u.Vector3D,P0.Vector3D
  *fi\m=ProductoEscalar(*fi,*fi)
  If *fi\m
    u\m=ProductoEscalar(*R0,*fi)/*fi\m
    *fi\m=Sqr(*fi\m)
    ;Rt-> = Proyeccion de *R0-> sobre *fi->:
    Rt\x=u\m**fi\x
    Rt\y=u\m**fi\y
    Rt\z=u\m**fi\z
    ;P0-> = proyeccion ortogonal de *R0-> sobre *fi->:
    P0\x=*R0\x-Rt\x
    P0\y=*R0\y-Rt\y
    P0\z=*R0\z-Rt\z
    P0\m=getmodulo(P0)
    If P0\m=0.0; <= no hay giro ya que *R0-> y *fi-> son colineales. Pero hay "torsion" vectorial:
      ;Esta "torsion" significa que el 'Vector radio' ( *R0-> ) aumenta su amplitud en la medida de la amplitud del 'Vector angulo' ( *fi-> )
      *R0\x+*fi\x
      *R0\y+*fi\y
      *R0\z+*fi\z
      ProcedureReturn -1
    EndIf
    ;Calcular el producto vectorial: u-> = *fi-> X P0->
    u\x=*fi\y*P0\z-*fi\z*P0\y
    u\y=*fi\z*P0\x-*fi\x*P0\z
    u\z=*fi\x*P0\y-*fi\y*P0\x
    ;ahora obtener *R0-> = (Proyeccion de *R0-> sobre *fi->)-> + (cos(|*fi->|)·P0-> + |P0->|/|u->|·sin(|*fi->|)·u->)->:
    *R0\x=Rt\x
    *R0\y=Rt\y
    *R0\z=Rt\z
    Rt\x=Cos(*fi\m):Rt\y=Sin(*fi\m)
    u\m=getmodulo(u)
    P0\m*Rt\y/u\m
    *R0\x+Rt\x*P0\x+P0\m*u\x
    *R0\y+Rt\x*P0\y+P0\m*u\y
    *R0\z+Rt\x*P0\z+P0\m*u\z
    ProcedureReturn 1
  EndIf
  ProcedureReturn 0
EndProcedure
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)
LoadMesh(#Object0malla,"axes.mesh")
CreateMaterial(#material,LoadTexture(#textura,"axes.png"))
CreateEntity(#Object0,MeshID(#Object0malla),MaterialID(#material),0,0,0):RotateEntity(#Object0,1,20,3)
ScaleEntity(#Object0,0.05,0.05,0.05)
flecha(#Flechaorientacion):ScaleEntity(#Flechaorientacion,0.8,0.8,2,#PB_Relative):MoveEntity(#Flechaorientacion,0.0,0,0,#PB_Absolute)
flecha(#Flecharotacion,$0045FAEE):ScaleEntity(#Flecharotacion,0.8,0.8,2,#PB_Relative):MoveEntity(#Flecharotacion,0.0,0,0,#PB_Absolute)
u.Vector3D:mult.f=100
vx.f=0.1*mult:vy.f=0.2*mult:vz.f=-1*mult
u\x=vx.f:u\y=vy.f:u\z=vz.f:EntityLookAt(#Flecharotacion,u\x,u\y,u\z)
Repeat
  ExamineMouse():ExamineKeyboard()
  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
  TeclaControldecamara(LeftControl)
  ElseIf KeyboardPushed(#PB_Key_Up):vy.f-1:u\x=vx.f:u\y=vy.f:u\z=vz.f:EntityDirection(#Flecharotacion,u\x,u\y,u\z,#PB_World,#PB_Vector_NegativeZ)
  ElseIf KeyboardPushed(#PB_Key_Down):vy.f+1:u\x=vx.f:u\y=vy.f:u\z=vz.f:EntityDirection(#Flecharotacion,u\x,u\y,u\z,#PB_World,#PB_Vector_NegativeZ)
  ElseIf KeyboardPushed(#PB_Key_Left):vx.f-1:u\x=vx.f:u\y=vy.f:u\z=vz.f:EntityDirection(#Flecharotacion,u\x,u\y,u\z,#PB_World,#PB_Vector_NegativeZ)
  ElseIf KeyboardPushed(#PB_Key_Right):vx.f+1:u\x=vx.f:u\y=vy.f:u\z=vz.f:EntityDirection(#Flecharotacion,u\x,u\y,u\z,#PB_World,#PB_Vector_NegativeZ)
  ElseIf KeyboardPushed(#PB_Key_PageUp):vz.f-1:u\x=vx.f:u\y=vy.f:u\z=vz.f:EntityDirection(#Flecharotacion,u\x,u\y,u\z,#PB_World,#PB_Vector_NegativeZ)
  ElseIf KeyboardPushed(#PB_Key_PageDown):vz.f+1:u\x=vx.f:u\y=vy.f:u\z=vz.f:EntityDirection(#Flecharotacion,u\x,u\y,u\z,#PB_World,#PB_Vector_NegativeZ)
  ElseIf KeyboardPushed(#PB_Key_RightShift); <- rotar el objeto sobre eje 'x' global y sobre eje 'y' global
  ElseIf mdx
    eje.Vector3D
    ori.Vector3D:ori\x=EntityDirectionX(#Flechaorientacion):ori\y=EntityDirectionY(#Flechaorientacion):ori\z=EntityDirectionZ(#Flechaorientacion)
    eje=u
    eje\m=getmodulo(eje)
    If eje\m And mdx
      eje\x*mdx/eje\m:eje\y*mdx/eje\m:eje\z*mdx/eje\m
      Rotar_Vector3D_por_adicion_Angular(@eje.Vector3D,@ori)
      EntityDirection(#Flechaorientacion,ori\x,ori\y,ori\z,#PB_World,#PB_Vector_NegativeZ)
      EntityDirection(#Object0,ori\x,ori\y,ori\z,#PB_World,#PB_Vector_NegativeZ)
      FetchOrientation(EntityID(#Object0),#PB_Absolute)
      qo.cuaternio
      qo\w=GetW():qo\v\x=GetX():qo\v\y=GetY():qo\v\z=GetZ()
      SumarAnguloACuaternio(qo,-mdx)
      SetOrientation(EntityID(#Object0),qo\v\x,qo\v\y,qo\v\z,qo\w)
    EndIf
  EndIf
  RenderWorld()
  FlipBuffers():Delay(11)
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 :mrgreen:
User avatar
Psychophanta
Addict
Addict
Posts: 4996
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Simple function to rotate 3D objects over given axis

Post by Psychophanta »

Well, finally this is the stupid think I have been looking for.
Here it is the workaround function:

Code: Select all

Secret until Challenge result of at least 1 functional code (look: https://www.purebasic.fr/english/viewtopic.php?f=36&t=72403
Comtois was inthe thrak when he purposed to work with the EntityFixedYawAxis() function, and I should be realized that the trick was so simple to convert the local orientation of the object to global coordinates.
By the way , I see the ConvertWorldToLocalPosition() & ConvertLocalToWorldPosition(), should be named more correctly ConvertWorldToLocalCoordinates() & ConvertLocalToWorldCoordinates().

Functional and descriptive tip: (Use cursor keys and av-pag/re-pag to orientate the axis arrow. Uses mouse left/right movement to turn around the axis arrow. Left CTRL and mouse allows to orientate point of view to the object.)

Code: Select all

Secret until Challenge result of at least 1 functional code (look: https://www.purebasic.fr/english/viewtopic.php?f=36&t=72403
EDITED & DELETED Until Challenge result of at least 1 functional code (look: viewtopic.php?f=36&t=72403
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
marc_256
Enthusiast
Enthusiast
Posts: 744
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: Simple function to rotate 3D objects over given axis

Post by marc_256 »

Hi Psychophanta,

If I understand your problem !!

I'm working for some years now (since 1978 apple II :shock: I'm old) in 3D development / design,
and one of the most important tools in 3D programming are the nodes,
see
https://www.purebasic.com/documentation/node/index.html

1) create a number of nodes ... (empty 3D reference points)
2) add/link one or more objects, camera, lights, ... to a node ...
3) combine the nodes to other nodes ...
4) now you can move, rotate, scale the nodes independently to world coordinates (objects connected to this nodes)

I'm on vacation with my daughter now,
so I don't have my all-day's 3D work computer with me, for an PB example ...
But here are some examples on my website

http://www.marc-systems.be/ms_2018/webs ... studio.htm

marc,

PS: sorry for my english
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
User avatar
Psychophanta
Addict
Addict
Posts: 4996
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Simple function to rotate 3D objects over given axis

Post by Psychophanta »

Thank you Marc.
Right, use of nodes is mandatory for some dealings.

The current problem (solved via workaroaund) es shown in the link:
viewtopic.php?f=36&t=72403

I have not used nodes for it, because not needed, however the problem has a small complexity.

I decided to derive it to that thread just to check and test other possible solutions or workarounds for the same result.
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
Post Reply