[C++, DX9] btHeightfieldTerrainShape problem

Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

[C++, DX9] btHeightfieldTerrainShape problem

Post by Ripiz »

That's how I create my heightfield shape/body:

Code: Select all

		btHeightfieldTerrainShape *heightFieldShape = new btHeightfieldTerrainShape(128, 128, heights, 8, -1024, 1016, 2, PHY_UCHAR, false); //byte heights[128][128];
		btTransform matrix;
		btVector3 localInertia(0,0,0);
		body = new btRigidBody(0, 0, heightFieldShape, localInertia);	
		body->setWorldTransform(matrix);
		extern btDynamicsWorld *physics;
		physics->addRigidBody(body);
I can't see my heightfield, neither spheres collide with it. I added debug drawing and first line drawed was from e+10 to IND. So something went wrong.. Anyone have idea if my parameters are correct and etc?
Brutal
Posts: 14
Joined: Mon Jul 26, 2010 8:03 am

Re: [C++, DX9] btHeightfieldTerrainShape problem

Post by Brutal »

You don't seem to be setting the origin, rotation, etc. of the body. Here is the function I use to create the heightfield shape

Code: Select all

PhysicsObject* PhysicsManager::createHeightfieldShape(int size, float* data, const Ogre::Real& minHeight, const Ogre::Real& maxHeight, const Ogre::Vector3& position, const Ogre::Real& scale)
{
	// Convert height data in a format suitable for the physics engine
	float *terrainHeights = new float[size * size];
	assert(terrainHeights != 0);

    for (int i = 0; i < size; i++)
	{
		memcpy(terrainHeights + size * i, data + size * (size - i - 1), sizeof(float) * size);
	}

	btScalar heightScale = 1.f;
	btVector3 localScaling(scale, heightScale, scale);

	btHeightfieldTerrainShape *terrainShape = new btHeightfieldTerrainShape(size, size, terrainHeights, 1/*ignore*/, minHeight, maxHeight, 1, PHY_FLOAT, true);
	terrainShape->setUseDiamondSubdivision(true);
	terrainShape->setLocalScaling(localScaling);
	mCollisionShapes.push_back(terrainShape);

	//Create Rigid Body using 0 mass so it is static
	btRigidBody *body = new btRigidBody(INFINITE_MASS, new btDefaultMotionState(), terrainShape);
	body->setFriction(0.8f);
	body->setHitFraction(0.8f);
	body->setRestitution(0.6f);
	body->getWorldTransform().setOrigin(btVector3(position.x, position.y + (maxHeight - minHeight) / 2, position.z));
	body->getWorldTransform().setRotation(Convert::toBullet(Ogre::Quaternion::IDENTITY));
	body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);

	mDynamicsWorld->addRigidBody(body);

	return NULL; //fix this to return proper object later
}
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] btHeightfieldTerrainShape problem

Post by Ripiz »

Thanks. I've found where problem was :)
But I encountered new one.
My heightmap isn't rotated correctly, but even if I rotate it, seems I need to mirror it over some axis to make it appear correctly. I wasn't able to find any function to somehow mirror it, so I'm trying to mirror height values. But even after I simply copy values from one array to other, my heightmap doesn't appear correctly anymore, why?

Code: Select all

		byte heights2[128][128];
		for(register uint x = 0; x < 128; x++)
			for(register uint y = 0; y < 128; y++)
				heights2[x][y] = heights[x][y];
		btHeightfieldTerrainShape *heightFieldShape = new btHeightfieldTerrainShape(128, 128, heights2, 1, -1024, 1016, 2, PHY_UCHAR, false);
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] btHeightfieldTerrainShape problem

Post by SteveSegreto »

There is a boolean option when you create the btHeightfieldTerrainShape (final parameter of constructor) that should let you mirror the heightfield's triangles.
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] btHeightfieldTerrainShape problem

Post by Ripiz »

Code: Select all

//do you mean change this into that?
btHeightfieldTerrainShape *heightFieldShape = new btHeightfieldTerrainShape(128, 128, heights2, 1, -1024, 1016, 2, PHY_UCHAR, false);
                                                                                                                                |
                                                                                                                                |
                                                                                                                               \|/
                                                                                                                                Y
btHeightfieldTerrainShape *heightFieldShape = new btHeightfieldTerrainShape(128, 128, heights2, 1, -1024, 1016, 2, PHY_UCHAR, true);
I did that, but nothing changed.

Why heightmap is bugged if I copy values to local variable?
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] btHeightfieldTerrainShape problem

Post by SteveSegreto »

I'm not quite sure what you mean by "mirror over some axis" or "copy values from one array to the other", can you post a bit of code, please?

The btHeightfieldTerrainShape keeps a direct pointer to the array of height values it received from you in it's constructor. Changing *ANY* of the values in that array in your code will change the height values used by the Bullet library. It doesn't keep a copy of those height values. This is great for certain situations (like just selecting a 20x20 heightfield around the character's current position in the game world and changing it as the player moves through a *VERY* large world), because it frees you from having to copy thousands and thousands of heightfield values to Bullet.

BTW, do you have and use the DebugDrawer enabled? Are you using DirectX 9.0? Here is a little DebugDrawer class you can use for DirectX 9.0 if you need it:

Code: Select all


//-----------------------------------------------------------------------------
// File: CDebugDrawer.h
//
// Purpose: A debug drawer used by the physics library.
//
// Copyright (c) 2010 Steve Segreto. All rights reserved.
//-----------------------------------------------------------------------------
#pragma once

#include "LinearMath/btIDebugDraw.h"
#include <vector>

struct VCol
{
	VCol(const D3DXVECTOR3& v, D3DCOLOR c):pos(v),col(c){}

	D3DXVECTOR3 pos;
	D3DCOLOR    col;
};

class CDebugDrawer : public btIDebugDraw
{
public:
	int                 m_debugMode;
	std::vector< VCol > m_vertices;

	CDebugDrawer();

	void            present();
	virtual void	drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor);
	virtual void	drawLine(const btVector3& from,const btVector3& to,const btVector3& color);
	virtual void	drawSphere (const btVector3& p, btScalar radius, const btVector3& color);
	virtual void	drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha);
	virtual void	drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha);
	virtual void	drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color);
	virtual void	reportErrorWarning(const char* warningString);
	virtual void	draw3dText(const btVector3& location,const char* textString);
	virtual void	setDebugMode(int debugMode);
	virtual int		getDebugMode() const { return m_debugMode;}

};

Code: Select all

//-----------------------------------------------------------------------------
// File: CDebugDrawer.cpp
//
// Purpose: A debug drawer used by the physics library.
//
// Copyright (c) 2010 Steve Segreto. All rights reserved.
//-----------------------------------------------------------------------------
#include "CDebugDrawer.h"

CDebugDrawer::CDebugDrawer() : m_debugMode(0)
{
}

void CDebugDrawer::present()
{
	if (!m_vertices.size()) return;

	D3DXMATRIX world;
	D3DXMatrixIdentity( &world );
	g_d3dDevice->SetTransform(D3DTS_WORLD, &world);
	g_d3dDevice->SetVertexShader( NULL ) );
	g_d3dDevice->SetPixelShader( NULL ) );
	g_d3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
	g_d3dDevice->SetFVF( D3DFVF_XYZ | D3DFVF_DIFFUSE );
	g_d3dDevice->DrawPrimitiveUP(D3DPT_LINELIST, m_vertices.size() / 2, &m_vertices[0], sizeof(VCol));

	m_vertices.clear();
}

void CDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor)
{
	D3DXVECTOR3 vFrom, vTo, vCFrom, vCTo;

	memcpy( &vFrom,  &from,      sizeof( D3DXVECTOR3 ) );
	memcpy( &vTo,    &to,        sizeof( D3DXVECTOR3 ) );
	memcpy( &vCFrom, &fromColor, sizeof( D3DXVECTOR3 ) );
	memcpy( &vCTo,   &toColor,   sizeof( D3DXVECTOR3 ) );

	D3DCOLOR cFrom, cTo;
	cFrom = D3DCOLOR_ARGB( 0xFF, (DWORD)(vCFrom.x * 255), (DWORD)(vCFrom.y * 255), (DWORD)(vCFrom.z * 255) );
	cTo   = D3DCOLOR_ARGB( 0xFF, (DWORD)(vCTo.x * 255), (DWORD)(vCTo.y * 255), (DWORD)(vCTo.z * 255) );

	VCol vert[] = {VCol(vFrom, cFrom), VCol(vTo, cTo)};

	if (m_vertices.size() < 50000)
	{
		m_vertices.push_back( vert[0] );
		m_vertices.push_back( vert[1] );
	}
}

void CDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
{
	drawLine(from, to, color, color);
}

void CDebugDrawer::drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
{
}

void CDebugDrawer::drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha)
{
}

void CDebugDrawer::drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha)
{
}

void CDebugDrawer::setDebugMode(int debugMode)
{
	m_debugMode = debugMode;
}

void CDebugDrawer::draw3dText(const btVector3& location,const char* textString)
{
}

void CDebugDrawer::reportErrorWarning(const char* warningString)
{
	OutputDebugStringA( warningString );
	OutputDebugStringA( "\n" );
}

void CDebugDrawer::drawContactPoint(const btVector3& pointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)
{
}
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] btHeightfieldTerrainShape problem

Post by Ripiz »

SteveSegreto wrote:The btHeightfieldTerrainShape keeps a direct pointer to the array of height values it received from you in it's constructor. It doesn't keep a copy of those height values.
That explains everything. I know where problem is now. Thanks a lot!

Also thanks for that DebugDrawer class, I'll improve mine ^^