Page 1 of 1

only half of terrain height field visible

Posted: Mon Mar 19, 2018 2:27 am
by chisser98
Hello,

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.
physics height field.PNG
physics height field 2.PNG
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);
}
if I double the length of the height field, I change this line:

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);
to this:

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);
and this is the code I used to create my rigid body:

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;
}
I'm at a bit of a loss as to why seemingly only half of the height field displays here.

Does anyone have any ideas?

Jarrett

Re: only half of terrain height field visible

Posted: Mon Mar 19, 2018 3:52 pm
by drleviathan
Is that really the only line you change when you want to double the size of your terrain?

This line only allocates image.width*image.height space in the std::vector and it seems to me you would want to double that.

Code: Select all

heightMapData.resize(image.width * image.height);
Meanwhile you would loop heightMapData.size() times, but pull data out of image, which has only image.width*image.height data points. Maybe you should not change any of the code but instead use an image that is twice as big?

Re: only half of terrain height field visible

Posted: Tue Mar 20, 2018 2:00 am
by chisser98
Thanks for the reply drleviathan.

It appears that my problem was with my rendering code - turns out I was only rendering half of the debug data provided by bullet.