I am trying to add physics to my terrain using btHeightfieldTerrainShape. I have slowly got something working, however, it seems like only half of my physics height field is rendering (using debug rendering).
I am using a 257 * 257 greyscale image for my terrain heightmap.
Oddly, if I double the length of the physics height field, it appears to actually render the full height field (I do seem to get crashes when I do this, however).
I have attached 2 images - one is my normal render of the terrain height field, and the second is when I double the length of the terrain height field.
This is the code I used to create the terrain height field:
Code: Select all
std::vector<char> heightMapData;
CollisionShapeHandle PhysicsEngine::createStaticTerrainShape(const image::Image& image)
{
int32 dataSize = (image.format == image::Format::FORMAT_RGBA ? 4 : 3);
heightMapData.resize(image.width * image.height);
int j=0;
for (int i=0; i < heightMapData.size(); ++i)
{
heightMapData[i] = (image.data[j] + image.data[j+1] + image.data[j+2]) / 3;
j+=dataSize;
}
std::cout << image.width << ", " << image.height << std::endl;
auto shape = std::make_unique<btHeightfieldTerrainShape>(image.width, image.height, &heightMapData[0], 1.0f/8.0f, -1024, 1024, 1, PHY_UCHAR, true);
shapes_.push_back(std::move(shape));
auto index = shapes_.size() - 1;
return CollisionShapeHandle(index, 1);
}
Code: Select all
auto shape = std::make_unique<btHeightfieldTerrainShape>(image.width, image.height, &heightMapData[0], 1.0f/8.0f, -1024, 1024, 1, PHY_UCHAR, true);
Code: Select all
auto shape = std::make_unique<btHeightfieldTerrainShape>(image.width, image.height*2, &heightMapData[0], 1.0f/8.0f, -1024, 1024, 1, PHY_UCHAR, true);
Code: Select all
RigidBodyObjectHandle PhysicsEngine::createRigidBodyObject(
const PhysicsSceneHandle& physicsSceneHandle,
const CollisionShapeHandle& collisionShapeHandle,
const glm::vec3& position,
const glm::quat& orientation,
const float32 mass,
const float32 friction,
const float32 restitution,
std::unique_ptr<IMotionChangeListener> motionStateListener,
const UserData& userData
)
{
auto& shape = shapes_[collisionShapeHandle.index()];
btTransform transform;
transform.setRotation( btQuaternion(orientation.x, orientation.y, orientation.z, orientation.w) );
transform.setOrigin( btVector3(position.x, position.y, position.z) );
btScalar bulletMass(mass);
btVector3 localInertia(0.0f, 0.0f, 0.0f);
if (bulletMass != btScalar(0.0f))
{
shape->calculateLocalInertia(bulletMass, localInertia);
}
auto& physicsScene = physicsScenes_[physicsSceneHandle];
auto rigidBodyObjectHandle = physicsScene.rigidBodyData.create();//std::make_unique<BulletRigidBodyData>();
auto& rigidBodyData = physicsScene.rigidBodyData[rigidBodyObjectHandle];
rigidBodyData.motionState = std::make_unique<BulletMotionState>(transform, std::move(motionStateListener));
btRigidBody::btRigidBodyConstructionInfo constructionInfo(bulletMass, rigidBodyData.motionState.get(), shape.get(), localInertia);
constructionInfo.m_friction = friction;
constructionInfo.m_restitution = restitution;
rigidBodyData.rigidBody = std::make_unique<btRigidBody>(constructionInfo);
rigidBodyData.userData = std::make_unique<BulletUserData>();
rigidBodyData.userData->rigidBodyObjectHandle = rigidBodyObjectHandle;
rigidBodyData.userData->type = BulletCollisionObjectType::RIGID_BODY;
rigidBodyData.userData->userData = userData;
auto rigidBodyDataPointer = &rigidBodyData;
auto rigidBodyPointer = rigidBodyData.rigidBody.get();
rigidBodyPointer->setUserPointer(rigidBodyDataPointer);
physicsScene.dynamicsWorld->addRigidBody(rigidBodyPointer);
return rigidBodyObjectHandle;
}
Does anyone have any ideas?
Jarrett