游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2800|回复: 4

碰撞检测

[复制链接]

42

主题

140

帖子

203

积分

中级会员

Rank: 3Rank: 3

积分
203
发表于 2003-11-1 11:50:00 | 显示全部楼层 |阅读模式
'//检察两个三角形间的的碰撞TriSrc()为原三角形,TriDest()为目标三角形
Private Function vbCheckTriTriCollision(TriSrc() As LitVertex, TriDest() As LitVertex, TransformSrcGeom As Boolean, TransformDestGeom As Boolean, TriSrcMat As D3DMATRIX, TriDestMat As D3DMATRIX) As Boolean
'//0. 定义的变量
Dim t As Single, A As Single, B As Single, C As Single, D As Single, i0 As Single, i1 As Single
Dim LowIdx As Long, HiIdx As Long, I As Long
Dim vNormal As Vector, v01 As Vector, v02 As Vector
'//1. 是否需要转换(下一针位置预测)
If TransformSrcGeom Then
For I = 0 To 2
TriSrc(I).P.X = (TriSrc(I).P.X * TriSrcMat.m11) + (TriSrc(I).P.Y * TriSrcMat.m21) + (TriSrc(I).P.Z * TriSrcMat.m31) + TriSrcMat.m41
TriSrc(I).P.Y = (TriSrc(I).P.X * TriSrcMat.m12) + (TriSrc(I).P.Y * TriSrcMat.m22) + (TriSrc(I).P.Z * TriSrcMat.m32) + TriSrcMat.m42
TriSrc(I).P.Z = (TriSrc(I).P.X * TriSrcMat.m13) + (TriSrc(I).P.Y * TriSrcMat.m23) + (TriSrc(I).P.Z * TriSrcMat.m33) + TriSrcMat.m43
Next I
End If
If TransformDestGeom Then
For I = 0 To 2
TriDest(I).P.X = (TriDest(I).P.X * TriDestMat.m11) + (TriDest(I).P.Y * TriDestMat.m21) + (TriDest(I).P.Z * TriDestMat.m31) + TriDestMat.m41
TriDest(I).P.Y = (TriDest(I).P.X * TriDestMat.m12) + (TriDest(I).P.Y * TriDestMat.m22) + (TriDest(I).P.Z * TriDestMat.m32) + TriDestMat.m42
TriDest(I).P.Z = (TriDest(I).P.X * TriDestMat.m13) + (TriDest(I).P.Y * TriDestMat.m23) + (TriDest(I).P.Z * TriDestMat.m33) + TriDestMat.m43
Next I
End If
'//2. 计算三角形的相领两边的向量
v01.X = TriSrc(0).P.X - TriSrc(1).P.X
v01.Y = TriSrc(0).P.Y - TriSrc(1).P.Y
v01.Z = TriSrc(0).P.Z - TriSrc(1).P.Z
v02.X = TriSrc(0).P.X - TriSrc(2).P.X
v02.Y = TriSrc(0).P.Y - TriSrc(2).P.Y
v02.Z = TriSrc(0).P.Z - TriSrc(2).P.Z
'//3. 计算三角形的法向量
vNormal = Normalise(CrossProduct(v01, v02))
A = vNormal.X
B = vNormal.Y
C = vNormal.Z
'//4. 计算三角形到圆点的距离
D = -DotProduct(vNormal, TriSrc(0).P)

'//5. 分别检察目标三角形的三边是否穿过原三角形所在的平面
For I = 0 To 2
LowIdx = I
HiIdx = I + 1
If (HiIdx = 3) Then HiIdx = 0
'//6.计算平行于原三角形,且经过顶点的平面到圆点的距离
i0 = (A * TriDest(LowIdx).P.X) + (B * TriDest(LowIdx).P.Y) + (C * TriDest(LowIdx).P.Z)
i1 = (A * TriDest(HiIdx).P.X) + (B * TriDest(HiIdx).P.Y) + (C * TriDest(HiIdx).P.Z)
If Not (i0 = i1) Then  '//这种情况(i0 = i1),边平行于原三角形
t = -(i1 + D) / (i0 - i1)
'//这个方程判断两个顶点是否在平面异侧,i1=-D时t=0,i0=-D时t=1
If (t >= 0#) And (t <= 1#) Then
  'if we now used the linear formula a+v(b-a) where a=TriDest(LowIdx) b=TriDest(HiIdx) v=t
  'we could work out the exact point in 3D space that they collide.
  vbCheckTriTriCollision = True
  Exit Function
End If
End If
Next I

vbCheckTriTriCollision = False
End Function




42

主题

140

帖子

203

积分

中级会员

Rank: 3Rank: 3

积分
203
 楼主| 发表于 2003-11-1 11:50:00 | 显示全部楼层

Re:碰撞检测

这是方形地面上,小车运动的碰撞检测
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyDown Then
move_verts car, MakeVector(2, 0, 0), False
ElseIf KeyCode = vbKeyUp Then
move_verts car, MakeVector(-2, 0, 0), False
End If
End Sub

Private sub form_load()
...
...
...
render loop...
    If GetTickCount - ticks > 1 Then ' gravity
        ticks = GetTickCount
        move_verts car, MakeVector(0, -4.9 / FPS_Highest, 0), True
    End If
...
end sub


Private Function move_verts(Object() As LITVERTEX, direction As D3DVECTOR, Gravity As Boolean) As Boolean
Dim i As Integer
Dim ans As Boolean
Dim p As LITVERTEX
Dim temp As LITVERTEX
Dim dmove As Boolean
Dim dmoveS() As Boolean
Dim x As Integer
ReDim dmoveS(UBound(Object)) As Boolean
For i = 0 To UBound(Object)
    temp.x = Object(i).x + direction.x
    temp.y = Object(i).y + direction.y
    temp.z = Object(i).z + direction.z
    For x = 0 To UBound(Cube) Step 3
        If Coll_Test(Cube(x), Cube(x + 1), Cube(x + 2), Object(i), temp, p) Then 'collision call collision detectoin
            'dmoveS(i) = True
            Exit Function
            'MoveToPlaneHeight Object(i), x / 3, Cube(x), temp 'ignore these notes
            'Object(i).x = temp.x
            'Object(i).z = temp.z
        End If
    Next x
Next i
For i = 0 To UBound(Object)
    'If Not dmoveS(i) Then
        Object(i).x = Object(i).x + direction.x
        Object(i).y = Object(i).y + direction.y
        Object(i).z = Object(i).z + direction.z
    'End If
Next i
Set carBuffer = D3DDevice.CreateVertexBuffer(Len(car(0)) * 6, 0, Lit_FVF, D3DPOOL_DEFAULT)
If carBuffer Is Nothing Then Exit Function
D3DVertexBuffer8SetData carBuffer, 0, Len(car(0)) * 6, 0, car(0)

D3DXMatrixLookAtLH matView, MakeVector(0, 15, 15), MakeVector(Object(0).x, Object(0).y, Object(0).z), MakeVector(0, 1, 0)
D3DDevice.SetTransform D3DTS_VIEW, matView
End Function


'//colision detection

Function ACos(ByVal number As Double) As Double
    If Abs(number) <> 1 Then
        ACos = 1.5707963267949 - Atn(number / Sqr(1 - number * number))
    ElseIf number = -1 Then
        ACos = 3.14159265358979
    End If
End Function

Private Function normalise(Vertex As LITVERTEX) As LITVERTEX
Dim x As D3DVECTOR
x.x = Vertex.x
x.y = Vertex.y
x.z = Vertex.z
D3DXVec3Normalize x, x
normalise.x = x.x
normalise.y = x.y
normalise.z = x.z
End Function


Public Function Coll_Test(p1 As LITVERTEX, p2 As LITVERTEX, p3 As LITVERTEX, l1 As LITVERTEX, l2 As LITVERTEX, point As LITVERTEX) As Boolean
Dim p As LITVERTEX
Dim N As LITVERTEX
Dim pa1 As LITVERTEX
Dim pa2 As LITVERTEX
Dim pa3 As LITVERTEX
Dim d As Double
Dim a1 As Double
Dim a2 As Double
Dim a3 As Double
Dim denom As Double
Dim mu As Double
Dim total As Double

'//Get Planes Normal and Make Length Of 1\\
   N.x = (p2.y - p1.y) * (p3.z - p1.z) - (p2.z - p1.z) * (p3.y - p1.y)
   N.y = (p2.z - p1.z) * (p3.x - p1.x) - (p2.x - p1.x) * (p3.z - p1.z)
   N.z = (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x)
   N = normalise(N) ' normalise normal

d = -N.x * p1.x - N.y * p1.y - N.z * p1.z

'//see if line is paralel to plane
denom = N.x * (l2.x - l1.x) + N.y * (l2.y - l1.y) + N.z * (l2.z - l1.z)

If denom = 0 Then
    Coll_Test = False
    Exit Function
End If

'//get location on line
mu = -(d + N.x * l1.x + N.y * l1.y + N.z * l1.z) / denom
   p.x = l1.x + mu * (l2.x - l1.x)
   p.y = l1.y + mu * (l2.y - l1.y)
   p.z = l1.z + mu * (l2.z - l1.z)
   
If mu > 1 Or mu < 0 Then   '//intersection isn't on line, no collision
    Coll_Test = False
    Exit Function
End If

'// see if intersection is with in plane
   pa1.x = p1.x - p.x
   pa1.y = p1.y - p.y
   pa1.z = p1.z - p.z
   pa1 = normalise(pa1)
   pa2.x = p2.x - p.x
   pa2.y = p2.y - p.y
   pa2.z = p2.z - p.z
   pa2 = normalise(pa2)
   pa3.x = p3.x - p.x
   pa3.y = p3.y - p.y
   pa3.z = p3.z - p.z
   pa3 = normalise(pa3)
   a1 = pa1.x * pa2.x + pa1.y * pa2.y + pa1.z * pa2.z
   a2 = pa2.x * pa3.x + pa2.y * pa3.y + pa2.z * pa3.z
   a3 = pa3.x * pa1.x + pa3.y * pa1.y + pa3.z * pa1.z
’判断交点是否在三角形内部,如果在内部,它与三个顶点向量的夹角的反余弦和会在一范围内
   total = (ACos(a1) + ACos(a2) + ACos(a3)) ' * RTOD
   If Abs(total) > 6.284 Or Abs(total) < 6.282 Then
      Coll_Test = False
      Exit Function
  End If
   Coll_Test = True
   point = p
End Function


42

主题

140

帖子

203

积分

中级会员

Rank: 3Rank: 3

积分
203
 楼主| 发表于 2003-11-1 12:37:00 | 显示全部楼层

Re: 碰撞检测

C,vb code

sf_2003111123716.rar

35.25 KB, 下载次数:

6

主题

103

帖子

103

积分

注册会员

Rank: 2

积分
103
发表于 2006-9-10 23:41:00 | 显示全部楼层

Re:碰撞检测

已阅

0

主题

62

帖子

62

积分

注册会员

Rank: 2

积分
62
发表于 2007-4-4 19:45:00 | 显示全部楼层

Re:碰撞检测

很有用的东西,支持
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-4-12 15:56

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表