celmodel fixes:

- Removed unused code in #if 0/#endif blocks
- Added non-const accessor for Mesh::PrimitiveGroup
- Return more information in pick result: mesh, primitive group, and primitive
index instead of just the distance to first intersection.
sensor-dev
Chris Laurel 2010-02-10 20:52:43 +00:00
parent 626e24d9f9
commit f9260386b2
5 changed files with 96 additions and 177 deletions

View File

@ -245,6 +245,16 @@ Mesh::getGroup(unsigned int index) const
}
Mesh::PrimitiveGroup*
Mesh::getGroup(unsigned int index)
{
if (index >= groups.size())
return NULL;
else
return groups[index];
}
unsigned int
Mesh::addGroup(PrimitiveGroup* group)
{
@ -350,7 +360,7 @@ Mesh::aggregateByMaterial()
bool
Mesh::pick(const Vector3d& rayOrigin, const Vector3d& rayDirection, double& distance) const
Mesh::pick(const Vector3d& rayOrigin, const Vector3d& rayDirection, PickResult* result) const
{
double maxDistance = 1.0e30;
double closest = maxDistance;
@ -379,6 +389,7 @@ Mesh::pick(const Vector3d& rayOrigin, const Vector3d& rayDirection, double& dist
(nIndices >= 3) &&
!(primType == TriList && nIndices % 3 != 0))
{
unsigned int primitiveIndex = 0;
index32 index = 0;
index32 i0 = (*iter)->indices[0];
index32 i1 = (*iter)->indices[1];
@ -423,7 +434,15 @@ Mesh::pick(const Vector3d& rayOrigin, const Vector3d& rayDirection, double& dist
double s0 = (m11 * q0 - m01 * q1) * d;
double s1 = (m00 * q1 - m10 * q0) * d;
if (s0 >= 0.0 && s1 >= 0.0 && s0 + s1 <= 1.0)
{
closest = t;
if (result)
{
result->group = *iter;
result->primitiveIndex = primitiveIndex;
result->distance = closest;
}
}
}
}
}
@ -461,82 +480,28 @@ Mesh::pick(const Vector3d& rayOrigin, const Vector3d& rayDirection, double& dist
}
}
primitiveIndex++;
} while (index < nIndices);
}
}
if (closest != maxDistance)
{
distance = closest;
return true;
}
else
{
return false;
}
return closest != maxDistance;
}
#if 0
void
Mesh::render(const std::vector<const Material*>& materials,
RenderContext& rc) const
bool
Mesh::pick(const Vector3d& rayOrigin, const Vector3d& rayDirection, double& distance) const
{
// The first time the mesh is rendered, we will try and place the
// vertex data in a vertex buffer object and potentially get a huge
// rendering performance boost. This can consume a great deal of
// memory, since we're duplicating the vertex data. TODO: investigate
// the possibility of deleting the original data. We can always map
// read-only later on for things like picking, but this could be a low
// performance path.
if (!vbInitialized && isVBOSupported())
PickResult result;
bool hit = pick(rayOrigin, rayDirection, &result);
if (hit)
{
vbInitialized = true;
if (nVertices * vertexDesc.stride > MinVBOSize)
{
glGenBuffersARB(1, &vbObject);
if (vbObject != 0)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbObject);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
nVertices * vertexDesc.stride,
vertices,
GL_STATIC_DRAW_ARB);
}
}
distance = result.distance;
}
if (vbObject != 0)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbObject);
rc.setVertexArrays(vertexDesc, NULL);
}
else
{
rc.setVertexArrays(vertexDesc, vertices);
}
unsigned int lastMaterial = ~0u;
// Iterate over all primitive groups in the mesh
for (vector<PrimitiveGroup*>::const_iterator iter = groups.begin();
iter != groups.end(); iter++)
{
// Set up the material
const Material* mat = NULL;
unsigned int materialIndex = (*iter)->materialIndex;
if (materialIndex != lastMaterial && materialIndex < materials.size())
mat = materials[materialIndex];
rc.setMaterial(mat);
rc.drawGroup(**iter);
}
if (vbObject != 0)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
return hit;
}
#endif
AlignedBox<float, 3>
@ -591,11 +556,6 @@ Mesh::transform(const Vector3f& translation, float scale)
{
const Vector3f tv = (Map<Vector3f>(reinterpret_cast<float*>(vdata)) + translation) * scale;
Map<Vector3f>(reinterpret_cast<float*>(vdata)) = tv;
#if CELVEC
reinterpret_cast<float*>(vdata)[0] = tv.x();
reinterpret_cast<float*>(vdata)[1] = tv.y();
reinterpret_cast<float*>(vdata)[2] = tv.z();
#endif
}
// Point sizes need to be scaled as well
@ -726,3 +686,12 @@ Mesh::getVertexAttributeSize(VertexAttributeFormat fmt)
return 0;
}
}
Mesh::PickResult::PickResult() :
mesh(NULL),
group(NULL),
primitiveIndex(0),
distance(-1.0)
{
}

View File

@ -136,6 +136,17 @@ class Mesh
unsigned int nIndices;
};
class PickResult
{
public:
PickResult();
Mesh* mesh;
PrimitiveGroup* group;
unsigned int primitiveIndex;
double distance;
};
Mesh();
~Mesh();
@ -144,6 +155,7 @@ class Mesh
const VertexDescription& getVertexDescription() const;
const PrimitiveGroup* getGroup(unsigned int index) const;
PrimitiveGroup* getGroup(unsigned int index);
unsigned int addGroup(PrimitiveGroup* group);
unsigned int addGroup(PrimitiveGroupType prim,
unsigned int materialIndex,
@ -164,6 +176,7 @@ class Mesh
const std::string& getName() const;
void setName(const std::string&);
bool pick(const Eigen::Vector3d& origin, const Eigen::Vector3d& direction, PickResult* result) const;
bool pick(const Eigen::Vector3d& origin, const Eigen::Vector3d& direction, double& distance) const;
Eigen::AlignedBox<float, 3> getBoundingBox() const;

View File

@ -132,30 +132,56 @@ Model::addMesh(Mesh* m)
bool
Model::pick(const Vector3d& rayOrigin, const Vector3d& rayDirection, double& distance) const
Model::pick(const Eigen::Vector3d& rayOrigin,
const Eigen::Vector3d& rayDirection,
Mesh::PickResult* result) const
{
double maxDistance = 1.0e30;
double closest = maxDistance;
Mesh::PickResult closestResult;
for (vector<Mesh*>::const_iterator iter = meshes.begin();
iter != meshes.end(); iter++)
{
double d = maxDistance;
if ((*iter)->pick(rayOrigin, rayDirection, d) && d < closest)
Mesh::PickResult result;
if ((*iter)->pick(rayOrigin, rayDirection, &result))
{
closest = d;
if (result.distance < closest)
{
closestResult = result;
closestResult.mesh = *iter;
closest = result.distance;
}
}
}
if (closest != maxDistance)
{
distance = closest;
if (result)
{
*result = closestResult;
}
return true;
}
else
{
return false;
}
}
bool
Model::pick(const Vector3d& rayOrigin, const Vector3d& rayDirection, double& distance) const
{
Mesh::PickResult result;
bool hit = pick(rayOrigin, rayDirection, &result);
if (hit)
{
distance = result.distance;
}
return hit;
}
@ -432,25 +458,3 @@ Model::sortMeshes(const MeshComparator& comparator)
// Sort the meshes so that completely opaque ones are first
sort(meshes.begin(), meshes.end(), MeshComparatorAdapter(comparator));
}
#if 0
void
Model::loadTextures()
{
for (vector<const Material*>::const_iterator iter = materials.begin();
iter != materials.end(); iter++)
{
const Mesh::Material* m = *iter;
if (m->maps[Material::DiffuseMap] != InvalidResource)
GetTextureManager()->find(m->maps[Material::DiffuseMap]);
if (m->maps[Material::NormalMap] != InvalidResource)
GetTextureManager()->find(m->maps[Material::NormalMap]);
if (m->maps[Material::SpecularMap] != InvalidResource)
GetTextureManager()->find(m->maps[Material::SpecularMap]);
if (m->maps[Material::EmissiveMap] != InvalidResource)
GetTextureManager()->find(m->maps[Material::EmissiveMap]);
}
}
#endif

View File

@ -68,14 +68,25 @@ class Model
*/
unsigned int addMesh(Mesh* mesh);
/*! Find the closest intersection between the ray (given
/** Find the closest intersection between the ray (given
* by origin and direction) and the model. If the ray
* intersects the model, return true and fill in the
* pick result record. If the result record is NULL, it
* ignored, and the function just computes whether or
* not the ray intersected the model.
*/
bool pick(const Eigen::Vector3d& rayOrigin,
const Eigen::Vector3d& rayDirection,
Mesh::PickResult* result) const;
/** Find the closest intersection between the ray (given
* by origin and direction) and the model. If the ray
* intersects the model, return true and set distance;
* otherwise return false and leave distance unmodified.
*/
bool pick(const Eigen::Vector3d& rayOrigin,
const Eigen::Vector3d& rayDirection,
double& distance) const;
double& distance) const;
void transform(const Eigen::Vector3f& translation, float scale);

View File

@ -571,84 +571,6 @@ Token TokenStream::nextToken()
}
#if 0
class BinaryInputStream
{
public:
BinaryInputStream(istream* in) :
m_in(in)
{
}
private:
istream* m_in;
};
class BinaryOutputStream
{
public:
BinaryOutputStream(ostream* out) :
m_out(out)
{
}
void writeUint32(unsigned int i);
void writeInt16(int i);
void writeFloat(float f);
void writeString(const std::string s)
{
writeInt16(static_cast<int16>(s.length()));
m_out->write(s.c_str(), s.length());
}
private:
ostream* m_out;
};
class CmodBinaryOutputStream : public BinaryOuputStream
{
public:
CmodBinaryOuputStream(ostream* out) :
BinaryOutputStream(out)
{
}
void writeToken(ModelFileToken val)
{
writeInt16((int) val);
}
void writeType(ModelFileType val)
{
writeInt16((int) val);
}
void writeTypeFloat1(float f)
{
writeType(CMOD_Float1);
writeFloat(f);
}
void writeTypeColor(const Material::Color& c)
{
writeType(CMOD_Color);
writeFloat(c.red);
writeFloat(c.green);
writeFloat(c.blue);
}
void writeTypeString(const string& s)
{
writeType(out, CMOD_String);
writeString(s);
}
};
#endif
/*!
This is an approximate Backus Naur form for the contents of ASCII cmod
files. For brevity, the categories &lt;unsigned_int&gt; and &lt;float&gt; aren't