Sign in to follow this  
kandemor

OPCODE question

Recommended Posts

kandemor    122
Hello, I'm trying to add a collision system based on Opcode in my engine. I've downloaded the 1.3 version and the user's manual, but it's the user's manual of the 1.2 version and I think some things have changed. Can someone help me, please? Where can I find information about the 1.3 version? And some sample code? Thank you! VinCenT

Share this post


Link to post
Share on other sites
codemonster    595
Indeed, the Opcode docs are awful. The Open Dynamics Engine uses Opcode optionally. Download the ODE source and have a look into the file named collision_trimesh.cpp.

Here's a small example using Opcode 1.3 I wrote earlier this year. It's by far not complete (and there may be bugs), but it worked and I didnt need more functionality at the time. The Opcode parts/classes you are looking for either begin with Opcode:: or uppercase letters. All the lowercased classes etc. are from my project and shouldnt really bother you.

Header:

namespace coll
{
class c_triangle_manager : public i_triangle_manager
{
public:
c_triangle_manager( scene::i_mesh* mesh, const math::c_matrix* transformation );
virtual ~c_triangle_manager();

virtual bool get_colliders( const math::t_spheref& sphere, Opcode::SphereCache& cache, Opcode::SphereCollider& collider );
virtual bool get_colliders( const math::t_aabb3df& box, Opcode::AABBCache& cache, Opcode::AABBCollider& collider );
virtual bool get_colliders( const math::c_ray& ray, Container& container, Opcode::RayCollider& collider );

d_forceinline virtual const math::t_aabb3df& get_bounding_box() const { return m_bbox; }
d_forceinline virtual const std::vector < Point >& get_vertices() const { return m_list_of_vertices; }
d_forceinline virtual const std::vector < IndexedTriangle >& get_indexed_triangles() const { return m_list_of_triangles; }

private:
math::t_aabb3df m_bbox;
Opcode::Model m_model;
Opcode::MeshInterface m_imesh;

std::vector < Point > m_list_of_vertices;
std::vector < IndexedTriangle > m_list_of_triangles;
};
}



Implementation:

namespace coll
{
c_triangle_manager::c_triangle_manager( scene::i_mesh* mesh, const math::c_matrix* transformation )
{
debug_assert( mesh );

size_t idx_count = 0;

m_bbox.reset( 0.1f, 0.1f, 0.1f );

t_u32 count = mesh->get_submesh_count();
for ( t_u32 idx = 0; idx < count; ++idx )
{
scene::i_submesh* buffer = mesh->get_submesh( idx );

if ( buffer )
{
vid::s_vertex_data& vertex_data = buffer->get_vertex_data();
vid::s_index_data& index_data = buffer->get_index_data();

t_s32 vertex_count = vertex_data.get_vertex_count();
t_s32 index_count = index_data.get_index_count();

t_u16* indices = index_data.get_index_pointer();

math::t_vector3f* vertices = vertex_data.get_vertex_pointer();
debug_assert( vertices );

t_u32 i0, i1, i2;

Point pt;
math::t_vector3f v;

size_t i;

for ( i = 0; i < index_count; i+=3 )
{
i0 = indices[ i + 0 ];
i1 = indices[ i + 1 ];
i2 = indices[ i + 2 ];

v = vertices[ i0 ];
m_bbox.insert( v );
pt.x = v.x; pt.y = v.y; pt.z = v.z;
m_list_of_vertices.push_back( pt );

v = vertices[ i1 ];
m_bbox.insert( v );
pt.x = v.x; pt.y = v.y; pt.z = v.z;
m_list_of_vertices.push_back( pt );

v = vertices[ i2 ];
m_bbox.insert( v );
pt.x = v.x; pt.y = v.y; pt.z = v.z;
m_list_of_vertices.push_back( pt );

m_list_of_triangles.push_back( IndexedTriangle( idx_count+0, idx_count+1, idx_count+2 ) );
idx_count+=3;
}

}
}

m_imesh.SetNbTriangles( m_list_of_triangles.size() );
m_imesh.SetNbVertices( m_list_of_vertices.size() );

if ( !m_imesh.SetPointers( &m_list_of_triangles[ 0 ], &m_list_of_vertices[ 0 ] ) )
{
// TODO
}

udword degenerate = m_imesh.CheckTopology();
if ( degenerate )
{
// TODO
}

Opcode::OPCODECREATE opcc;

opcc.mIMesh = &m_imesh;
opcc.mNoLeaf = true;
opcc.mQuantized = true;
//opcc.mCollisionHull = false;
opcc.mKeepOriginal = false;
opcc.mCanRemap = true;


if ( !m_model.Build( opcc ) )
{
// TODO
}
}


c_triangle_manager::~c_triangle_manager()
{
}


bool c_triangle_manager::get_colliders( const math::t_spheref& sphere, Opcode::SphereCache& cache, Opcode::SphereCollider& collider )
{
Point center( sphere.center.x, sphere.center.y, sphere.center.z );
Sphere s( center, sphere.radius );

return collider.Collide( cache, s, m_model );
}


bool c_triangle_manager::get_colliders( const math::t_aabb3df& box, Opcode::AABBCache& cache, Opcode::AABBCollider& collider )
{
Point min;
min.x = box.min.x;
min.y = box.min.y;
min.z = box.min.z;

Point max;
max.x = box.max.x;
max.y = box.max.y;
max.z = box.max.z;

AABB aabb;
aabb.SetMinMax( min, max );

return collider.Collide( cache, aabb, m_model );
}


bool c_triangle_manager::get_colliders( const math::c_ray& ray, Container& container, Opcode::RayCollider& collider )
{
Point origin;
origin.x = ray.origin.x;
origin.y = ray.origin.y;
origin.z = ray.origin.z;

Point direction;
direction.x = ray.normal.x;
direction.y = ray.normal.y;
direction.z = ray.normal.z;

Ray opray( origin, direction );

return collider.Collide( opray, m_model );
}

}



Usage:
i removed some parts in the following code snippet to make the usage clearer...

math::t_vector3f position;
math::t_spheref sphere;
Opcode::SphereCache cache;
Opcode::SphereCollider collider;
coll::i_triangle_manager* tmgr;

// removed code for clarity

if ( tmgr )
{
sphere.center.set( position.x, position.y, position.z );
sphere.radius = m_bsphere_radius;

bool result = tmgr->get_colliders( sphere, cache, collider );

if ( result )
{
udword nbtouched = collider.GetNbTouchedPrimitives();

if ( nbtouched )
{
// even more removed code...
}
}
}



This really isnt the best or cleanest example that was ever created, so please use with care. But I hope it helps anyway...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this