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)