Middle mouse button to rotate objects (arrows in this example)
Left Control key and move mouse to orbitate camera view over the observed center.
Sorry for some comments in spanish in the code.
Code: Select all
ExamineDesktops()
Global bitplanes.a=DesktopDepth(0),FRX.u=DesktopWidth(0),FRY.u=DesktopHeight(0),RX.u=FRX,RY.u=FRY,FrecuenciadeMuestreo.a=60
If FRX<1280 Or FRY<720:RX=FRX*2/3:RY=FRY*2/3:Else:RX=1280:RY=720:EndIf
InitEngine3D(#PB_Engine3D_NoLog,#PB_Compiler_Home+"Compilers\Engine3d.dll")
If InitMouse()=0 Or InitSprite()=0 Or InitKeyboard()=0:MessageRequester("Error","Can't open DirectX",0):End:EndIf
#ventana=1
OpenWindow(#ventana,0,0,RX,RY,Titulo$,#PB_Window_BorderLess|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#ventana),0,0,RX,RY,1,0,0,#PB_Screen_WaitSynchronization)
Add3DArchive(#PB_Compiler_Home+"examples/3D/Data/Scripts",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"examples\3D\Data\fonts",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"examples/3d/Data/Textures",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"examples\3D\Data\GUI",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"examples/3d/Data/Packs/desert.zip",#PB_3DArchive_Zip)
Parse3DScripts()
SetGUITheme3D("","DejaVuSans-10"):#TextoInfoObjeto=0
Enumeration Luces
#Luz
EndEnumeration
Enumeration Camaras
#Camara
EndEnumeration
Enumeration Texturas
#texturacubo1
EndEnumeration
Enumeration Nodos
#pivotcamara
EndEnumeration
Enumeration Entidades
#arrowR
#arrowG
#arrowB
EndEnumeration
Enumeration Texto3D
#texto1=40
EndEnumeration
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
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
Procedure AnguloFormadoPor2Vectores(*in1.Vector3D,*in2.Vector3D,*out.Vector3D)
Protected.Vector3D v1,v2:CopyMemory(*in1,@v1,SizeOf(Vector3D)):CopyMemory(*in2,@v2,SizeOf(Vector3D))
ProductoVectorial(*in1,*in2,*out):*out\m=getmodulo(*out)
v1\m=getmodulo(v1):v2\m=getmodulo(v2)
If *out\m=0.0
If v1\m=0.0 Or v2\m=0.0:FillMemory(*out,SizeOf(Vector3D),0,#PB_Byte):ProcedureReturn:EndIf
*out\m=1.0
EndIf
v1\x/v1\m:v1\y/v1\m:v1\z/v1\m
v2\x/v2\m:v2\y/v2\m:v2\z/v2\m
v1\x-v2\x:v1\y-v2\y:v1\z-v2\z:v1\m=getmodulo(v1)
v2\m=2*ASin(v1\m/2)
*out\x*v2\m/*out\m:*out\y*v2\m/*out\m:*out\z*v2\m/*out\m
*out\m=v2\m
EndProcedure
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-> )
; El resultado es:
; Proyección de *R0-> sobre *fi-> MÁS proyección ortogonal de *R0-> sobre *fi-> por el Cos(|fi->|) MÁS módulo de la proyección ortogonal de *R0-> sobre *fi-> por el Sen(|fi->|) por u^,
; siendo u-> = *fi-> X *R0-> .
Protected Rt.Vector3D,u.Vector3D,P0.Vector3D
*fi\m=ProductoEscalar(*fi,*fi)
If *fi\m
u\m=ProductoEscalar(*R0,*fi)/*fi\m; <- aqui lo uso como variable comodin
*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 *R0-> (o por P0-> daría igual)
u\x=*fi\y**R0\z-*fi\z**R0\y
u\y=*fi\z**R0\x-*fi\x**R0\z
u\z=*fi\x**R0\y-*fi\y**R0\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
Procedure.b MouseButtonEdgeDetection(boton.b,estado.b)
Static mb.b:Protected i.b=1<<boton
If estado;<- if current key status is PUSHED
If mb&i=0:mb|i:ProcedureReturn 1:EndIf;<- if previous key status was NOT PUSHED, then assign previous state to current one, and EXIT.
ElseIf mb&i;<- else (if previous key status was PUSHED and current key status is NOT PUSHED):
mb!i:ProcedureReturn -1;<- set previous key status to NOT PUSHED.
EndIf
ProcedureReturn 0
EndProcedure
Procedure.b KeyEdgeDetection(tecla.a,estado.b)
Static pka.a
If estado;<-if current key status is PUSHED
If pka=0:pka=tecla:ProcedureReturn 1:EndIf;<-if previous key status was NOT PUSHED, then assign previous state to current one, and EXIT.
ElseIf pka=tecla;<-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
Procedure AddMesh(mallaorigen.i,mallaobtenida.i,liberar.b=1,color.l=$FFFFFFFF)
Protected Dim mallaorigenDataV.MeshVertex(0),Dim mallaorigenDataF.MeshFace(0),Dim mallaobtenidaDataV.MeshVertex(0),Dim mallaobtenidaDataF.MeshFace(0),i.i,maxindex.i
GetMeshData(mallaorigen.i,0,mallaorigenDataV(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate| #PB_Mesh_Normal|#PB_Mesh_Color,0,MeshVertexCount(mallaorigen.i,0)-1)
GetMeshData(mallaorigen.i,0,mallaorigenDataF(),#PB_Mesh_Face,0,MeshIndexCount(mallaorigen.i,0)-1)
GetMeshData(mallaobtenida.i,0,mallaobtenidaDataV(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate|#PB_Mesh_Normal|#PB_Mesh_Color,0,MeshVertexCount(mallaobtenida.i,0)-1)
GetMeshData(mallaobtenida.i,0,mallaobtenidaDataF(),#PB_Mesh_Face,0,MeshIndexCount(mallaobtenida.i,0)-1)
FreeMesh(mallaobtenida.i)
CreateMesh(mallaobtenida.i,#PB_Mesh_TriangleList,#PB_Mesh_Static)
For i=0 To ArraySize(mallaobtenidaDataV())
With mallaobtenidaDataV(i)
MeshVertex(\x,\y,\z,\u,\v,color.l,\NormalX,\NormalY,\NormalZ)
EndWith
Next
For i=0 To ArraySize(mallaorigenDataV())
With mallaorigenDataV(i)
MeshVertex(\x,\y,\z,\u,\v,color.l,\NormalX,\NormalY,\NormalZ)
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.i)
UpdateMeshBoundingBox(mallaobtenida.i)
If liberar.b:FreeMesh(mallaorigen.i):EndIf
EndProcedure
Procedure.i arrow(arrow.i,color.l=$00FBFD49,centro.f=0.5,grosor.f=1,longitud.f=1,letra$="",tipoletra$="",PosText.f=0.5,ResizeTextX.f=10,ResizeTextY.f=16,ResizeTextZ.f=1/30)
;'grosor.f' es el diametro de la base del cilindro, esto es, su grosor
Protected n.f=0.2,g_b.f=0.5232; <- ambos valores deben ser entre 0 y 1. 'g_b.f' es la relación entre el diametro del cilindro y el del cono
Protected b.f=grosor/g_b; <- 'b.f' es el diametro de la base del cono
Protected a.f=1.65*b; <- altura cono = relación de aspecto del cono * diametro de su base
Protected d.f=a.f*(1+n*(g_b-1)); <- distancia entre el vértice del cono y la base del cilindro más cercana
CreateCylinder(9991,grosor/2,longitud-d,3,1,1)
CreateCone(9992,b/2,a,3,1)
CreateTexture(9991,32,32)
StartDrawing(TextureOutput(9991))
Box(0,0,32,32,color.l)
StopDrawing()
CreateMaterial(9991,TextureID(9991))
SetMaterialColor(9991,#PB_Material_AmbientColor,color.l)
TransformMesh(9992,0,(longitud+d-a)/2,0,1,1,1,0,0,0,0):UpdateMeshBoundingBox(9992)
AddMesh(9992,9991)
TransformMesh(9991,0,-(centro*longitud+(d-longitud)/2),0,1,1,1,0,0,0,0):UpdateMeshBoundingBox(9991)
If arrow.i=#PB_Any
arrow.i=CreateEntity(#PB_Any,MeshID(9991),MaterialID(9991),0,0,0)
Else
CreateEntity(arrow.i,MeshID(9991),MaterialID(9991),0,0,0)
EndIf
If letra$
CreateText3D(arrow.i,letra$,tipoletra$,1,RGBA(Red(color),Green(color),Blue(color),240))
Text3DAlignment(arrow.i,#PB_Text3D_HorizontallyCentered|#PB_Text3D_Top)
ScaleText3D(arrow.i,grosor*ResizeTextX,grosor*ResizeTextY,longitud*ResizeTextZ,#PB_Relative)
AttachEntityObject(arrow.i,"",Text3DID(arrow.i))
MoveText3D(arrow.i,0,-longitud.f*(centro.f-PosText.f),0,#PB_Local)
EndIf
FreeMesh(9991)
FreeMaterial(9991)
FreeTexture(9991)
ProcedureReturn arrow.i
EndProcedure
Macro AnimarGiroenPropioEjeXYZ(rot,tipoobjeto,objeto,grados,veloc=5)
seno2.d=Pow(Sin(Animaciondiferencial.d),2)
; seno2.d=1-Abs(Cos(Animaciondiferencial.d)); con este va pero el paso no es de #PI/(grados#*2/veloc#). Interesante estudiar esto matemáticamente.
Animaciondiferencial.d+#PI/(grados#*2/veloc#)
If Abs(Animaciondiferencial.d)>=#PI:Animaciondiferencial.d=0:AnimacionPivotCamara.b=0
Else:rot#(tipoobjeto#ID(objeto#),Sign(grados#)*veloc#*seno2.d,#PB_Local|#PB_Relative)
EndIf
EndMacro
Macro OrbitarObjeto1SobreObjeto0(tecla=LeftControl,tipo1=Camera,objeto1=#Camara,tipo0=Node,objeto0=#Pivotcamara); <- el 'objeto1' orbita sobre el 'objeto0', y este debe ser nodo de 'objeto1'
If AnimacionPivotCamara.b
Select TipodeGiro.b
Case 1; pitch 90 grados
AnimarGiroenPropioEjeXYZ(Pitch,tipo0#,objeto0#,Gradosdegiro.d)
Case 2; pitch -90 grados
AnimarGiroenPropioEjeXYZ(Pitch,tipo0#,objeto0#,Gradosdegiro.d)
Case 3; yaw 90 grados
AnimarGiroenPropioEjeXYZ(Yaw,tipo0#,objeto0#,Gradosdegiro.d)
Case 4; yaw -90 grados
AnimarGiroenPropioEjeXYZ(Yaw,tipo0#,objeto0#,Gradosdegiro.d)
Case 5; roll 90 grados
AnimarGiroenPropioEjeXYZ(Roll,tipo0#,objeto0#,Gradosdegiro.d)
Case 6; roll -90 grados
AnimarGiroenPropioEjeXYZ(Roll,tipo0#,objeto0#,Gradosdegiro.d)
EndSelect
Else
If KeyboardPushed(#PB_Key_Pad0)
Rotate#tipo0#(objeto0#,0,0,0,#PB_Absolute)
Move#tipo1#(objeto1#,0,0,9,#PB_Absolute)
EndIf
estadotecla.b=KeyboardPushed(#PB_Key_#tecla#):estadoteclaf.b=KeyEdgeDetection(#PB_Key_#tecla#,estadotecla.b)
If estadoteclaf.b>0; <- inicia control camara
pasocam.f=0.01:pasocamincr.f=0.001
ShowGUI(222,0,#camara,1):CursorX0.f=CursorX.f:CursorY0.f=CursorY.f
ElseIf estadoteclaf.b<0; <- termina control camara
ShowGUI(222,1,#camara,1)
ElseIf estadotecla.b; <- mover el punto de vista
MouseLocate(CursorX0.f,CursorY0.f)
;para desplazar la camara hacia delante, atras, arriba, abajo, izq o der
If DELTA\m
If mmb.b
Move#tipo1#(objeto1#,DELTA\x/40,-DELTA\y/40,0,#PB_Local)
Else
Rotate#tipo0#(objeto0#,-DELTA\y/10,-DELTA\x/10,0,#PB_Relative)
If DELTA\z
Move#tipo1#(objeto1#,0,0,-DELTA\z,#PB_Local)
EndIf
EndIf
ElseIf KeyboardPushed(#PB_Key_Add)
Move#tipo1#(objeto1#,0,0,-pasocam,#PB_Local)
pasocam+pasocamincr
ElseIf KeyboardPushed(#PB_Key_Subtract)
Move#tipo1#(objeto1#,0,0,pasocam,#PB_Local)
pasocam+pasocamincr
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad8)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=-90
AnimacionPivotCamara.b=1:TipodeGiro.b=1
Else
Pitch(tipo0#ID(objeto0#),-0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad2)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=90
AnimacionPivotCamara.b=1:TipodeGiro.b=2
Else
Pitch(tipo0#ID(objeto0#),0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad4)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=-90
AnimacionPivotCamara.b=1:TipodeGiro.b=3
Else
Yaw(tipo0#ID(objeto0#),-0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad6)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=90
AnimacionPivotCamara.b=1:TipodeGiro.b=4
Else
Yaw(tipo0#ID(objeto0#),0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad7)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=-90
AnimacionPivotCamara.b=1:TipodeGiro.b=5
Else
Roll(tipo0#ID(objeto0#),-0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad9)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=90
AnimacionPivotCamara.b=1:TipodeGiro.b=6
Else
Roll(tipo0#ID(objeto0#),0.5,#PB_Local|#PB_Relative)
EndIf
EndIf
EndIf
EndMacro
Macro desplazardesdepuntodevista(entidad)
ConvertLocalToWorldPosition(CameraID(#camara),THETA\x,-THETA\y,THETA\z)
THETA\x=GetX():THETA\y=GetY():THETA\z=GetZ():THETA\m=getmodulo(THETA)
MoveEntity(entidad#,THETA\x,THETA\y,THETA\z,#PB_World|#PB_Relative)
EndMacro
Macro rotardesdepuntodevista(entidad)
Swap THETA\x,THETA\y
ConvertLocalToWorldPosition(CameraID(#camara),THETA\x,THETA\y,THETA\z)
THETA\x=GetX():THETA\y=GetY():THETA\z=GetZ():THETA\m=getmodulo(THETA)
EntityFixedYawAxis(entidad#,1,THETA\x/THETA\m,THETA\y/THETA\m,THETA\z/THETA\m); <- esta funcion interpreta el eje como local
Yaw(EntityID(entidad#),Degree(THETA\m),#PB_World|#PB_Relative)
;EntityFixedYawAxis(entidad#,0)
EndMacro
Global.Vector3D comodin ; comodin para todo
Global.Vector3D DELTA,THETA; para puntero ratón en su uso 2D
Global.D3DXVECTOR3 pick,pickv,pos; <- para usar puntero del ratón para referir elementos 3D
Global.Vector3D eje,ele,ene; <- para linea ortogonal 3D
Global EntidadSeleccionada.i
Macro orientacionyangulos()
; 'fi->' es el ángulo de inclinación de un objeto 3D con respecto a la 'y' global.
; Tras llamar a la función FetchOrientation(), su módulo es |fi->| = 2·ACos(GetW()) , y sus componentes:
; fi\x = GetX()/Sin(|fi->|/2) * |fi->| ( o bien fi\x = GetX()/Sqr(1-GetW()^2) * |fi->| )
; fi\y = GetY()/Sin(|fi->|/2) * |fi->| ( o bien fi\y = GetY()/Sqr(1-GetW()^2) * |fi->| )
; fi\z = GetZ()/Sin(|fi->|/2) * |fi->| ( o bien fi\z = GetZ()/Sqr(1-GetW()^2) * |fi->| )
; 'fi-^' es el vector unidad de 'fi->' y por tanto tiene por componentes ( fi\x/|fi->|, fi\y/|fi->|, fi\z/|fi->| )
fiarrowR.Vector3D
fiarrowG.Vector3D
fiarrowB.Vector3D
FillMemory(@arrowR,SizeOf(Vector3D)):arrowR\y=1
FillMemory(@arrowG,SizeOf(Vector3D)):arrowG\y=1
FillMemory(@arrowB,SizeOf(Vector3D)):arrowB\y=1
FetchOrientation(EntityID(#arrowR),#PB_Absolute)
fiarrowR\m=2*ACos(GetW())
If fiarrowR\m
ww.f=Sin(fiarrowR\m/2)
fiarrowR\x=GetX():fiarrowR\y=GetY():fiarrowR\z=GetZ()
fiarrowR\x*fiarrowR\m/ww:fiarrowR\y*fiarrowR\m/ww:fiarrowR\z*fiarrowR\m/ww
Rotar_Vector3D_por_adicion_Angular(@fiarrowR,@arrowR)
Else
fiarrowR\x=0:fiarrowR\y=0:fiarrowR\z=0
EndIf
FetchOrientation(EntityID(#arrowG),#PB_Absolute)
fiarrowG\m=2*ACos(GetW())
If fiarrowG\m
ww.f=Sin(fiarrowG\m/2)
fiarrowG\x=GetX()*fiarrowG\m/ww:fiarrowG\y=GetY()*fiarrowG\m/ww:fiarrowG\z=GetZ()*fiarrowG\m/ww
Rotar_Vector3D_por_adicion_Angular(@fiarrowG,@arrowG)
Else
fiarrowG\x=0:fiarrowG\y=0:fiarrowG\z=0
EndIf
FetchOrientation(EntityID(#arrowB),#PB_Absolute)
fiarrowB\m=2*ACos(GetW())
If fiarrowB\m
ww.f=Sin(fiarrowB\m/2)
fiarrowB\x=GetX()*fiarrowB\m/ww:fiarrowB\y=GetY()*fiarrowB\m/ww:fiarrowB\z=GetZ()*fiarrowB\m/ww
Rotar_Vector3D_por_adicion_Angular(@fiarrowB,@arrowB)
Else
fiarrowB\x=0:fiarrowB\y=0:fiarrowB\z=0
EndIf
; flechaR\x=EntityDirectionX(#flechaR):flechaR\y=EntityDirectionY(#flechaR):flechaR\z=EntityDirectionZ(#flechaR); <- resultados incorrectos
; flechaG\x=EntityDirectionX(#flechaG):flechaG\y=EntityDirectionY(#flechaG):flechaG\z=EntityDirectionZ(#flechaG); <- resultados incorrectos
; flechaB\x=EntityDirectionX(#flechaB):flechaB\y=EntityDirectionY(#flechaB):flechaB\z=EntityDirectionZ(#flechaB); <- resultados incorrectos
AnguloFormadoPor2Vectores(arrowR,arrowG,comodin)
Text3DCaption(#texto1,"Global Orientation of R: "+StrF(arrowR\x,2)+","+StrF(arrowR\y,2)+","+StrF(arrowR\z,2)+#LFCR$+
"Global Orientation of G: "+StrF(arrowG\x,2)+","+StrF(arrowG\y,2)+","+StrF(arrowG\z,2)+#LFCR$+
"Global Orientation of B: "+StrF(arrowB\x,2)+","+StrF(arrowB\y,2)+","+StrF(arrowB\z,2)+#LFCR$+
"Total angle between R and G: "+StrF(Degree(comodin\m),2)+"º")
EndMacro
CreateLight(#luz,$EEEEEE,4,4,2,#PB_Light_Point):SetLightColor(#luz,#PB_Light_DiffuseColor,$EEEEEE):MoveLight(#luz,4,4,2,#PB_Absolute)
CreateCamera(#camara,0,0,100,100):CreateNode(#pivotcamara,0,0,0):AttachNodeObject(#pivotcamara,CameraID(#camara)):CameraRange(#camara,0.1,1E4):MoveCamera(#camara,0,0,9,#PB_Absolute)
SkyBox("desert07.jpg")
;
arrowR.Vector3D:arrowG.Vector3D:arrowB.Vector3D
FillMemory(@arrowR,SizeOf(Vector3D)):arrowR\x=1
FillMemory(@arrowG,SizeOf(Vector3D)):arrowG\y=1
FillMemory(@arrowB,SizeOf(Vector3D)):arrowB\z=-1
arrow(#arrowR,$AA7A8BF9,0,0.075,2,"R","StarWars",0.5,2,2.25,1/30):EntityDirection(#arrowR,arrowR\x,arrowR\y,arrowR\z,#PB_Absolute|#PB_World,#PB_Vector_Y)
arrow(#arrowG,$AAAAF9BB,0,0.075,2,"G","StarWars",0.5,2,2.25,1/30):EntityDirection(#arrowG,arrowG\x,arrowG\y,arrowG\z,#PB_Absolute|#PB_World,#PB_Vector_Y)
arrow(#arrowB,$AAFEAAA3,0,0.075,2,"B","StarWars",0.5,2,2.25,1/30):EntityDirection(#arrowB,arrowB\x,arrowB\y,arrowB\z,#PB_Absolute|#PB_World,#PB_Vector_Y)
CreateText3D(#texto1,"epale!","",1,$DDDDDDDD)
Text3DAlignment(#texto1,#PB_Text3D_HorizontallyCentered|#PB_Text3D_Top)
ScaleText3D(#texto1,0.3,0.4,0.1,#PB_Relative)
AttachNodeObject(#Pivotcamara,Text3DID(#texto1))
MoveText3D(#texto1,-3,2,0,#PB_Absolute|#PB_World)
orientacionyangulos()
EntidadSeleccionada.i=-1
ShowGUI(222,1,#camara,1)
Repeat
Repeat:evento.i=WindowEvent():Until evento=#PB_Event_None
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)
DELTA\x=MouseDeltaX():DELTA\y=MouseDeltaY():DELTA\z=MouseWheel():DELTA\m=getmodulo(DELTA)
wCursorX.f=WindowMouseX(#ventana):wCursorY.f=WindowMouseY(#ventana)
OrbitarObjeto1SobreObjeto0(LeftControl,Camera,#camara,Node,#Pivotcamara)
InputEvent3D(CursorX.f,CursorY.f,lmb.b)
lmbe.b=MouseButtonEdgeDetection(#PB_MouseButton_Left,lmb)
mmbe.b=MouseButtonEdgeDetection(#PB_MouseButton_Middle,mmb)
If lmbe.b=1 Or mmbe.b=1
ShowGUI(222,0,#camara,1)
EntidadSeleccionada.i=MouseRayCast(#camara,CursorX,CursorY,-1)
Select EntidadSeleccionada.i
Case #arrowR:EntidadSeleccionada$="arrowR"
Case #arrowG:EntidadSeleccionada$="arrowG"
Case #arrowB:EntidadSeleccionada$="arrowB"
Default:EntidadSeleccionada$=""
EndSelect
If EntidadSeleccionada$
anchuratexto.u=Len(EntidadSeleccionada$)*14
pick\x=PickX():pick\y=PickY():pick\z=PickZ()
pos\x=EntityX(EntidadSeleccionada,#PB_Absolute):pos\y=EntityY(EntidadSeleccionada,#PB_Absolute):pos\z=EntityZ(EntidadSeleccionada,#PB_Absolute)
pick=pos
OpenWindow3D(#TextoInfoObjeto,CameraProjectionX(#camara,pick\x,pick\y,pick\z),CameraProjectionY(#camara,pick\x,pick\y,pick\z),anchuratexto.u,32,"detalles objeto",#PB_Window3D_SizeGadget|#PB_Window3D_BorderLess)
TextGadget3D(#TextoInfoObjeto,0,-1,anchuratexto.u,32,EntidadSeleccionada$)
EndIf
ElseIf lmbe.b=-1 Or mmbe.b=-1
ShowGUI(222,1,#camara,1)
If EntidadSeleccionada$
pos\x=EntityX(EntidadSeleccionada,#PB_Absolute):pos\y=EntityY(EntidadSeleccionada,#PB_Absolute):pos\z=EntityZ(EntidadSeleccionada,#PB_Absolute)
MouseLocate(CameraProjectionX(#camara,pos\x,pos\y,pos\z),CameraProjectionY(#camara,pos\x,pos\y,pos\z))
If IsWindow3D(#TextoInfoObjeto)
FreeGadget3D(#PB_All)
CloseWindow3D(#TextoInfoObjeto)
EndIf
EntidadSeleccionada$=""
EndIf
EndIf
If DELTA\m And EntidadSeleccionada$ And IsWindow3D(#TextoInfoObjeto)
THETA=DELTA:THETA\x/100:THETA\y/100:THETA\z/20:THETA\m=getmodulo(THETA)
If lmb.b; mover
pos\x=EntityX(EntidadSeleccionada,#PB_Absolute):pos\y=EntityY(EntidadSeleccionada,#PB_Absolute):pos\z=EntityZ(EntidadSeleccionada,#PB_Absolute)
pick\x=CameraProjectionX(#camara,pos\x,pos\y,pos\z);+pickv\x
pick\y=CameraProjectionY(#camara,pos\x,pos\y,pos\z);+pickv\y
ResizeWindow3D(#TextoInfoObjeto,pick\x,pick\y,anchuratexto.u,#PB_Ignore)
desplazardesdepuntodevista(EntidadSeleccionada); <- mover
ElseIf mmb.b; rotar
rotardesdepuntodevista(EntidadSeleccionada)
orientacionyangulos()
EndIf
EndIf
TimeSinceLastFrame.i=RenderWorld(50)
FlipBuffers()
; StartDrawing(WindowOutput(#ventana))
; DrawText(0,RY-80,"res: "+StrU(RX)+","+StrU(RY))
; DrawText(0,RY-60,"scr: "+StrF(CursorX,2)+","+StrF(CursorY,2))
; DrawText(0,RY-40,"win: "+StrF(wCursorX,2)+","+StrF(wCursorY,2))
; StopDrawing()
Delay(6)
Until KeyboardPushed(#PB_Key_Escape)