mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 15:15:31 +00:00
Various collision changes:
- no collision with NCO objects - better camera control (no turning the camera upside down) - up/down buttons (shift/ctrl) does not move the player when walking - eye level adjusted - various updates git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@55 ea6a568a-9f4f-0410-981a-c910a81bb256
This commit is contained in:
parent
e927c9a70e
commit
08ba0278a1
9 changed files with 236 additions and 97 deletions
2
Makefile
2
Makefile
|
@ -28,7 +28,7 @@ ogre_cpp=ogre framelistener interface overlay bsaarchive
|
|||
avcodec_cpp=avcodec
|
||||
|
||||
# Bullet cpp files
|
||||
bullet_cpp=bullet player
|
||||
bullet_cpp=bullet player scale
|
||||
|
||||
#### No modifications should be required below this line. ####
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ Changelog:
|
|||
0.5 (WIP)
|
||||
|
||||
- working on collision detection with Bullet
|
||||
- working on walk & fall character physics
|
||||
- working on fixing sound issues for windows (running out of sound
|
||||
resources, music playback doesn't good)
|
||||
- new key bindings:
|
||||
|
|
|
@ -48,6 +48,13 @@ void bullet_setPlayerDir(float x, float y, float z);
|
|||
// been applied.
|
||||
void bullet_getPlayerPos(float *x, float *y, float *z);
|
||||
|
||||
// Create a box shape.
|
||||
/*
|
||||
void bullet_createBoxShape(float minX, float minY, float minZ,
|
||||
float maxX, float maxY, float maxZ,
|
||||
float *trans,float *matrix);
|
||||
*/
|
||||
|
||||
// Create a triangle shape. This is cumulative, all meshes created
|
||||
// with this function are added to the same shape. Since the various
|
||||
// parts of a mesh can be differently transformed and we are putting
|
||||
|
|
|
@ -29,6 +29,12 @@ using namespace std;
|
|||
|
||||
class CustomOverlappingPairCallback;
|
||||
|
||||
enum
|
||||
{
|
||||
MASK_PLAYER = 1,
|
||||
MASK_STATIC = 2
|
||||
};
|
||||
|
||||
// System variables
|
||||
btDefaultCollisionConfiguration* g_collisionConfiguration;
|
||||
btCollisionDispatcher *g_dispatcher;
|
||||
|
@ -56,6 +62,11 @@ btVector3 g_walkDirection;
|
|||
// added into this, until bullet_getFinalShape() is called.
|
||||
btTriangleIndexVertexArray *g_currentMesh;
|
||||
|
||||
// Current compound shape being built. g_compoundShape and
|
||||
// g_currentMesh are returned together (the mesh inserted into the
|
||||
// compound) if both are present.
|
||||
btCompoundShape *g_compoundShape;
|
||||
|
||||
// These variables and the class below are used in player collision
|
||||
// detection. The callback is injected into the broadphase and keeps a
|
||||
// continuously updated list of what objects are colliding with the
|
||||
|
@ -77,6 +88,9 @@ int g_physMode;
|
|||
// Include the player physics
|
||||
#include "cpp_player.cpp"
|
||||
|
||||
// Include the uniform shape scaler
|
||||
//#include "cpp_scale.cpp"
|
||||
|
||||
class CustomOverlappingPairCallback : public btOverlappingPairCallback
|
||||
{
|
||||
public:
|
||||
|
@ -105,13 +119,6 @@ public:
|
|||
{ if (proxy0->m_clientObject==g_playerObject)
|
||||
g_pairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
|
||||
}
|
||||
|
||||
/* KILLME
|
||||
btBroadphasePairArray& getOverlappingPairArray()
|
||||
{ return g_pairCache->getOverlappingPairArray(); }
|
||||
btOverlappingPairCache* getOverlappingPairCache()
|
||||
{ return g_pairCache; }
|
||||
*/
|
||||
};
|
||||
|
||||
extern "C" int32_t bullet_init()
|
||||
|
@ -132,8 +139,8 @@ extern "C" int32_t bullet_init()
|
|||
// to create a custom broadphase designed for our purpose. (We
|
||||
// should probably use different ones for interior and exterior
|
||||
// cells in any case.)
|
||||
btVector3 worldMin(-40000,-40000,-40000);
|
||||
btVector3 worldMax(40000,40000,40000);
|
||||
btVector3 worldMin(-20000,-20000,-20000);
|
||||
btVector3 worldMax(20000,20000,20000);
|
||||
g_broadphase = new btAxisSweep3(worldMin,worldMax);
|
||||
|
||||
g_dynamicsWorld =
|
||||
|
@ -149,20 +156,25 @@ extern "C" int32_t bullet_init()
|
|||
|
||||
// Create the player collision shape.
|
||||
float width = 50;
|
||||
|
||||
/*
|
||||
// One possible shape is the convex hull around two spheres
|
||||
float height = 100;
|
||||
float height = 50;
|
||||
btVector3 spherePositions[2];
|
||||
btScalar sphereRadii[2];
|
||||
sphereRadii[0] = width;
|
||||
sphereRadii[1] = width;
|
||||
spherePositions[0] = btVector3 (0.0, height/2.0, 0.0);
|
||||
spherePositions[1] = btVector3 (0.0, -height/2.0, 0.0);
|
||||
spherePositions[0] = btVector3 (0,0,0);
|
||||
spherePositions[1] = btVector3 (0,0,-height);
|
||||
|
||||
// One possible shape is the convex hull around two spheres
|
||||
g_playerShape = new btMultiSphereShape(btVector3(width/2.0, height/2.0,
|
||||
width/2.0), &spherePositions[0], &sphereRadii[0], 2);
|
||||
//*/
|
||||
//g_playerShape = new btCylinderShape(btVector3(50, 50, 50));
|
||||
*/
|
||||
|
||||
// Other posibilities - most are too slow, except the sphere
|
||||
//g_playerShape = new btCylinderShapeZ(btVector3(width, width, height));
|
||||
g_playerShape = new btSphereShape(width);
|
||||
//g_playerShape = new btCapsuleShapeZ(width, height);
|
||||
|
||||
// Create the collision object
|
||||
g_playerObject = new btCollisionObject ();
|
||||
|
@ -183,13 +195,13 @@ extern "C" int32_t bullet_init()
|
|||
g_dynamicsWorld->setInternalTickCallback(playerStepCallback);
|
||||
|
||||
// Add the character collision object to the world.
|
||||
g_dynamicsWorld->addCollisionObject(g_playerObject
|
||||
,btBroadphaseProxy::DebrisFilter
|
||||
//,btBroadphaseProxy::StaticFilter
|
||||
);
|
||||
g_dynamicsWorld->addCollisionObject(g_playerObject,
|
||||
MASK_PLAYER,
|
||||
MASK_STATIC);
|
||||
|
||||
// Make sure this is zero at startup
|
||||
// Make sure these is zero at startup
|
||||
g_currentMesh = NULL;
|
||||
g_compoundShape = NULL;
|
||||
|
||||
// Start out walking
|
||||
g_physMode = PHYS_WALK;
|
||||
|
@ -242,6 +254,41 @@ extern "C" void bullet_getPlayerPos(float *x, float *y, float *z)
|
|||
*z = g_playerPosition.getZ();
|
||||
}
|
||||
|
||||
// Create a box shape and add it to the cumulative shape of the
|
||||
// current object
|
||||
/*
|
||||
extern "C" void bullet_createBoxShape(float minX, float minY, float minZ,
|
||||
float maxX, float maxY, float maxZ,
|
||||
float *trans,float *matrix)
|
||||
{
|
||||
if(g_compoundShape == NULL)
|
||||
g_compoundShape = new btCompoundShape;
|
||||
|
||||
// Build a box from the given data.
|
||||
int x = (maxX-minX)/2;
|
||||
int y = (maxY-minY)/2;
|
||||
int z = (maxZ-minZ)/2;
|
||||
btBoxShape *box = new btBoxShape(btVector3(x,y,z));
|
||||
|
||||
// Next, create the transformations
|
||||
btMatrix3x3 mat(matrix[0], matrix[1], matrix[2],
|
||||
matrix[3], matrix[4], matrix[5],
|
||||
matrix[6], matrix[7], matrix[8]);
|
||||
|
||||
// In addition to the mesh's world translation, we have to add the
|
||||
// local translation of the box origin to fit with the given min/max
|
||||
// values.
|
||||
x += minX + trans[0];
|
||||
y += minY + trans[1];
|
||||
z += minZ + trans[2];
|
||||
btVector3 trns(x,y,z);
|
||||
|
||||
// Finally, add the shape to the compound
|
||||
btTransform tr(mat, trns);
|
||||
g_compoundShape->addChildShape(tr, box);
|
||||
}
|
||||
*/
|
||||
|
||||
void* copyBuffer(void *buf, int elemSize, int len)
|
||||
{
|
||||
int size = elemSize * len;
|
||||
|
@ -251,41 +298,6 @@ void* copyBuffer(void *buf, int elemSize, int len)
|
|||
return res;
|
||||
}
|
||||
|
||||
// Define a cube with coordinates 0,0,0 - 1,1,1.
|
||||
const float cube_verts[] =
|
||||
{
|
||||
0,0,0, 1,0,0, 0,1,0,
|
||||
1,1,0, 0,0,1, 1,0,1,
|
||||
0,1,1, 1,1,1
|
||||
};
|
||||
|
||||
// Triangles of the cube. The orientation of each triange doesn't
|
||||
// matter.
|
||||
const short cube_tris[] =
|
||||
{
|
||||
// bottom side
|
||||
0, 1, 2,
|
||||
1, 2, 3,
|
||||
// top side
|
||||
4, 5, 6,
|
||||
5, 6, 7,
|
||||
// front side
|
||||
0, 4, 5,
|
||||
0, 1, 5,
|
||||
// back side
|
||||
2, 3, 7,
|
||||
2, 6, 7,
|
||||
// left side
|
||||
0, 2, 4,
|
||||
2, 4, 6,
|
||||
// right side
|
||||
1, 3, 5,
|
||||
3, 5, 7
|
||||
};
|
||||
|
||||
const int cube_num_verts = 8;
|
||||
const int cube_num_tris = 12;
|
||||
|
||||
// Internal version that does not copy buffers
|
||||
void createTriShape(int32_t numFaces, void *triArray,
|
||||
int32_t numVerts, void *vertArray,
|
||||
|
@ -329,6 +341,41 @@ void createTriShape(int32_t numFaces, void *triArray,
|
|||
g_currentMesh->addIndexedMesh(im, PHY_SHORT);
|
||||
}
|
||||
|
||||
// Define a cube with coordinates 0,0,0 - 1,1,1.
|
||||
const float cube_verts[] =
|
||||
{
|
||||
0,0,0, 1,0,0, 0,1,0,
|
||||
1,1,0, 0,0,1, 1,0,1,
|
||||
0,1,1, 1,1,1
|
||||
};
|
||||
|
||||
// Triangles of the cube. The orientation of each triange doesn't
|
||||
// matter.
|
||||
const short cube_tris[] =
|
||||
{
|
||||
// bottom side
|
||||
0, 1, 2,
|
||||
1, 2, 3,
|
||||
// top side
|
||||
4, 5, 6,
|
||||
5, 6, 7,
|
||||
// front side
|
||||
0, 4, 5,
|
||||
0, 1, 5,
|
||||
// back side
|
||||
2, 3, 7,
|
||||
2, 6, 7,
|
||||
// left side
|
||||
0, 2, 4,
|
||||
2, 4, 6,
|
||||
// right side
|
||||
1, 3, 5,
|
||||
3, 5, 7
|
||||
};
|
||||
|
||||
const int cube_num_verts = 8;
|
||||
const int cube_num_tris = 12;
|
||||
|
||||
// Create a (trimesh) box with the given dimensions. Used for bounding
|
||||
// boxes. TODO: I guess we have to use the NIF-specified bounding box
|
||||
// for this, not our automatically calculated one.
|
||||
|
@ -379,14 +426,33 @@ extern "C" void bullet_createTriShape(int32_t numFaces,
|
|||
// so the next call to createTriShape will start a new shape.
|
||||
extern "C" btCollisionShape *bullet_getFinalShape()
|
||||
{
|
||||
// Return null if no meshes have been inserted
|
||||
if(g_currentMesh == NULL) return NULL;
|
||||
btCollisionShape *shape;
|
||||
|
||||
// Create the shape from the completed mesh
|
||||
btBvhTriangleMeshShape *shape =
|
||||
new btBvhTriangleMeshShape(g_currentMesh, false);
|
||||
// Create a shape from all the inserted completed meshes
|
||||
shape = NULL;
|
||||
if(g_currentMesh != NULL)
|
||||
shape = new btBvhTriangleMeshShape(g_currentMesh, false);
|
||||
|
||||
// Is there a compound shape as well? (usually contains bounding
|
||||
// boxes)
|
||||
if(g_compoundShape != NULL)
|
||||
{
|
||||
// If both shape types are present, insert the mesh shape into
|
||||
// the compound.
|
||||
if(shape != NULL)
|
||||
{
|
||||
btTransform tr;
|
||||
tr.setIdentity();
|
||||
g_compoundShape->addChildShape(tr, shape);
|
||||
}
|
||||
|
||||
// The compound is the final shape
|
||||
shape = g_compoundShape;
|
||||
}
|
||||
|
||||
// Clear these for the next NIF
|
||||
g_currentMesh = NULL;
|
||||
g_compoundShape = NULL;
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
@ -396,14 +462,12 @@ extern "C" void bullet_insertStatic(btCollisionShape *shape,
|
|||
float *quat,
|
||||
float scale)
|
||||
{
|
||||
// TODO: Good test case for scaled meshes: Aharunartus, some of the
|
||||
// stairs inside the cavern currently don't collide
|
||||
// Are we scaled?
|
||||
if(scale != 1.0)
|
||||
{
|
||||
cout << "WARNING: Cannot scale collision meshes yet (wanted "
|
||||
<< scale << ")\n";
|
||||
return;
|
||||
}
|
||||
return;
|
||||
// Wrap the shape in a class that scales it. TODO: Try this on
|
||||
// ALL shapes, just to test the slowdown.
|
||||
//shape = new ScaleShape(shape, scale);
|
||||
|
||||
btTransform trafo;
|
||||
trafo.setIdentity();
|
||||
|
@ -416,7 +480,7 @@ extern "C" void bullet_insertStatic(btCollisionShape *shape,
|
|||
btCollisionObject *obj = new btCollisionObject();
|
||||
obj->setCollisionShape(shape);
|
||||
obj->setWorldTransform(trafo);
|
||||
g_dynamicsWorld->addCollisionObject(obj);
|
||||
g_dynamicsWorld->addCollisionObject(obj, MASK_STATIC, MASK_PLAYER);
|
||||
}
|
||||
|
||||
// Move the physics simulation 'delta' seconds forward in time
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
bool g_touchingContact;
|
||||
btVector3 g_touchingNormal;
|
||||
btScalar g_currentStepOffset;
|
||||
float g_stepHeight = 20;
|
||||
float g_stepHeight = 5;
|
||||
|
||||
// Returns the reflection direction of a ray going 'direction' hitting
|
||||
// a surface with normal 'normal'
|
||||
|
@ -293,6 +293,18 @@ void playerStepCallback(btDynamicsWorld* dynamicsWorld, btScalar timeStep)
|
|||
// simulation.
|
||||
btVector3 walkStep = g_walkDirection * timeStep;
|
||||
|
||||
float len = walkStep.length();
|
||||
|
||||
// In walk mode, it shouldn't matter whether or not we look up or
|
||||
// down. Rotate the vector back to the horizontal plane.
|
||||
if(g_physMode == PHYS_WALK)
|
||||
{
|
||||
walkStep.setZ(0);
|
||||
float len2 = walkStep.length();
|
||||
if(len2 > 0)
|
||||
walkStep *= len/len2;
|
||||
}
|
||||
|
||||
// Get the player position
|
||||
g_playerPosition = g_playerObject->getWorldTransform().getOrigin();
|
||||
|
||||
|
|
|
@ -312,6 +312,9 @@ extern(C) int d_frameStarted(float time)
|
|||
if(isPressed(Keys.MoveRight)) moveX += speed;
|
||||
if(isPressed(Keys.MoveForward)) moveZ -= speed;
|
||||
if(isPressed(Keys.MoveBackward)) moveZ += speed;
|
||||
|
||||
// TODO: These should be enabled for floating modes (like swimming
|
||||
// and levitation) only.
|
||||
if(isPressed(Keys.MoveUp)) moveY += speed;
|
||||
if(isPressed(Keys.MoveDown)) moveY -= speed;
|
||||
|
||||
|
|
|
@ -120,9 +120,15 @@ extern "C" void ogre_screenshot(char* filename)
|
|||
extern "C" void ogre_rotateCamera(float x, float y)
|
||||
{
|
||||
mCamera->yaw(Degree(-x));
|
||||
|
||||
Quaternion nopitch = mCamera->getOrientation();
|
||||
|
||||
mCamera->pitch(Degree(-y));
|
||||
|
||||
//g_light->setDirection(mCamera->getDirection());
|
||||
// Is the camera close to being upside down?
|
||||
if(mCamera->getUp()[1] <= 0.1)
|
||||
// If so, undo the last pitch
|
||||
mCamera->setOrientation(nopitch);
|
||||
}
|
||||
|
||||
// Get current camera position
|
||||
|
@ -155,7 +161,7 @@ extern "C" void ogre_moveCamera(float x, float y, float z)
|
|||
// Transforms Morrowind coordinates to OGRE coordinates. The camera
|
||||
// is not affected by the rotation of the root node, so we must
|
||||
// transform this manually.
|
||||
mCamera->setPosition(Vector3(x,z,-y));
|
||||
mCamera->setPosition(Vector3(x,z+90,-y));
|
||||
|
||||
//g_light->setPosition(mCamera->getPosition());
|
||||
}
|
||||
|
@ -181,5 +187,8 @@ extern "C" void ogre_setCameraRotation(float r1, float r2, float r3)
|
|||
// Move camera relative to its own axis set.
|
||||
extern "C" void ogre_moveCameraRel(float x, float y, float z)
|
||||
{
|
||||
mCamera->moveRelative(Vector3(x,y,z));
|
||||
mCamera->moveRelative(Vector3(x,0,z));
|
||||
|
||||
// up/down movement is always done relative the world axis
|
||||
mCamera->move(Vector3(0,y,0));
|
||||
}
|
||||
|
|
|
@ -182,6 +182,8 @@ extern "C" void ogre_makeScene()
|
|||
// Alter the camera aspect ratio to match the viewport
|
||||
mCamera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
|
||||
|
||||
mCamera->setFOVy(Degree(55));
|
||||
|
||||
// Set default mipmap level (NB some APIs ignore this)
|
||||
TextureManager::getSingleton().setDefaultNumMipmaps(5);
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ struct MeshLoader
|
|||
base = ogre_getDetachedNode();
|
||||
|
||||
// Recursively insert nodes (don't rotate the first node)
|
||||
insertNode(n, base, true);
|
||||
insertNode(n, base, 0, true);
|
||||
|
||||
// Get the final shape, if any
|
||||
shape = bullet_getFinalShape();
|
||||
|
@ -92,10 +92,12 @@ struct MeshLoader
|
|||
|
||||
private:
|
||||
|
||||
void insertNode(Node data, NodePtr parent, bool noRot = false)
|
||||
void insertNode(Node data, NodePtr parent,
|
||||
int flags,
|
||||
bool noRot = false)
|
||||
{
|
||||
// Skip hidden nodes for now.
|
||||
if(data.flags & 0x01) return;
|
||||
// Add the flags to the previous node's flags
|
||||
flags = data.flags | flags;
|
||||
|
||||
// Create a scene node, move and rotate it into place. The name
|
||||
// must be unique, however we might have to recognize some special
|
||||
|
@ -115,23 +117,29 @@ struct MeshLoader
|
|||
NiNode n = cast(NiNode)data;
|
||||
if(n !is null)
|
||||
// Handle the NiNode, and any children it might have
|
||||
handleNiNode(n, node);
|
||||
handleNiNode(n, node, flags);
|
||||
}
|
||||
|
||||
{
|
||||
NiTriShape n = cast(NiTriShape)data;
|
||||
if(n !is null)
|
||||
// Trishape, with a mesh
|
||||
handleNiTriShape(n, node);
|
||||
handleNiTriShape(n, node, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void handleNiNode(NiNode data, NodePtr node)
|
||||
void handleNiNode(NiNode data, NodePtr node, int flags)
|
||||
{
|
||||
// Ignore sound activators and similar objects.
|
||||
NiStringExtraData d = cast(NiStringExtraData) data.extra;
|
||||
if(d !is null && d.string == "MRK")
|
||||
return;
|
||||
if(d !is null)
|
||||
{
|
||||
if(d.string == "MRK")
|
||||
return;
|
||||
|
||||
if(d.string == "NCO")
|
||||
flags |= 0x800; // Temporary internal marker
|
||||
}
|
||||
|
||||
// Handle any effects here
|
||||
|
||||
|
@ -144,16 +152,31 @@ struct MeshLoader
|
|||
|
||||
// Loop through children
|
||||
foreach(Node n; data.children)
|
||||
insertNode(n, node);
|
||||
insertNode(n, node, flags);
|
||||
}
|
||||
|
||||
void handleNiTriShape(NiTriShape shape, NodePtr node)
|
||||
void handleNiTriShape(NiTriShape shape, NodePtr node, int flags)
|
||||
{
|
||||
char[] texture;
|
||||
char[] material;
|
||||
char[] newName = UniqueName(baseName);
|
||||
NiMaterialProperty mp;
|
||||
|
||||
bool hidden = (flags & 0x01) != 0; // Not displayed
|
||||
bool collide = (flags & 0x02) != 0; // Use this mesh for collision
|
||||
bool bbcollide = (flags & 0x04) != 0; // Use bounding box for
|
||||
// collision
|
||||
// Always use mesh collision for now
|
||||
if(bbcollide) collide = true;
|
||||
bbcollide = false;
|
||||
|
||||
// Things marked "NCO" should not collide with anything.
|
||||
if(flags & 0x800)
|
||||
collide = false;
|
||||
|
||||
// Skip the entire material phase for hidden nodes
|
||||
if(hidden) goto nomaterial;
|
||||
|
||||
// Scan the property list for textures
|
||||
foreach(Property p; shape.properties)
|
||||
{
|
||||
|
@ -227,6 +250,8 @@ struct MeshLoader
|
|||
texturePtr);
|
||||
}
|
||||
|
||||
nomaterial:
|
||||
|
||||
with(shape.data)
|
||||
{
|
||||
//writefln("Number of vertices: ", vertices.length);
|
||||
|
@ -251,7 +276,9 @@ struct MeshLoader
|
|||
maxY = -float.infinity,
|
||||
maxZ = -float.infinity;
|
||||
|
||||
// Calculate the bounding box. TODO: This is really a hack.
|
||||
// Calculate the bounding box. TODO: This is really a
|
||||
// hack. IIRC the bounding box supplied by the NIF could not
|
||||
// be trusted, but I can't remember why :/
|
||||
for( int i; i < vertices.length; i+=3 )
|
||||
{
|
||||
if( vertices[i] < minX ) minX = vertices[i];
|
||||
|
@ -269,20 +296,34 @@ struct MeshLoader
|
|||
float[9] matrix;
|
||||
ogre_getWorldTransform(node, trans.ptr, matrix.ptr);
|
||||
|
||||
// Create a bullet collision shape from the trimesh, if there
|
||||
// are any triangles present. Pass along the world
|
||||
// transformation as well, since we must transform the trimesh
|
||||
// data manually.
|
||||
if(facesPtr != null)
|
||||
bullet_createTriShape(triangles.length, facesPtr,
|
||||
vertices.length, vertices.ptr,
|
||||
// Next we must create the actual OGRE mesh and the collision
|
||||
// objects, based on the flags we have been given.
|
||||
assert(!bbcollide);
|
||||
/* // Bounding box collision currently disabled
|
||||
if(bbcollide)
|
||||
// Insert the bounding box into the collision system
|
||||
bullet_createBoxShape(minX, minY, minZ, maxX, maxY, maxZ,
|
||||
trans.ptr, matrix.ptr);
|
||||
|
||||
// Create the ogre mesh, associate it with the node
|
||||
ogre_createMesh(newName.ptr, vertices.length, vertices.ptr,
|
||||
normalsPtr, colorsPtr, uvsPtr, triangles.length, facesPtr,
|
||||
radius, material.ptr, minX, minY, minZ, maxX, maxY, maxZ,
|
||||
node);
|
||||
// Create a bullet collision shape from the trimesh. Pass
|
||||
// along the world transformation as well, since we must
|
||||
// transform the trimesh data manually.
|
||||
else*/if(collide)
|
||||
{
|
||||
assert(facesPtr !is null,
|
||||
"cannot create collision shape without a mesh");
|
||||
bullet_createTriShape(triangles.length, facesPtr,
|
||||
vertices.length, vertices.ptr,
|
||||
trans.ptr, matrix.ptr);
|
||||
}
|
||||
|
||||
// Create the ogre mesh, associate it with the node. Skip for
|
||||
// hidden nodes.
|
||||
if(!hidden)
|
||||
ogre_createMesh(newName.ptr, vertices.length, vertices.ptr,
|
||||
normalsPtr, colorsPtr, uvsPtr, triangles.length,
|
||||
facesPtr, radius, material.ptr, minX, minY, minZ,
|
||||
maxX, maxY, maxZ, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue