only half of terrain height field visible

Post Reply
chisser98
Posts: 5
Joined: Wed Apr 19, 2017 2:08 am

only half of terrain height field visible

Post by chisser98 » Mon Mar 19, 2018 2:27 am

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.PNG (1008.99 KiB) Viewed 922 times
physics height field 2.PNG
physics height field 2.PNG (1.24 MiB) Viewed 922 times
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

User avatar
drleviathan
Posts: 551
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: only half of terrain height field visible

Post by drleviathan » Mon Mar 19, 2018 3:52 pm

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?

chisser98
Posts: 5
Joined: Wed Apr 19, 2017 2:08 am

Re: only half of terrain height field visible

Post by chisser98 » Tue Mar 20, 2018 2:00 am

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.

Post Reply