2008年10月26日 星期日

XNA - 3D模型的碰撞檢測 - Part 2

XNA - 3D模型的碰撞檢測 - Part 2

例如:

if (bulletBoundingSphere.Intersects(planeBoundingSphere))
{
//plane's been hit. cue smoke, flames, snakes in a panic, singing nuns, whatever...
}



這裡範例展示要如何取得Model的BoundingSphere…

//Load the model using my game's instance of a ContentManager.

Model myModel = MyGame.ContentManager.Load("ContentMeshesMyModel");

foreach (ModelMesh mesh in myModel.Meshes)
{
//Do stuff with mesh.BoundingSphere
}



接著來看看這些程式碼,它們可以在MyGame.cs裡面找到…

private void AnalyseModel()
{
// Take a copy of the Model's BoneTransforms (transforms to be applied to each part of the model)
GetBoneTransforms();

// Build BoundingParts for Collision Detection
BuildBoundingParts();
}

private void GetBoneTransforms()
{
_modelBoneTransforms = new Matrix[_model.Bones.Count];
_model.CopyAbsoluteBoneTransformsTo(_modelBoneTransforms);
}



是的,這一切聽起來令人興奮,所以來看看著個好東西。這些程式碼在MyGame.cs約頂部的地方,你可以看到以下有趣的程式碼…

//Blob mesh
private string[] _modelBoundingPartNames = new string[]
{
"Fuselage",
"Wing",
"Tail"
};

private Color[] _modelBoundingPartColours = new Color[]
{
Color.Blue,
Color.Red,
Color.GreenYellow
};

private Vector4[][] _modelBoundingPartSubdivisions = new Vector4[][]
{
//Fuselage
new Vector4[] { new Vector4(0.50f, 0.10f, 0.46f, 0.20f),
new Vector4(0.50f, 0.30f, 0.46f, 0.27f),
new Vector4(0.50f, 0.60f, 0.48f, 0.26f)
},
//Wing
new Vector4[] { new Vector4(0.07f, 0.51f, 0.50f, 0.20f),
new Vector4(0.30f, 0.515f, 0.50f, 0.25f),
new Vector4(0.50f, 0.515f, 0.50f, 0.27f),
new Vector4(0.70f, 0.515f, 0.50f, 0.25f),
new Vector4(0.93f, 0.51f, 0.50f, 0.20f)
},
//Tail
new Vector4[] { new Vector4(0.25f, 0.52f, 0.45f, 0.40f),
new Vector4(0.50f, 0.56f, 0.53f, 0.55f),
new Vector4(0.75f, 0.52f, 0.45f, 0.40f)
}
};



接下來看BuildBoundingParts()方法會做些甚麼事情!

///
/// Builds a collection of BoundingParts for each ModelMesh in the Model.
/// Each BoundingPart will contain one or many BoundingSphere as defined in the _modelBoundingPartSubdivisions array.
///

private void BuildBoundingParts()
{
_modelBoundingParts = new BoundingPartList();

BoundingPart boundingPart;

int meshIndex = 0;
foreach (ModelMesh mesh in _model.Meshes)
{
BoundingSphere[] pieces = new BoundingSphere[_modelBoundingPartSubdivisions[meshIndex].Length];
int pieceIndex = 0;

//Create, Scale and Position new BoundingSphere's according to the defined subdivisions for this part of the model.
foreach (Vector4 subdivision in _modelBoundingPartSubdivisions[meshIndex])
{
//Determine the new BoundingSphere's Radius
float radius = subdivision.W * mesh.BoundingSphere.Radius;

//Determine the new BoundingSphere's Center by interpolating.
//The subdivision's X, Y, Z represent percentages in each axis. They will used across the full diameter of XNA's "default" BoundingSphere.
float x = MathHelper.Lerp(mesh.BoundingSphere.Center.X - mesh.BoundingSphere.Radius, mesh.BoundingSphere.Center.X + mesh.BoundingSphere.Radius, subdivision.X);
float y = MathHelper.Lerp(mesh.BoundingSphere.Center.Y - mesh.BoundingSphere.Radius, mesh.BoundingSphere.Center.Y + mesh.BoundingSphere.Radius, subdivision.Y);
float z = MathHelper.Lerp(mesh.BoundingSphere.Center.Z - mesh.BoundingSphere.Radius, mesh.BoundingSphere.Center.Z + mesh.BoundingSphere.Radius, subdivision.Z);
Vector3 centre = new Vector3(x, y, z);

pieces[pieceIndex] = new BoundingSphere(centre, radius);

pieceIndex++;
}
boundingPart = new BoundingPart(mesh.BoundingSphere, pieces, _modelBoneTransforms[mesh.ParentBone.Index], _modelBoundingPartNames[meshIndex], _modelBoundingPartColours[meshIndex]);

_modelBoundingParts.Add(boundingPart);
meshIndex++;
}
}

沒有留言: