ich beschäftige mich gerade mit dem 3D Part von Purebasic. Aktuell mit Kollisionen, ich habe folgendes Tutorial im Netz gefunden: http://www.neobrothers.de/oldpage1/tuto ... ision.html
Ich fand das ganz gut erklärt, die Funktionen die dort verwendet wurden findet man im MSDN erklärt (http://msdn.microsoft.com/en-us/library ... 85%29.aspx).
Bei der Umsetzung meinerseits hakt es aber gewaltig, anstatt das Ergebnis zu bekommen, das der Punkt in der Box liegt, bekomme ich den Rückgabewert vor welcher Seite er liegt, siehe hier:
Code: Alles auswählen
EnableExplicit
Structure fVector3D
x.f
y.f
z.f
EndStructure
Structure Box3D
Array p.fVector3D(7)
EndStructure
Structure Model3DHandle
hTex.i
hMat.i
hMsh.i
hEnt.i
EndStructure
Define.i hLine, hCam, WindowEvt, MouseMoveX, MouseMoveY, DoLoop = #True
Define.fVector3D p1, p2
Define.Model3DHandle plane1, plane2, plane3
Define.Box3D box
Macro Do(Status, Error, EndProgram = #True)
If Not Status
CompilerIf #PB_Compiler_Debugger
Debug "ERROR: " + Error
CompilerElse
MessageRequester("ERROR", Error)
CompilerEndIf
CompilerIf EndProgram
End
CompilerEndIf
EndIf
EndMacro
Macro PrintV(v)
Debug "x="+StrF(v\x,1)+", y="+StrF(v\y,1)+", z="+StrF(v\z,1)
EndMacro
Procedure VectorSub(*v1.fVector3D, *v2.fVector3D, *result.fVector3D)
*result\x = *v1\x - *v2\x
*result\y = *v1\y - *v2\y
*result\z = *v1\z - *v2\z
EndProcedure
Procedure VectorCross(*v1.fVector3D, *v2.fVector3D, *result.fVector3D)
*result\x = (*v1\y * *v2\z) - (*v1\z * *v2\y)
*result\y = (*v1\z * *v2\x) - (*v1\x * *v2\z)
*result\z = (*v1\x * *v2\y) - (*v1\y * *v2\x)
EndProcedure
Procedure.f VectorDot(*v1.fVector3D, *v2.fVector3D)
ProcedureReturn (*v1\x * *v2\x) + (*v1\y * *v2\y) + (*v1\z * *v2\z)
EndProcedure
Procedure VectorNormalize(*v1.fVector3D)
Protected length.f = Sqr((*v1\x * *v1\x) + (*v1\y * *v1\y) + (*v1\x * *v1\z))
*v1\x = *v1\x / length
*v1\y = *v1\y / length
*v1\z = *v1\z / length
EndProcedure
Procedure BallBlock_Collision(*box.Box3D, *point.fVector3D)
Protected.i collide = 0
Protected.fVector3D normal, result1, result2, result3
; bottom
If collide = 0
VectorSub(*box\p(1), *box\p(0), result1)
VectorSub(*box\p(2), *box\p(0), result2)
VectorCross(result1, result2, normal)
VectorSub(*point, *box\p(0), result3)
If VectorDot(normal, result3) <= 0
collide = 1
EndIf
EndIf
; top
If collide = 0
VectorSub(*box\p(6), *box\p(4), result1)
VectorSub(*box\p(5), *box\p(4), result2)
VectorCross(result1, result2, normal)
VectorSub(*point, *box\p(4), result3)
If VectorDot(normal, result3) <= 0
collide = 2
EndIf
EndIf
; front
If collide = 0
VectorSub(*box\p(6), *box\p(2), result1)
VectorSub(*box\p(3), *box\p(2), result2)
VectorCross(result1, result2, normal)
VectorSub(*point, *box\p(2), result3)
If VectorDot(normal, result3) <= 0
collide = 3
EndIf
EndIf
; rear
If collide = 0
VectorSub(*box\p(4), *box\p(0), result1)
VectorSub(*box\p(1), *box\p(0), result2)
VectorCross(result1, result2, normal)
VectorSub(*point, *box\p(0), result3)
If VectorDot(normal, result3) <= 0
collide = 4
EndIf
EndIf
; right
If collide = 0
VectorSub(*box\p(5), *box\p(1), result1)
VectorSub(*box\p(2), *box\p(1), result2)
VectorCross(result1, result2, normal)
VectorSub(*point, *box\p(1), result3)
If VectorDot(normal, result3) <= 0
collide = 5
EndIf
EndIf
; left
If collide = 0
VectorSub(*box\p(3), *box\p(0), result1)
VectorSub(*box\p(4), *box\p(0), result2)
VectorCross(result1, result2, normal)
VectorSub(*point, *box\p(0), result3)
If VectorDot(normal, result3) <= 0
collide = 6
EndIf
EndIf
Debug collide
ProcedureReturn collide
EndProcedure
Procedure DrawBox()
Shared box
Protected.i n
For n = 0 To 7 Step 2
CreateLine3D(#PB_Any, box\p(n)\x, box\p(n)\y, box\p(n)\z, RGB(255,0,0), box\p(n+1)\x, box\p(n+1)\y, box\p(n+1)\z, RGB(255,0,0))
Next
CreateLine3D(#PB_Any, box\p(0)\x, box\p(0)\y, box\p(0)\z, RGB(255,0,0), box\p(3)\x, box\p(3)\y, box\p(3)\z, RGB(255,0,0))
CreateLine3D(#PB_Any, box\p(1)\x, box\p(1)\y, box\p(1)\z, RGB(255,0,0), box\p(2)\x, box\p(2)\y, box\p(2)\z, RGB(255,0,0))
CreateLine3D(#PB_Any, box\p(4)\x, box\p(4)\y, box\p(4)\z, RGB(255,0,0), box\p(7)\x, box\p(7)\y, box\p(7)\z, RGB(255,0,0))
CreateLine3D(#PB_Any, box\p(5)\x, box\p(5)\y, box\p(5)\z, RGB(255,0,0), box\p(6)\x, box\p(6)\y, box\p(6)\z, RGB(255,0,0))
CreateLine3D(#PB_Any, box\p(0)\x, box\p(0)\y, box\p(0)\z, RGB(255,0,0), box\p(4)\x, box\p(4)\y, box\p(4)\z, RGB(255,0,0))
CreateLine3D(#PB_Any, box\p(1)\x, box\p(1)\y, box\p(1)\z, RGB(255,0,0), box\p(5)\x, box\p(5)\y, box\p(5)\z, RGB(255,0,0))
CreateLine3D(#PB_Any, box\p(3)\x, box\p(3)\y, box\p(3)\z, RGB(255,0,0), box\p(7)\x, box\p(7)\y, box\p(7)\z, RGB(255,0,0))
CreateLine3D(#PB_Any, box\p(2)\x, box\p(2)\y, box\p(2)\z, RGB(255,0,0), box\p(6)\x, box\p(6)\y, box\p(6)\z, RGB(255,0,0))
EndProcedure
Procedure DrawLine()
Shared p1, p2
Shared hLine, plane1, plane2
If Not IsTexture(plane1\hTex)
plane1\hTex = CreateTexture(#PB_Any, 64, 64)
StartDrawing(TextureOutput(plane1\hTex))
DrawText(32, 0, "p1", RGB(0,255,0))
StopDrawing()
EndIf
If Not IsMaterial(plane1\hMat)
plane1\hMat = CreateMaterial(#PB_Any, TextureID(plane1\hTex))
MaterialBlendingMode(plane1\hMat, #PB_Material_Add)
EndIf
If Not IsMesh(plane1\hMsh)
plane1\hMsh = CreatePlane(#PB_Any, 50, 50, 1, 1, 1, 1)
EndIf
If Not IsTexture(plane2\hTex)
plane2\hTex = CreateTexture(#PB_Any, 64, 64)
StartDrawing(TextureOutput(plane2\hTex))
DrawText(16, 0, "p2", RGB(0,255,0))
StopDrawing()
EndIf
If Not IsMaterial(plane2\hMat)
plane2\hMat = CreateMaterial(#PB_Any, TextureID(plane2\hTex))
MaterialBlendingMode(plane2\hMat, #PB_Material_Add)
EndIf
If Not IsMesh(plane2\hMsh)
plane2\hMsh = CreatePlane(#PB_Any, 50, 50, 1, 1, 1, 1)
EndIf
If IsMesh(hLine) : FreeMesh(hLine) : EndIf
hLine = CreateLine3D(#PB_Any, p1\x, p1\y, p1\z, RGB(0,255,0), p2\x, p2\y, p2\z, RGB(0,255,0))
If Not IsEntity(plane1\hEnt)
plane1\hEnt = CreateEntity(#PB_Any, MeshID(plane1\hMsh), MaterialID(plane1\hMat), p1\x, p1\y-35, p1\z)
RotateEntity(plane1\hEnt, 90, 180, 0, #PB_Absolute)
Else
MoveEntity(plane1\hEnt, p1\x, p1\y-35, p1\z, #PB_Absolute)
EndIf
If Not IsEntity(plane2\hEnt)
plane2\hEnt = CreateEntity(#PB_Any, MeshID(plane2\hMsh), MaterialID(plane2\hMat), p2\x, p2\y-35, p2\z)
RotateEntity(plane2\hEnt, 90, 180, 0, #PB_Absolute)
Else
MoveEntity(plane2\hEnt, p2\x, p2\y-35, p2\z, #PB_Absolute)
EndIf
EndProcedure
Procedure DrawInfo(Collision.i)
Shared plane3
Static.i lastCollision, done
If done = 0
plane3\hTex = CreateTexture(#PB_Any, 128, 64)
StartDrawing(TextureOutput(plane3\hTex))
DrawText(0, 0, "move Mouse", RGB(255,255,255))
StopDrawing()
plane3\hMat = CreateMaterial(#PB_Any, TextureID(plane3\hTex))
MaterialBlendingMode(plane3\hMat, #PB_Material_Add)
plane3\hMsh = CreatePlane(#PB_Any, 100, 50, 1, 1, 1, 1)
plane3\hEnt = CreateEntity(#PB_Any, MeshID(plane3\hMsh), MaterialID(plane3\hMat), 0, 100, 0)
RotateEntity(plane3\hEnt, 90, 180, 0, #PB_Absolute)
done = 1
lastCollision = -1
EndIf
If lastCollision <> Collision
If IsTexture(plane3\hTex) : FreeTexture(plane3\hTex) : EndIf
Select Collision
Case 0
plane3\hTex = CreateTexture(#PB_Any, 128, 64)
StartDrawing(TextureOutput(plane3\hTex))
DrawText(0, 0, "no Collision", RGB(255,255,255))
StopDrawing()
Case 1
plane3\hTex = CreateTexture(#PB_Any, 128, 64)
StartDrawing(TextureOutput(plane3\hTex))
DrawText(0, 0, "p1 Collide", RGB(255,255,255))
StopDrawing()
Case 2
plane3\hTex = CreateTexture(#PB_Any, 128, 64)
StartDrawing(TextureOutput(plane3\hTex))
DrawText(0, 0, "p2 Collide", RGB(255,255,255))
StopDrawing()
EndSelect
If IsMaterial(plane3\hMat)
FreeMaterial(plane3\hMat)
plane3\hMat = CreateMaterial(#PB_Any, TextureID(plane3\hTex))
MaterialBlendingMode(plane3\hMat, #PB_Material_Add)
EndIf
SetEntityMaterial(plane3\hEnt, MaterialID(plane3\hMat))
lastCollision = Collision
EndIf
EndProcedure
; init
Do(InitEngine3D(), "Can not init 3D Engine")
Do(InitSprite(), "Can not init Sprite")
Do(InitKeyboard(), "Can not init Keyboard")
Do(InitMouse(), "Can not init Mouse")
Do(ExamineDesktops(), "Can not find Desktops")
Do(OpenWindow(0, 0, 0, DesktopWidth(0)/1.5, DesktopHeight(0)/1.5, "Collision", #PB_Window_ScreenCentered|#PB_Window_SystemMenu), "Can Not open window")
Do(OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0), WindowHeight(0), 0, 0, 0, #PB_Screen_SmartSynchronization), "Can not open screen")
; build box
; 7--------6
; /| /
; / | /|
; / | / |
;4--------5 |
; | | | |
; | 3|---|--/2
; | / | /
; |/ |/
;0--------1
; center is 0,0,0
box\p(0)\x = -50
box\p(0)\y = -50
box\p(0)\z = 50
box\p(1)\x = 50
box\p(1)\y = -50
box\p(1)\z = 50
box\p(2)\x = 50
box\p(2)\y = -50
box\p(2)\z = -50
box\p(3)\x = -50
box\p(3)\y = -50
box\p(3)\z = -50
box\p(4)\x = -50
box\p(4)\y = 50
box\p(4)\z = 50
box\p(5)\x = 50
box\p(5)\y = 50
box\p(5)\z = 50
box\p(6)\x = 50
box\p(6)\y = 50
box\p(6)\z = -50
box\p(7)\x = -50
box\p(7)\y = 50
box\p(7)\z = -50
; build points
p1\x = 200
p1\y = 0
p1\z = 0
p2\x = 400
p2\y = 0
p2\z = 0
DrawBox()
DrawLine()
DrawInfo(0)
hCam = CreateCamera(#PB_Any, 0, 0, 100, 100)
MoveCamera(hCam, 0, 0, 500, #PB_Absolute)
Repeat
; catch all window events
Repeat
WindowEvt = WindowEvent()
Select WindowEvt
Case #PB_Event_CloseWindow
DoLoop = #False
EndSelect
Until WindowEvt = 0
; catch keystrokes
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape)
DoLoop = #False
EndIf
EndIf
; catch mouse and move line3d
If ExamineMouse()
MouseMoveX = MouseDeltaX()
MouseMoveY = MouseDeltaY()
p1\x = p1\x + MouseMoveX * 0.5
p1\y = p1\y - MouseMoveY * 0.5
p2\x = p2\x + MouseMoveX * 0.5
DrawLine()
; check collision
If BallBlock_Collision(box, p1)
DrawInfo(1)
Else
DrawInfo(0)
EndIf
; If BallBlock_Collision(box, p2)
; DrawInfo(2)
; Else
; DrawInfo(0)
; EndIf
EndIf
; render world
RenderWorld()
FlipBuffers()
Until DoLoop = #False
End
Sollte das gelöst werden, vielleicht hat auch noch jemand einen Tip wie ich die Kollision eine Kugel mit einer Box errechne ?
Vielen Dank im voraus.