Genau das hab ich gesucht.
Gruß
Scarabol
Code: Alles auswählen
If initialized = #False
...
EndIf
Code: Alles auswählen
Vec_Add(@playerPos, @camOffset, @camPos) ; needed by the following
Code: Alles auswählen
; TerrainCollision.pb
;
; Example how to translate 2D-screencoordinates into a 3D-worldposition given by the first hit with the terrain
;
; If you want to use RotateCamera, you would have to change this example (setting up the up-vector again
; and recalculate some values supposed to be constant in this examples)
;
; To start this example copy it to the PureBasic\Examples\Sources - directory to let it reference the requested resources
;
; by Froggerprogger, 01.04.07
#CameraSpeed = 5
#Deg2Rad = #PI / 180.0
#Rad2Deg = 1.0 / #Deg2Rad
; declared as global to get them from within Screen3DRequester
Global ScreenWidth, ScreenHeight
IncludeFile "Screen3DRequester.pb"
Define.f KeyX, KeyY, MouseX, MouseY
; a structure for a 3D-float-vector
Structure Vec3D
x.f
y.f
z.f
EndStructure
; some vector-math
Procedure.f Vec_ScalarProd(*v1.Vec3D, *v2.Vec3D) ; <v1, v2>
ProcedureReturn *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z
EndProcedure
Procedure.f Vec_Abs(*v1.Vec3D) ; |v1|
Protected z.f
z = Sqr(*v1\x * *v1\x + *v1\y * *v1\y + *v1\z * *v1\z)
ProcedureReturn z
EndProcedure
Procedure Vec_ScalarMul(*v1.Vec3D, f.f, *v.Vec3D = 0) ; v1 = f * v1
If *v = 0
*v = *v1
EndIf
*v\x = *v1\x * f
*v\y = *v1\y * f
*v\z = *v1\z * f
EndProcedure
Procedure Vec_VectorProd(*v1.Vec3D, *v2.Vec3D, *v.Vec3D) ; v = v1 x v2
*v\x = *v1\y * *v2\z - *v1\z * *v2\y
*v\y = *v1\z * *v2\x - *v1\x * *v2\z
*v\z = *v1\x * *v2\y - *v1\y * *v2\x
EndProcedure
Procedure Vec_Add(*v1.Vec3D, *v2.Vec3D, *v.Vec3D) ; v = v1 + v2
*v\x = *v1\x + *v2\x
*v\y = *v1\y + *v2\y
*v\z = *v1\z + *v2\z
EndProcedure
Procedure Vec_Sub(*v1.Vec3D, *v2.Vec3D, *v.Vec3D) ; v = v1 - v2
*v\x = *v1\x - *v2\x
*v\y = *v1\y - *v2\y
*v\z = *v1\z - *v2\z
EndProcedure
Procedure Vec_Copy(*v1.Vec3D, *v.Vec3D) ; v = v1
*v\x = *v1\x
*v\y = *v1\y
*v\z = *v1\z
EndProcedure
Procedure Vec_Set(x.f, y.f, z.f, *v.Vec3D) ; v = (x,y,z)
*v\x = x
*v\y = y
*v\z = z
EndProcedure
Procedure.d Vec_Distance(*v1.Vec3D, *v2.Vec3D)
ProcedureReturn Sqr(Pow(*v1\x - *v2\x, 2)+Pow(*v1\y - *v2\y, 2)+Pow(*v1\z - *v2\z, 2))
EndProcedure
Procedure.f GSin(winkel.f)
ProcedureReturn Sin(winkel*#PI/180)
EndProcedure
Procedure.f GCos(winkel.f)
ProcedureReturn Cos(winkel*#PI/180)
EndProcedure
Procedure.f Distance3D(x1, y1, z1, x2, y2, z2)
ProcedureReturn Sqr(Pow(x1-x2,2)+Pow(y1-y2,2)+Pow(z1-z2,2))
EndProcedure
playerPos.Vec3D ; player's position (same as lookAt)
startPos.Vec3D ; player's startposition when automoving
targetPos.Vec3D ; player' targetposition when automoving
camOffset.Vec3D ; the camera's offset from which to look at the player
camPos.Vec3D ; the cameras position (playerPos + camOffset)
camDir.Vec3D ; the direction of the camera (playerPos - camPos)
up.Vec3D ; the camera's up-position
Vec_Set(0, 1, 0, @up)
pointerDir.Vec3D ; the line from camPos through the mousecursor
lVector.Vec3D ; (normalized) vector showing to the screen's left side orthogonal on camDir
tVector.Vec3D ; (normalized) vector showing to the screen's top orthogonal on camDir
screenHit.Vec3D ; the point where the surface given by lVector and tVector through playerPos is hit
scalar_lVectorCamDir.f ; <lVector, camDir> (precalculated for speed-up)
scalar_tVectorCamDir.f ; <tVector, camDir> (precalculated for speed-up)
vecprod_lVectorCamDir.Vec3D ; lVector x camDir (precalculated for speed-up)
vecprod_tVectorCamDir.Vec3D ; tVector x camDir (precalculated for speed-up)
factorPerPixel.f ; the factor for lVector and tVector for each screen-pixel
searchDepth.f ; searching for terrain-collision up to searchDepth times the player-distance
searchStep.f ; searching through depth with this stepsize
Vec_Set(20, 30, 0, @camOffset)
fov.f = 80 * #Deg2Rad ; the field of view to use
searchDepth = 4.0
searchStep = 0.01
animationSpeed.l ; ms for player to reach target
animationSpeed = 2000
targetReachtime.l ; time when to reach target
initialized.l = #False
CameraAngleX = 240
CameraAngleY = 45
If InitEngine3D()
Add3DArchive("Data\" , #PB_3DArchive_FileSystem)
InitSprite()
InitKeyboard()
InitMouse()
If Screen3DRequester()
AmbientColor(RGB(255,255,255))
CreateMaterial (0, LoadTexture(0, "Terrain_Texture.jpg"))
AddMaterialLayer(0, LoadTexture(1, "Terrain_Detail.jpg"), 1)
CreateTerrain("Terrain.png", MaterialID(0), 1, 1, 1, 4)
CreateCamera(0, 0, 0, 100, 100)
CameraLocate(0, 128, 10, 128)
CameraFOV(0, fov)
SkyDome("Clouds.jpg",10)
; load player-entity
LoadMesh (0, "Robot.mesh")
CreateMaterial(1, LoadTexture(1, "r2skin.jpg"))
CreateEntity(0, MeshID(0), MaterialID(1), 0, 0, 0)
ResizeEntity(0, 0.2, 0.2, 0.2)
; set the initial playerposition
playerPos\x = 100
playerPos\z = 100
playerPos\y = TerrainHeight(playerPos\x, playerPos\z)
CameraDistance = 40
MouseLocate(ScreenWidth / 2, ScreenHeight / 2)
MouseX = ScreenWidth / 2
MouseY = ScreenHeight / 2
; start
Repeat
Screen3DEvents()
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
If ExamineMouse()
MouseDeltaX = MouseDeltaX()
MouseDeltaY = MouseDeltaY()
MouseX + MouseDeltaX
If MouseX > ScreenWidth
MouseX = ScreenWidth
ElseIf MouseX < 0
MouseX = 0
EndIf
MouseY + MouseDeltaY
If MouseY > ScreenHeight
MouseY = ScreenHeight
ElseIf MouseY < 0
MouseY = 0
EndIf
EndIf
; set the cameraDir
Vec_Sub(@playerPos, @camPos, @camDir)
; set the lVector = norm(up x camDir)
Vec_VectorProd(@up, @camDir, @lVector)
abs.f = Vec_Abs(@lVector)
Vec_ScalarMul(@lVector, 1.0/abs, @lVector)
; set the tVector = camDir x lVector
Vec_VectorProd(@camDir, @lVector, @tVector)
abs.f = Vec_Abs(@tVector)
Vec_ScalarMul(@tVector, 1/abs)
; get the distance of cam to entity
dist.f = Vec_Abs(@camDir)
; set the factor per pixel
factorPerPixel = Tan(fov/2) * dist * 2.0 / ScreenHeight
; set the horizontal/vertical ranges
vRange.f = factorPerPixel * ScreenHeight/2.0
hRange.f = factorPerPixel * ScreenWidth/2.0
If MouseButton(#PB_MouseButton_Left)
; get the horizontal ratio
hRatio.f = (MouseX - ScreenWidth/2.0) / (ScreenWidth / 2.0)
; get the vertical ratio
vRatio.f = (MouseY - ScreenHeight/2.0) / (ScreenHeight / 2.0)
; build screenHit = playerPos - hRange * hRatio * lVector - vRange * vRatio * tVector
t1.Vec3D
Vec_ScalarMul(@lVector, hRange * hRatio, @t1)
t2.Vec3D
Vec_ScalarMul(@tVector, vRange * vRatio, @t2)
Vec_Sub(@playerPos, @t1, @screenHit)
Vec_Sub(@screenHit, @t2, @screenHit)
; pointerDir = screenHit - camPos
Vec_Sub(@screenHit, @camPos, @pointerDir)
; set pointerDir's length to dist
abs.f = Vec_Abs(@pointerDir)
Vec_ScalarMul(@pointerDir, dist/abs)
; scan the line until hit terrain
t.f = 0
While t < searchDepth
; get x and y along line: camPos + t * pointerDir
x.f = camPos\x + t*pointerDir\x
y.f = camPos\y + t*pointerDir\y
z.f = camPos\z + t*pointerDir\z
If y < TerrainHeight(x, z) Or y < 0
targetPos\x = x - searchStep * pointerDir\x
targetPos\y = y - searchStep * pointerDir\y
targetPos\z = z - searchStep * pointerDir\z
Vec_Copy(@playerPos, @startPos)
targetReachtime = ElapsedMilliseconds() + animationSpeed
Break
EndIf
t + searchStep
Wend
ElseIf MouseButton(#PB_MouseButton_Right)
CameraAngleX + MouseDeltaX
CameraAngleY + MouseDeltaY
EndIf
CameraDistance - MouseWheel()*2
If targetReachtime > ElapsedMilliseconds()
playerPos\x = targetPos\x - (targetReachtime - ElapsedMilliseconds()) * (targetPos\x - startPos\x) / animationSpeed
playerPos\z = targetPos\z - (targetReachtime - ElapsedMilliseconds()) * (targetPos\z - startPos\z) / animationSpeed
Else
playerPos\x + KeyX
playerPos\z + KeyY
EndIf
playerPos\y = TerrainHeight(playerPos\x, playerPos\z)
EntityLocate(0, playerPos\x, playerPos\y, playerPos\z)
; place the camera relative to the entity and look at player
If CameraAngleX > 360
CameraAngleX - 360
ElseIf CameraAngleX < 0
CameraAngleX + 360
EndIf
If CameraAngleY < 5
CameraAngleY = 5
ElseIf CameraAngleY > 85
CameraAngleY = 85
EndIf
camOffset\x = GSin(CameraAngleX)*CameraDistance
camOffset\y = GSin(CameraAngleY)*CameraDistance
camOffset\z = GCos(CameraAngleX)*CameraDistance
Vec_Add(@playerPos, @camOffset, @camPos)
If camPos\y < TerrainHeight(camPos\x, camPos\z)+10
camPos\y = TerrainHeight(camPos\x, camPos\z)+10
EndIf
CameraLocate(0, camPos\x, camPos\y, camPos\z)
CameraLookAt(0, playerPos\x, playerPos\y, playerPos\z)
StartDrawing(TextureOutput(0))
Circle(targetPos\x+3, targetPos\z+3, 5, #Red)
StopDrawing()
RenderWorld()
Screen3DStats()
StartDrawing(ScreenOutput())
Circle(MouseX, MouseY, 5, $0000FF)
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(0, 0, "CameraAngleX : " + StrF(CameraAngleX) + " CameraAngleY : " + StrF(CameraAngleY, 2))
DrawText(0, 20, "camPos (x y z): " + StrF(camPos\x) + "/" + StrF(camPos\y) + "/" + StrF(camPos\z))
DrawText(0, 40, "camDir (x y z): " + StrF(camDir\x) + "/" + StrF(camDir\y) + "/" + StrF(camDir\z))
DrawText(0, 60, "lVector (x y z): " + StrF(lVector\x) + "/" + StrF(lVector\y) + "/" + StrF(lVector\z))
DrawText(0, 80, "tVector (x y z): " + StrF(tVector\x) + "/" + StrF(tVector\y) + "/" + StrF(tVector\z))
DrawText(0, 100, "pointerDir (x y z): " + StrF(pointerDir\x) + "/" + StrF(pointerDir\y) + "/" + StrF(pointerDir\z))
DrawText(0, 120, "t1 (x y z): " + StrF(t1\x) + "/" + StrF(t1\y) + "/" + StrF(t1\z))
DrawText(0, 140, "screenHit (x y z): " + StrF(screenHit\x) + "/" + StrF(screenHit\y) + "/" + StrF(screenHit\z))
DrawText(0, 160, "hRange/vRange: " + StrF(hRange) + "/" + StrF(vRange, 2))
; DrawText(0, 180, "EntityPos (x y z) : " + StrF(EntityX(1)) + "/" + StrF(EntityY(1)) + "/" + StrF(EntityZ(1)))
StopDrawing()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
EndIf
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End