Page 1 of 1

[Solved]: Get X or Y reference from camera frontal view

Posted: Mon Mar 04, 2019 1:43 pm
by Psychophanta
Hi,
we can access to a front view vector via:
CameraDirectionX(), CameraDirectionY() and CameraDirectionZ()
So, we can get the front (Z) vector.

Is there any native function, trick or workaround to get also its 'X' and/or its 'Y' vector?

Thanks in advance !

Re: Question: Get X or Y reference from camera frontal view

Posted: Fri Mar 08, 2019 6:30 pm
by Comtois
AxisX = orientation * UnitX
AxisY = orientation * UnitY
AxisZ = orientation * -UnitZ

Code: Select all

#CameraSpeed = 2

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY

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

Structure quaternion Extends Vector3
  w.f
EndStructure  

Declare QmV(*R.Vector3, *Q.Quaternion, *V.Vector3) 

Define.Vector3 UnitX, UnitY, UnitZ,AxisX, AxisY, AxisZ
Define.quaternion q

UnitX\x=1 : UnitX\y=0 : UnitX\z=0
UnitY\x=0 : UnitY\y=1 : UnitY\z=0
UnitZ\x=0 : UnitZ\y=0 : UnitZ\z=-1

If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    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/Scripts", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/skybox.zip", #PB_3DArchive_Zip)
    Parse3DScripts()
    
    ; First create materials
    ;
    
    GrassMaterial = CreateMaterial(#PB_Any, TextureID(LoadTexture(#PB_Any,"grass1.png")))
    MaterialBlendingMode(GrassMaterial, #PB_Material_AlphaBlend)
    DirtMaterial = CreateMaterial(#PB_Any, TextureID(LoadTexture(#PB_Any,"Dirt.jpg")))
    
    
    ; Then create the billboard group and use the previous material
    ;
    ;-Billboard
    
    Billboard = CreateBillboardGroup(#PB_Any, MaterialID(GrassMaterial), 96, 96, 0, 0, 0, -1, 1)
    BillboardGroupCommonDirection(Billboard, 0, 1, 0)
    
    For i = 0 To 600
      AddBillboard(Billboard, Random(2000)-1000, Random(18) + 30, Random(2000) - 1000)
    Next i
    
    ; create ground
    
    MeshPlane = CreatePlane(#PB_Any, 2000, 2000, 40, 40, 4, 4)
    CreateEntity(#PB_Any, MeshID(MeshPlane), MaterialID(DirtMaterial))
    
    ; Add house
    MeshHouse = LoadMesh(#PB_Any, "tudorhouse.mesh")
    House = CreateEntity(#PB_Any, MeshID(MeshHouse), #PB_Material_None, 0, 280, 0)
    ScaleEntity(House, 0.5, 0.5, 0.5)
    
    ; SkyBox
    SkyBox("stevecube.jpg")
    
    ; create camera
    Camera = CreateCamera(#PB_Any, 0, 0, 100, 100)
    MoveCamera(Camera, 200, 400, 900, #PB_Absolute)
    CameraLookAt(Camera, 0, 100, 0)
    
    Repeat
      Screen3DEvents()
      
      If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 0.05
        MouseY = -MouseDeltaY() * #CameraSpeed * 0.05
      EndIf
      
      If ExamineKeyboard()
        
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed 
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed 
        Else
          KeyY = 0
        EndIf
        
      EndIf
      
      RotateCamera(Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera  (Camera, KeyX, 0, KeyY)
      
      
      FetchOrientation(CameraID(Camera))
      q\x = GetX()
      q\y = GetY()
      q\z = GetZ()
      q\w = GetW()
      
      Qmv(@AxisX, @q, @UnitX)
      Qmv(@AxisY, @q, @UnitY)
      Qmv(@AxisZ, @q, @UnitZ)
      
      Debug CameraDirectionX(Camera)
      Debug CameraDirectionY(Camera)
      Debug CameraDirectionZ(Camera)
      Debug "--"
      Debug AxisZ\x
      Debug AxisZ\Y
      Debug AxisZ\Z
      Debug "*****"
      
      
      RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf

End


Macro CROSS_PRODUCT(N, V1, V2)
  N\x = ((V1\y * V2\z) - (V1\z * V2\y))
  N\y = ((V1\z * V2\x) - (V1\x * V2\z))
  N\z = ((V1\x * V2\y) - (V1\y * V2\x))
EndMacro

; Vector3 = Quaternion * Vector3
Procedure QmV(*R.Vector3, *Q.Quaternion, *V.Vector3) 
  ; nVidia SDK implementation
  Protected.Vector3 uv, uuv 
  CROSS_PRODUCT(uv, *Q, *V)
  CROSS_PRODUCT(uuv, *Q, uv)
  uv\x * (2.0 * *Q\w)
  uv\y * (2.0 * *Q\w)
  uv\z * (2.0 * *Q\w)
  uuv\x * 2.0
  uuv\y * 2.0 
  uuv\z * 2.0  
  *R\x = *V\x + uv\x + uuv\x 
  *R\y = *V\y + uv\y + uuv\y 
  *R\z = *V\z + uv\z + uuv\z 
EndProcedure

Re: Question: Get X or Y reference from camera frontal view

Posted: Fri Mar 08, 2019 7:14 pm
by Psychophanta
@Comtois, you again retrieve the 'Z' vector.

Question is:
Is there any native function, trick or workaround to get also its 'X' and/or its 'Y' vector?

Re: Question: Get X or Y reference from camera frontal view

Posted: Fri Mar 08, 2019 8:07 pm
by Comtois
and answer is :

AxisX = orientation * UnitX
AxisY = orientation * UnitY
AxisZ = orientation * -UnitZ

May be i should write

Vector X = orientation * UnitX
Vector Y = orientation * UnitY
Vector Z = orientation * -UnitZ

Re: Question: Get X or Y reference from camera frontal view

Posted: Sat Mar 09, 2019 9:55 am
by Psychophanta
Question is not that.
Is not about front vector, nor back vector, but "up" and "right" vectors of the object.

Re: Question: Get X or Y reference from camera frontal view

Posted: Sat Mar 09, 2019 11:18 am
by Comtois
you are disturbed by the debug, it was to control the result of the Qmv() Procedure.

Either, I modified my code to highlight the 3 axes.

Code: Select all

#CameraSpeed = 2

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY

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

Structure quaternion Extends Vector3
  w.f
EndStructure  

Declare QmV(*R.Vector3, *Q.Quaternion, *V.Vector3) 

Define.Vector3 UnitX, UnitY, UnitZ,AxisX, AxisY, AxisZ
Define.quaternion q

UnitX\x=1 : UnitX\y=0 : UnitX\z=0
UnitY\x=0 : UnitY\y=1 : UnitY\z=0
UnitZ\x=0 : UnitZ\y=0 : UnitZ\z=-1

If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    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/Scripts", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/skybox.zip", #PB_3DArchive_Zip)
    Parse3DScripts()
    
    ; First create materials
    ;
    
    GrassMaterial = CreateMaterial(#PB_Any, TextureID(LoadTexture(#PB_Any,"grass1.png")))
    MaterialBlendingMode(GrassMaterial, #PB_Material_AlphaBlend)
    DirtMaterial = CreateMaterial(#PB_Any, TextureID(LoadTexture(#PB_Any,"Dirt.jpg")))
    
    
    ; Then create the billboard group and use the previous material
    ;
    ;-Billboard
    
    Billboard = CreateBillboardGroup(#PB_Any, MaterialID(GrassMaterial), 96, 96, 0, 0, 0, -1, 1)
    BillboardGroupCommonDirection(Billboard, 0, 1, 0)
    
    For i = 0 To 600
      AddBillboard(Billboard, Random(2000)-1000, Random(18) + 30, Random(2000) - 1000)
    Next i
    
    ; create ground
    
    MeshPlane = CreatePlane(#PB_Any, 2000, 2000, 40, 40, 4, 4)
    CreateEntity(#PB_Any, MeshID(MeshPlane), MaterialID(DirtMaterial))
    
    ; Add house
    MeshHouse = LoadMesh(#PB_Any, "tudorhouse.mesh")
    House = CreateEntity(#PB_Any, MeshID(MeshHouse), #PB_Material_None, 0, 280, 0)
    ScaleEntity(House, 0.5, 0.5, 0.5)
    
    ; SkyBox
    SkyBox("stevecube.jpg")
    
    ; create camera
    Camera = CreateCamera(#PB_Any, 0, 0, 100, 100)
    MoveCamera(Camera, 200, 400, 900, #PB_Absolute)
    CameraLookAt(Camera, 0, 100, 0)
    
    ; create camera
    Camera2 = CreateCamera(#PB_Any, 0, 0, 20, 20)
    MoveCamera(Camera2, 280, 240, 90, #PB_Absolute)
    CameraLookAt(Camera2, 0, 100, 0)
    
    d=100
    Repeat
      Screen3DEvents()
      
      If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 0.05
        MouseY = -MouseDeltaY() * #CameraSpeed * 0.05
      EndIf
      
      If ExamineKeyboard()
        
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed 
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed 
        Else
          KeyY = 0
        EndIf
        
      EndIf
      
      RotateCamera(Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera  (Camera, KeyX, 0, KeyY)
      
      FetchOrientation(CameraID(Camera2))
      q\x = GetX()
      q\y = GetY()
      q\z = GetZ()
      q\w = GetW()
      
      Qmv(@AxisX, @q, @UnitX)
      Qmv(@AxisY, @q, @UnitY)
      Qmv(@AxisZ, @q, @UnitZ)
      
      CreateLine3D(0, CameraX(Camera2), CameraY(Camera2), CameraZ(Camera2), RGB(255,0,0), CameraX(Camera2) + AxisX\x*d, CameraY(Camera2) + AxisX\y*d, CameraZ(Camera2) + AxisX\z*d, RGB(255,0,0))
      CreateLine3D(1, CameraX(Camera2), CameraY(Camera2), CameraZ(Camera2), RGB(0,255,0), CameraX(Camera2) + AxisY\x*d, CameraY(Camera2) + AxisY\y*d, CameraZ(Camera2) + AxisY\z*d, RGB(0,255,0))
      CreateLine3D(2, CameraX(Camera2), CameraY(Camera2), CameraZ(Camera2), RGB(0,0,255), CameraX(Camera2) + AxisZ\x*d, CameraY(Camera2) + AxisZ\y*d, CameraZ(Camera2) + AxisZ\z*d, RGB(0,0,255))      
      
      
      RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf

End


Macro CROSS_PRODUCT(N, V1, V2)
  N\x = ((V1\y * V2\z) - (V1\z * V2\y))
  N\y = ((V1\z * V2\x) - (V1\x * V2\z))
  N\z = ((V1\x * V2\y) - (V1\y * V2\x))
EndMacro

; Vector3 = Quaternion * Vector3
Procedure QmV(*R.Vector3, *Q.Quaternion, *V.Vector3) 
  ; nVidia SDK implementation
  Protected.Vector3 uv, uuv 
  CROSS_PRODUCT(uv, *Q, *V)
  CROSS_PRODUCT(uuv, *Q, uv)
  uv\x * (2.0 * *Q\w)
  uv\y * (2.0 * *Q\w)
  uv\z * (2.0 * *Q\w)
  uuv\x * 2.0
  uuv\y * 2.0 
  uuv\z * 2.0  
  *R\x = *V\x + uv\x + uuv\x 
  *R\y = *V\y + uv\y + uuv\y 
  *R\z = *V\z + uv\z + uuv\z 
EndProcedure

Re: Question: Get X or Y reference from camera frontal view

Posted: Sat Mar 09, 2019 11:58 pm
by Psychophanta
I see now, nice. :D

Anyway, I can see that the way i am using now for it is easier, perhaps uglier, BUT more efficient, because looks like it makes use of less computing resources (less CPU speed resource and less memory for variables).

Code: Select all

#CameraSpeed = 2

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY

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

Define.Vector3 AxisX, AxisY, AxisZ

If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    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/Scripts", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/skybox.zip", #PB_3DArchive_Zip)
    Parse3DScripts()
    
    ; First create materials
    ;
    
    GrassMaterial = CreateMaterial(#PB_Any, TextureID(LoadTexture(#PB_Any,"grass1.png")))
    MaterialBlendingMode(GrassMaterial, #PB_Material_AlphaBlend)
    DirtMaterial = CreateMaterial(#PB_Any, TextureID(LoadTexture(#PB_Any,"Dirt.jpg")))
    
    
    ; Then create the billboard group and use the previous material
    ;
    ;-Billboard
    
    Billboard = CreateBillboardGroup(#PB_Any, MaterialID(GrassMaterial), 96, 96, 0, 0, 0, -1, 1)
    BillboardGroupCommonDirection(Billboard, 0, 1, 0)
    
    For i = 0 To 600
      AddBillboard(Billboard, Random(2000)-1000, Random(18) + 30, Random(2000) - 1000)
    Next i
    
    ; create ground
    
    MeshPlane = CreatePlane(#PB_Any, 2000, 2000, 40, 40, 4, 4)
    CreateEntity(#PB_Any, MeshID(MeshPlane), MaterialID(DirtMaterial))
    
    ; Add house
    MeshHouse = LoadMesh(#PB_Any, "tudorhouse.mesh")
    House = CreateEntity(#PB_Any, MeshID(MeshHouse), #PB_Material_None, 0, 280, 0)
    ScaleEntity(House, 0.5, 0.5, 0.5)
    
    ; SkyBox
    SkyBox("stevecube.jpg")
    
    ; create camera
    Camera = CreateCamera(#PB_Any, 0, 0, 100, 100)
    MoveCamera(Camera, 200, 400, 900, #PB_Absolute)
    CameraLookAt(Camera, 0, 100, 0)
    
    ; create camera
    Camera2 = CreateCamera(#PB_Any, 0, 0, 20, 20)
    MoveCamera(Camera2, 280, 240, 90, #PB_Absolute)
    CameraLookAt(Camera2, 0, 100, 0)
Macro CROSS_PRODUCT(N, V1, V2)
  N\x = ((V1\y * V2\z) - (V1\z * V2\y))
  N\y = ((V1\z * V2\x) - (V1\x * V2\z))
  N\z = ((V1\x * V2\y) - (V1\y * V2\x))
EndMacro
Macro getbase()
  RotateCamera(Camera2,90,0,0,#PB_Relative)
  AxisY\x=CameraDirectionX(Camera2):AxisY\y=CameraDirectionY(Camera2):AxisY\z=CameraDirectionZ(Camera2)
  RotateCamera(Camera2,270,0,0,#PB_Relative)
  AxisZ\x=CameraDirectionX(Camera2):AxisZ\y=CameraDirectionY(Camera2):AxisZ\z=CameraDirectionZ(Camera2)
  CROSS_PRODUCT(AxisX,AxisZ,AxisY)
EndMacro
    d=100
    Repeat
      Screen3DEvents()
      If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 0.05
        MouseY = -MouseDeltaY() * #CameraSpeed * 0.05
      EndIf
      If ExamineKeyboard()
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed 
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed 
        Else
          KeyY = 0
        EndIf
      EndIf
      RotateCamera(Camera2, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera  (Camera2, KeyX, 0, KeyY)
      getbase()
      CreateLine3D(0, CameraX(Camera2), CameraY(Camera2), CameraZ(Camera2), RGB(255,0,0), CameraX(Camera2) + AxisX\x*d, CameraY(Camera2) + AxisX\y*d, CameraZ(Camera2) + AxisX\z*d, RGB(255,0,0))
      CreateLine3D(1, CameraX(Camera2), CameraY(Camera2), CameraZ(Camera2), RGB(0,255,0), CameraX(Camera2) + AxisY\x*d, CameraY(Camera2) + AxisY\y*d, CameraZ(Camera2) + AxisY\z*d, RGB(0,255,0))
      CreateLine3D(2, CameraX(Camera2), CameraY(Camera2), CameraZ(Camera2), RGB(0,0,255), CameraX(Camera2) + AxisZ\x*d, CameraY(Camera2) + AxisZ\y*d, CameraZ(Camera2) + AxisZ\z*d, RGB(0,0,255))      
      
      RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End

Re: [Solved]: Get X or Y reference from camera frontal view

Posted: Sun Mar 10, 2019 10:49 am
by Comtois
Maybe it's better like that

Code: Select all

Macro getbase()
  AxisY\x=0:AxisY\y=1:AxisY\z=0
  AxisZ\x=CameraDirectionX(Camera2):AxisZ\y=CameraDirectionY(Camera2):AxisZ\z=CameraDirectionZ(Camera2)
  AxisZ2\x=-AxisZ\x : AxisZ2\y=-AxisZ\y : AxisZ2\z=-AxisZ\z 
  CROSS_PRODUCT(AxisX,AxisY,AxisZ2)
  CROSS_PRODUCT(AxisY,AxisZ2,AxisX)
EndMacro
note that the function Qmv() allows to obtain the position in the world of a local point. It's a more general function.

Code: Select all

Procedure ConvertLocalToWorld(*WorldPosition.Vector3, *LocalPoint.Vector3)
  Protected.Vector3 p
  Protected.quaternion q
  
  FetchOrientation(CameraID(Camera2)) ; Or Node or Entity
  q\x = GetX()
  q\y = GetY()
  q\z = GetZ()
  q\w = GetW()
  
  QmV(@p, *q, *LocalPoint)
  
  *WorldPosition\x = p\x + CameraX(Camera2)  
  *WorldPosition\y = p\y + CameraY(Camera2)
  *WorldPosition\z = p\z + CameraZ(Camera2)
EndProcedure

Re: [Solved]: Get X or Y reference from camera frontal view

Posted: Sun Mar 10, 2019 10:59 pm
by Psychophanta
Comtois wrote:Maybe it's better like that

Code: Select all

Macro getbase()
  AxisY\x=0:AxisY\y=1:AxisY\z=0
  AxisZ\x=CameraDirectionX(Camera2):AxisZ\y=CameraDirectionY(Camera2):AxisZ\z=CameraDirectionZ(Camera2)
  AxisZ2\x=-AxisZ\x : AxisZ2\y=-AxisZ\y : AxisZ2\z=-AxisZ\z 
  CROSS_PRODUCT(AxisX,AxisY,AxisZ2)
  CROSS_PRODUCT(AxisY,AxisZ2,AxisX)
EndMacro
This one does not work well. Just try yourself and you will see.
And by the way, AxisZ2 creation is nonsense, so the equivalent of that macro is:

Code: Select all

Macro getbase()
  AxisY\x=0:AxisY\y=1:AxisY\z=0
  AxisZ\x=CameraDirectionX(Camera2):AxisZ\y=CameraDirectionY(Camera2):AxisZ\z=CameraDirectionZ(Camera2)
  CROSS_PRODUCT(AxisX,AxisZ,AxisY)
  CROSS_PRODUCT(AxisY,AxisX,AxisZ)
EndMacro

Re: [Solved]: Get X or Y reference from camera frontal view

Posted: Mon Mar 11, 2019 9:37 am
by Comtois
what is nonsense is to try to answer you.

Re: [Solved]: Get X or Y reference from camera frontal view

Posted: Mon Mar 11, 2019 2:46 pm
by Psychophanta
Comtois wrote:what is nonsense is to try to answer you.
Well, the thing I told is a true; the use of that variable is absurd, nonsense. If it is not true, demonstrate it.

Also this Macro is a nonsense. Else check it and tell us if is or not:

Code: Select all

Macro getbase1(); <- Does not work correct !
  Base\y\x=0:Base\y\y=1:Base\y\z=0
  Base\z\x=CameraDirectionX(#Camara):Base\z\y=CameraDirectionY(#Camara):Base\z\z=CameraDirectionZ(#Camara)
  ProductoVectorial(Base\z,Base\y,Base\x):m.f=getmodulo(Base\x):Base\x\x/m:Base\x\y/m:Base\x\z/m
  ProductoVectorial(Base\x,Base\z,Base\y)
EndMacro
Tip to test 3 'getbase' different functions: 2 of them work correct, the other one does not (use wheelmouse to test in the tip), so, it is nonsense while nobody demonstrates at least 1 only sense for it.

Code: Select all

#CameraSpeed = 2
#Camara=2
IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"
Define.f KeyX, KeyY, MouseX, MouseY, MouseZ
Structure D3DXVECTOR3
  x.f
  y.f
  z.f
EndStructure
Structure Vector3D Extends D3DXVECTOR3
  m.f;<-length(modulo)
EndStructure
Structure cuaternio Extends D3DXVECTOR3
  w.f
EndStructure
Structure Vector9D
  x.D3DXVECTOR3
  y.D3DXVECTOR3
  z.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 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 QmV(*Q.cuaternio,*V.Vector3D,*R.Vector3D)
  ; Vector3=Quaternion*Vector3
  Protected uv.Vector3D,uuv.Vector3D
  ProductoVectorial(*Q,*V,uv)
  ProductoVectorial(*Q,uv,uuv)
  uv\x*(2.0**Q\w)
  uv\y*(2.0**Q\w)
  uv\z*(2.0**Q\w)
  uuv\x*2.0
  uuv\y*2.0
  uuv\z*2.0
  *R\x=*V\x+uv\x+uuv\x
  *R\y=*V\y+uv\y+uuv\y
  *R\z=*V\z+uv\z+uuv\z
EndProcedure
Procedure ConvertLocalToWorld(*WorldPosition.Vector3D,*LocalPoint.Vector3D)
  Protected p.Vector3D,q.cuaternio
  FetchOrientation(CameraID(#Camara)):q\x=GetX():q\y=GetY():q\z=GetZ():q\w=GetW()
  QmV(*q,*LocalPoint,@p)
  *WorldPosition\x=p\x+CameraX(#Camara):*WorldPosition\y=p\y+CameraY(#Camara):*WorldPosition\z=p\z+CameraZ(#Camara)
EndProcedure
Base.Vector9D
q.cuaternio
Unit.Vector9D
Unit\x\x=1:Unit\x\y=0:Unit\x\z=0
Unit\y\x=0:Unit\y\y=1:Unit\y\z=0
Unit\z\x=0:Unit\z\y=0:Unit\z\z=-1

If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    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/Scripts", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/skybox.zip", #PB_3DArchive_Zip)
    Parse3DScripts()
    
    ; First create materials
    ;
    
    GrassMaterial = CreateMaterial(#PB_Any, TextureID(LoadTexture(#PB_Any,"grass1.png")))
    MaterialBlendingMode(GrassMaterial, #PB_Material_AlphaBlend)
    DirtMaterial = CreateMaterial(#PB_Any, TextureID(LoadTexture(#PB_Any,"Dirt.jpg")))
    
    
    ; Then create the billboard group and use the previous material
    ;
    ;-Billboard
    
    Billboard = CreateBillboardGroup(#PB_Any, MaterialID(GrassMaterial), 96, 96, 0, 0, 0, -1, 1)
    BillboardGroupCommonDirection(Billboard, 0, 1, 0)
    
    For i = 0 To 600
      AddBillboard(Billboard, Random(2000)-1000, Random(18) + 30, Random(2000) - 1000)
    Next i
    
    ; create ground
    
    MeshPlane = CreatePlane(#PB_Any, 2000, 2000, 40, 40, 4, 4)
    CreateEntity(#PB_Any, MeshID(MeshPlane), MaterialID(DirtMaterial))
    
    ; Add house
    MeshHouse = LoadMesh(#PB_Any, "tudorhouse.mesh")
    House = CreateEntity(#PB_Any, MeshID(MeshHouse), #PB_Material_None, 0, 280, 0)
    ScaleEntity(House, 0.5, 0.5, 0.5)
    
    ; SkyBox
    SkyBox("stevecube.jpg")
    
    ; create camera
    Camera = CreateCamera(#PB_Any, 0, 0, 100, 100)
    MoveCamera(Camera, 200, 400, 900, #PB_Absolute)
    CameraLookAt(Camera, 0, 100, 0)
    
    ; create camera
    CreateCamera(#Camara, 0, 0, 20, 20)
    MoveCamera(#Camara, 280, 240, 90, #PB_Absolute)
    CameraLookAt(#Camara, 0, 100, 0)

    d=100
    Repeat
      Screen3DEvents()
      If ExamineMouse()
        MouseX = MouseDeltaX() * #CameraSpeed * 0.05
        MouseY = MouseDeltaY() * #CameraSpeed * 0.05
        MouseZ = MouseWheel()*10
      EndIf
      If ExamineKeyboard()
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed 
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed 
        Else
          KeyY = 0
        EndIf
      EndIf
      RotateCamera(#Camara, MouseY, MouseX,MouseZ, #PB_Relative)
      MoveCamera(#Camara, KeyX, 0, KeyY)
Macro getbase(); <- works correct !
  Pitch(CameraID(#Camara),90,#PB_Local)
  Base\y\x=CameraDirectionX(#Camara):Base\y\y=CameraDirectionY(#Camara):Base\y\z=CameraDirectionZ(#Camara)
  Pitch(CameraID(#Camara),270,#PB_Local)
  Base\z\x=CameraDirectionX(#Camara):Base\z\y=CameraDirectionY(#Camara):Base\z\z=CameraDirectionZ(#Camara)
  ProductoVectorial(Base\z,Base\y,Base\x)
EndMacro
Macro getbase1(); <- Does not work correct !
  Base\y\x=0:Base\y\y=1:Base\y\z=0
  Base\z\x=CameraDirectionX(#Camara):Base\z\y=CameraDirectionY(#Camara):Base\z\z=CameraDirectionZ(#Camara)
  ProductoVectorial(Base\z,Base\y,Base\x):m.f=getmodulo(Base\x):Base\x\x/m:Base\x\y/m:Base\x\z/m
  ProductoVectorial(Base\x,Base\z,Base\y)
EndMacro
Macro getbaseq(); <- works correct !
  FetchOrientation(CameraID(#Camara)):q\x=GetX():q\y=GetY():q\z=GetZ():q\w=GetW()
  Qmv(@q,@Unit\x,@Base\x)
  Qmv(@q,@Unit\y,@Base\y)
  Qmv(@q,@Unit\z,@Base\z)
EndMacro
getbase()
      CreateLine3D(0, CameraX(#Camara), CameraY(#Camara), CameraZ(#Camara), RGB(255,0,0), CameraX(#Camara) + Base\x\x*d, CameraY(#Camara) + Base\x\y*d, CameraZ(#Camara) + Base\x\z*d, RGB(255,0,0))
      CreateLine3D(1, CameraX(#Camara), CameraY(#Camara), CameraZ(#Camara), RGB(0,255,0), CameraX(#Camara) + Base\y\x*d, CameraY(#Camara) + Base\y\y*d, CameraZ(#Camara) + Base\y\z*d, RGB(0,255,0))
      CreateLine3D(2, CameraX(#Camara), CameraY(#Camara), CameraZ(#Camara), RGB(0,0,255), CameraX(#Camara) + Base\z\x*d, CameraY(#Camara) + Base\z\y*d, CameraZ(#Camara) + Base\z\z*d, RGB(0,0,255))      
      
      RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End