Ported pfb, txp and obj loaders across to use osg::Geometry.

This commit is contained in:
Robert Osfield
2002-06-26 14:34:04 +00:00
parent 40fefcf335
commit bdafc27d9c
7 changed files with 125 additions and 225 deletions

View File

@@ -24,7 +24,7 @@
#include <osg/Transform>
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/Geometry>
#include <osg/StateSet>
#include <osg/Material>
#include <osg/Texture>
@@ -203,205 +203,87 @@ osg::Drawable* ReaderWriterOBJ::makeDrawable(GLMmodel* obj,
unsigned int ntris = grp->numtriangles;
unsigned int i = 0;
// geoset
osg::GeoSet* gset = new osg::GeoSet;
// geometry
osg::Geometry* geom = new osg::Geometry;
// primitives are only triangles
gset->setPrimType(osg::GeoSet::TRIANGLES);
gset->setNumPrims(ntris);
int* primLen = new int[ntris];
gset->setPrimLengths(primLen);
geom->addPrimitive(new osg::DrawArrays(osg::Primitive::TRIANGLES,0,ntris*3));
// the following code for mapping the coords, normals and texcoords
// is complicated greatly by the need to create seperate out the
// sets of coords etc for each drawable.
typedef std::vector<int> IndexVec;
// fill an vector full of 0's, one for each vertex.
IndexVec vcount(obj->numvertices+1,0);
IndexVec ncount(obj->numnormals+1,0);
IndexVec tcount(obj->numtexcoords+1,0);
bool needNormals = obj->normals && obj->normals>0;
bool needTexcoords = obj->texcoords && obj->numtexcoords>0 && grp->hastexcoords;
osg::Vec3Array* coordArray = new osg::Vec3Array(3*ntris);
osg::Vec3Array::iterator coords = coordArray->begin();
geom->setVertexArray(coordArray);
osg::Vec3Array::iterator normals = 0;
if (needNormals)
{
osg::Vec3Array* normalArray = new osg::Vec3Array(3*ntris);
geom->setNormalArray(normalArray);
geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
normals = normalArray->begin();
}
osg::Vec2Array::iterator texcoords = 0;
if (needTexcoords)
{
osg::Vec2Array* texCoordArray = new osg::Vec2Array(3*ntris);
geom->setTexCoordArray(0,texCoordArray);
texcoords = texCoordArray->begin();
}
// first count the number of vertices used in this group.
for (i = 0; i < ntris; i++)
{
GLMtriangle* tri = &(tris[grp->triangles[i]]);
// increment the count once for each traingle corner.
++vcount[tri->vindices[0]];
++vcount[tri->vindices[1]];
++vcount[tri->vindices[2]];
if (needNormals)
for(int corner=0;corner<3;++corner)
{
++ncount[tri->nindices[0]];
++ncount[tri->nindices[1]];
++ncount[tri->nindices[2]];
}
if (needTexcoords)
{
++tcount[tri->tindices[0]];
++tcount[tri->tindices[1]];
++tcount[tri->tindices[2]];
}
}
int ci = tri->vindices[corner]*3;
IndexVec::iterator itr;
int numCoords = 0;
for(itr=vcount.begin();
itr!=vcount.end();
++itr)
{
if ((*itr)>0) ++numCoords;
}
if (numCoords==0) return NULL;
int numNormals = 0;
for(itr=ncount.begin();
itr!=ncount.end();
++itr)
{
if ((*itr)>0) ++numNormals;
}
int numTexcoords = 0;
for(itr=tcount.begin();
itr!=tcount.end();
++itr)
{
if ((*itr)>0) ++numTexcoords;
}
// allocate drawables vertices.
osg::Vec3* coords = new osg::Vec3[numCoords];
// allocate drawables normals.
osg::Vec3* normals = NULL;
if (numNormals>0) normals = new osg::Vec3[numNormals];
// allocate drawables textcoords.
osg::Vec2* texcoords = NULL;
if (numTexcoords>0) texcoords = new osg::Vec2[numTexcoords];
// fill an vector full of 0's, one for each vertex.
IndexVec vmapping(obj->numvertices+1,-1);
IndexVec nmapping(obj->numnormals+1,-1);
IndexVec tmapping(obj->numtexcoords+1,-1);
int coordCount = 0;
for (i = 0; i < vcount.size(); i++)
{
if (vcount[i]>0)
{
// note obj_x -> osg_x,
// obj_y -> -osg_z,
// obj_z -> osg_y,
coords[coordCount].set(obj->vertices[i*3+0],
-obj->vertices[i*3+2],
obj->vertices[i*3+1]);
coords->set(obj->vertices[ci],-obj->vertices[ci+2],obj->vertices[ci+1]);
++coords;
vmapping[i]=coordCount;
++coordCount;
if (needNormals)
{
int ni = tri->nindices[corner]*3;
// note obj_x -> osg_x,
// obj_y -> osg_z,
// obj_z -> osg_y,
// to rotate the about x axis to have model z upwards.
normals->set(obj->normals[ni],-obj->normals[ni+2],obj->normals[ni+1]);
++normals;
}
if (needTexcoords)
{
int ti = tri->tindices[corner]*2;
texcoords->set(obj->texcoords[ti+0], obj->texcoords[ti+1]);
++texcoords;
}
}
}
int normCount = 0;
for (i = 0; i < ncount.size(); i++)
{
if (ncount[i]>0)
{
// note obj_x -> osg_x,
// obj_y -> osg_z,
// obj_z -> osg_y,
// to rotate the about x axis to have model z upwards.
normals[normCount].set(obj->normals[i*3+0],
-obj->normals[i*3+2],
obj->normals[i*3+1]);
nmapping[i]=normCount;
++normCount;
}
}
int texCount = 0;
for (i = 0; i < tcount.size(); i++)
{
if (tcount[i]>0)
{
texcoords[texCount].set(obj->texcoords[i*2+0], obj->texcoords[i*2+1]);
tmapping[i]=texCount;
++texCount;
}
}
// index arrays
unsigned int* cindex = NULL;
cindex = new unsigned int[ntris * 3];
unsigned int* nindex = NULL;
if (normals)
nindex = new unsigned int[ntris * 3];
unsigned int* tindex = NULL;
if (texcoords)
tindex = new unsigned int[ntris * 3];
// setup arrays
for (i = 0; i < ntris; i++) {
primLen[i] = 3;
GLMtriangle* tri = &(tris[grp->triangles[i]]);
cindex[i*3+0] = vmapping[tri->vindices[0]];
cindex[i*3+1] = vmapping[tri->vindices[1]];
cindex[i*3+2] = vmapping[tri->vindices[2]];
if (nindex) {
nindex[i*3+0] = nmapping[tri->nindices[0]];
nindex[i*3+1] = nmapping[tri->nindices[1]];
nindex[i*3+2] = nmapping[tri->nindices[2]];
}
if (tindex) {
tindex[i*3+0] = tmapping[tri->tindices[0]];
tindex[i*3+1] = tmapping[tri->tindices[1]];
tindex[i*3+2] = tmapping[tri->tindices[2]];
}
}
if (coords && cindex)
gset->setCoords(coords, cindex);
if (normals && nindex) {
gset->setNormals(normals, nindex);
gset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
}
if (texcoords && tindex) {
gset->setTextureCoords(texcoords, tindex);
gset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
}
// state and material (if any)
if (mtl) {
gset->setStateSet(mtl[grp->material]);
geom->setStateSet(mtl[grp->material]);
}
else
osg::notify(osg::INFO) << "Group " << grp->name << " has no material" << std::endl;
return gset;
return geom;
}

View File

@@ -463,23 +463,20 @@ int ConvertFromPerformer::getNumVerts(pfGeoSet *gset)
}
osg::GeoSet* ConvertFromPerformer::visitGeoSet(osg::Geode* osgGeode,pfGeoSet* geoset)
osg::Drawable* ConvertFromPerformer::visitGeoSet(osg::Geode* osgGeode,pfGeoSet* geoset)
{
if (geoset==NULL) return NULL;
osg::GeoSet* osgGeoSet = dynamic_cast<osg::GeoSet*>(getOsgObject(geoset));
if (osgGeoSet)
osg::Drawable* osgDrawable = dynamic_cast<osg::Drawable*>(getOsgObject(geoset));
if (osgDrawable)
{
if (osgGeode) osgGeode->addDrawable(osgGeoSet);
return osgGeoSet;
if (osgGeode) osgGeode->addDrawable(osgDrawable);
return osgDrawable;
}
osgGeoSet = new osg::GeoSet;
if (osgGeode) osgGeode->addDrawable(osgGeoSet);
regisiterPfObjectForOsgObject(geoset,osgGeoSet);
visitGeoState(osgGeoSet,geoset->getGState());
// we'll make it easy to convert by using the Performer style osg::GeoSet,
// and then convert back to a osg::Geometry afterwards.
osg::ref_ptr<osg::GeoSet> osgGeoSet = new osg::GeoSet;
int i;
@@ -702,11 +699,23 @@ osg::GeoSet* ConvertFromPerformer::visitGeoSet(osg::Geode* osgGeode,pfGeoSet* ge
}
return osgGeoSet;
visitGeoState(osgGeoSet,geoset->getGState());
// convert to osg::Geometry, as osg::GeoSet is now deprecated.
osgDrawable = osgGeoSet->convertToGeometry();
if (osgDrawable)
{
osgGeode->addDrawable(osgDrawable);
regisiterPfObjectForOsgObject(geoset,osgDrawable);
}
return osgDrawable;
}
osg::StateSet* ConvertFromPerformer::visitGeoState(osg::GeoSet* osgGeoSet,pfGeoState* geostate)
osg::StateSet* ConvertFromPerformer::visitGeoState(osg:Drawable* osgDrawable,pfGeoState* geostate)
{
if (geostate==NULL) return NULL;
@@ -718,7 +727,7 @@ osg::StateSet* ConvertFromPerformer::visitGeoState(osg::GeoSet* osgGeoSet,pfGeoS
}
osgStateSet = new osg::StateSet;
if (osgGeoSet) osgGeoSet->setStateSet(osgStateSet);
if (osgDrawable) osgDrawable->setStateSet(osgStateSet);
regisiterPfObjectForOsgObject(geostate,osgStateSet);

View File

@@ -45,8 +45,8 @@ class ConvertFromPerformer {
osg::Node* visitBillboard(osg::Group* osgParent,pfBillboard* billboard);
int getNumVerts(pfGeoSet *gset);
osg::GeoSet* visitGeoSet(osg::Geode* osgParent,pfGeoSet* geoset);
osg::StateSet* visitGeoState(osg::GeoSet* osgGeoSet,pfGeoState* geostate);
osg::Drawable* visitGeoSet(osg::Geode* osgParent,pfGeoSet* geoset);
osg::StateSet* visitGeoState(osg::Drawable* osgGeoSet,pfGeoState* geostate);
osg::Material* visitMaterial(osg::StateSet* osgStateSet,pfMaterial* front_mat,pfMaterial* back_mat);
osg::Texture* visitTexture(osg::StateSet* osgStateSet,pfTexture* tex);

View File

@@ -2,7 +2,6 @@
#include "osg/Notify"
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/Texture>
#include "osg/GL"

View File

@@ -2,7 +2,6 @@
#include "osg/Notify"
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/Texture>
#include "osg/GL"

View File

@@ -30,8 +30,6 @@
#include "TrPageParser.h"
#include <osg/GeoSet>
#include <string>
#include <vector>
#include <memory> // for auto_ptr

View File

@@ -30,7 +30,7 @@
#include <osg/Billboard>
#include <osg/Matrix>
#include <osg/Transform>
#include <osg/GeoSet>
#include <osg/Geometry>
#include <osg/CullFace>
#include <osg/Light>
#include <osg/Transparency>
@@ -216,30 +216,30 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
geom.GetMaterial(0,matId, local);
geom.GetNumNormal(numNorm);
Vec3* vertices = new Vec3[numVert];
Vec3Array* vertices = new Vec3Array(numVert);
// Get vertices
geom.GetVertices(vertices);
geom.GetVertices(&(vertices->front()));
// Turn the trpgGeometry into something Performer can understand
GeoSet *gset = 0L;
Geometry *geometry = 0L;
// Get texture coordinates
Vec2* tex_coords = 0L;
Vec2Array* tex_coords = 0L;
trpgTexData td;
if (geom.GetTexCoordSet(0,&td))
{
tex_coords = new Vec2[numVert];
tex_coords = new Vec2Array(numVert);
for (int i=0 ;i < numVert; i++)
{
tex_coords[i][0] = td.floatData[2*i+0];
tex_coords[i][1] = td.floatData[2*i+1];
(*tex_coords)[i].set(td.floatData[2*i+0],td.floatData[2*i+1]);
}
}
Vec3* normals = 0L;
Vec3Array* normals = 0L;
if (numNorm == numVert)
{
normals = new Vec3[numVert];
geom.GetNormals(normals);
normals = new Vec3Array(numVert);
geom.GetNormals(&(normals->front()));
}
Geode *geode = new Geode();
@@ -248,8 +248,8 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
case trpgGeometry::Triangles:
{
gset = new GeoSet;
gset->setPrimType(GeoSet::TRIANGLES);
geometry = new Geometry;
geometry->addPrimitive(new DrawArrays(Primitive::TRIANGLES,0,numPrims*3));
}
break;
case trpgGeometry::TriStrips:
@@ -258,10 +258,15 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
int* primitives = new int[numPrims];
geom.GetPrimLengths(primitives);
// Define GeoSet
gset = new GeoSet;
gset->setPrimType(GeoSet::TRIANGLE_STRIP);
gset->setPrimLengths(primitives);
// Define Geomtry
geometry = new Geometry;
int first=0;
for(int i=0;i<numPrims;++i)
{
geometry->addPrimitive(new DrawArrays(Primitive::TRIANGLE_STRIP,first,primitives[i]));
first += primitives[i];
}
}
break;
case trpgGeometry::TriFans:
@@ -269,10 +274,21 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
// Need primitive lengths too
int* primitives = new int[numPrims];
geom.GetPrimLengths(primitives);
// Need to flip the fans
// create the trifan primitives.
geometry = new Geometry;
int first=0;
int i;
for(i=0;i<numPrims;++i)
{
geometry->addPrimitive(new DrawArrays(Primitive::TRIANGLE_FAN,first,primitives[i]));
first += primitives[i];
}
// Need to flip the fans coords.
int ind = 0;
for (int i=0;i<numPrims;i++)
for (i=0;i<numPrims;++i)
{
int start=ind+1;
int end=primitives[i]+ind-1;
@@ -281,20 +297,16 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
// Swap vertices, texture coords & normals
for (int j=0; j < numSwap; j++ )
{
std::swap(vertices[start], vertices[end]);
std::swap((*vertices)[start], (*vertices)[end]);
if( tex_coords )
std::swap(tex_coords[start], tex_coords[end]);
std::swap((*tex_coords)[start], (*tex_coords)[end]);
if(normals)
std::swap(normals[start], normals[end]);
std::swap((*normals)[start], (*normals)[end]);
start++;
end--;
}
ind += primitives[i];
}
// Define GeoSet
gset = new GeoSet;
gset->setPrimType(GeoSet::TRIANGLE_FAN);
gset->setPrimLengths(primitives);
}
break;
default:
@@ -305,12 +317,14 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
// Add it to the current parent group
Group *top = parse->GetCurrTop();
if (gset)
if (geometry)
{
gset->setCoords(vertices);
gset->setNumPrims(numPrims);
geometry->setVertexArray(vertices);
if (normals)
gset->setNormals(normals);
{
geometry->setNormalArray(normals);
geometry->setNormalBinding(Geometry::BIND_PER_VERTEX);
}
// Note: Should check number of materials first
// Note: Should be combining multiple geosets
ref_ptr<StateSet> sset = 0L;
@@ -321,12 +335,11 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
if (tex_coords)
{
gset->setTextureCoords(tex_coords);
gset->setTextureBinding(GeoSet::BIND_PERVERTEX);
geometry->setTexCoordArray( 0, tex_coords);
}
gset->setStateSet(sset.get());
geode->addDrawable(gset);
geometry->setStateSet(sset.get());
geode->addDrawable(geometry);
top->addChild(geode);
}
return (void *) 1;