From Jason Daly, fix to multi-texturing/detail texture handling.

This commit is contained in:
Robert Osfield
2004-10-06 19:19:22 +00:00
parent 2027011beb
commit a907042618
3 changed files with 218 additions and 86 deletions

View File

@@ -13,7 +13,6 @@
#include "Pool.h"
#include "opcodes.h"
#include "GeoSetBuilder.h"
#include "AttrData.h"
#include <osg/Object>
#include <osg/LOD>
@@ -55,7 +54,23 @@ void DynGeoSet::append(DynGeoSet* source)
APPEND_DynGeoSet_List(_coordList)
if (_normal_binding==osg::Geometry::BIND_PER_VERTEX || _normal_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_normalList)
if (_color_binding==osg::Geometry::BIND_PER_VERTEX || _color_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_colorList)
if (_texture_binding==osg::Geometry::BIND_PER_VERTEX || _texture_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_tcoordList)
for (unsigned int i = 0; i < source->_tcoordLists.size(); i++)
{
if ((getTextureBinding(i)==osg::Geometry::BIND_PER_VERTEX) ||
(getTextureBinding(i)==osg::Geometry::BIND_PER_PRIMITIVE))
{
if (source->_tcoordLists.size() > 0)
{
if (_tcoordLists.size() <= i)
_tcoordLists.resize(i+1);
_tcoordLists[i].insert(_tcoordLists[i].end(),
source->_tcoordLists[i].begin(),
source->_tcoordLists[i].end());
}
}
}
}
@@ -88,21 +103,28 @@ DynGeoSet::DynGeoSet()
_primtype = NO_PRIMITIVE_TYPE;
_normal_binding = osg::Geometry::BIND_OFF;
_color_binding = osg::Geometry::BIND_OFF;
_texture_binding = osg::Geometry::BIND_OFF;
_detailTextureEnabled = false;
_geom = new osg::Geometry;
}
void DynGeoSet::setBinding()
{
unsigned int i;
VERIFY_DynGeoSet_Binding(_normal_binding, _normalList)
VERIFY_DynGeoSet_Binding(_color_binding, _colorList)
VERIFY_DynGeoSet_Binding(_texture_binding, _tcoordList)
for (i = 0; i < _tcoordLists.size(); i++)
VERIFY_DynGeoSet_Binding(_texture_bindings[i], _tcoordLists[i])
// Set bindings
setNormalBinding(_normal_binding);
setColorBinding(_color_binding);
setTextureBinding(_texture_binding);
for (i = 0; i < _tcoordLists.size(); i++)
setTextureBinding(i, _texture_bindings[i]);
osg::StateSet* stateset = getStateSet();
if (stateset)
@@ -153,37 +175,58 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom)
}
}
if (!_tcoordList.empty())
for (unsigned int i = 0; i < _tcoordLists.size(); i++)
{
osg::Vec2Array* texcoords = dynamic_cast<osg::Vec2Array*>(geom->getTexCoordArray(0));
if (texcoords)
{
texcoords->insert(texcoords->end(),_tcoordList.begin(),_tcoordList.end());
}
else
{
texcoords = new osg::Vec2Array(_tcoordList.begin(),_tcoordList.end());
geom->setTexCoordArray(0,texcoords);
if (!_tcoordLists[i].empty())
{
// Grab the current layer's texture coordinate array from the
// geometry
osg::Vec2Array* texcoords =
dynamic_cast<osg::Vec2Array*>(geom->getTexCoordArray(i));
// If we got detail texture defined for this geometry, we need to setup new texcoord
// related on base texture ones. Using txDetail_m and txDetail_n values we read in
// ReaderWriterATTR and we got in AttrData class.
//
// We apply those values multiplying original texcoord.x by txDetail_m and texcoord.y
// by txDetail_n to get detail texture repeated.
//
// Julian Ortiz, June 18th 2003.
if ( (_attrdata != NULL) && (_attrdata->useDetail > 0) ) {
osg::Vec2Array *texcoords2 = new osg::Vec2Array(_tcoordList.begin(),_tcoordList.end());
for(unsigned int index=0;index<texcoords2->size();index++) {
(*texcoords2)[index][0]=(*texcoords)[index][0]*_attrdata->txDetail_m;
(*texcoords2)[index][1]=(*texcoords)[index][1]*_attrdata->txDetail_n;
}
geom->setTexCoordArray(1,texcoords2);
}
}
// See if we need to create the texture coordinate array or add to
// it
if (texcoords)
{
// Append the new texture coordinates to the end of the existing
// list
texcoords->insert(texcoords->end(),_tcoordLists[i].begin(),
_tcoordLists[i].end());
}
else
{
// Create a new texture coordinate array
texcoords = new osg::Vec2Array(_tcoordLists[i].begin(),
_tcoordLists[i].end());
geom->setTexCoordArray(i,texcoords);
}
}
}
// If this geometry uses a detail texture, we apply the detail texture
// scalars to the texture coordinates on layer 0 to get the detail texture
// coordinates, which we put on layer 1. Note that this assumes that
// layer 1 is not in use for multitexturing. This means that
// multitexturing and detail texturing are not supported at the same time.
if ((_detailTextureEnabled) && (!_tcoordLists.empty()) &&
(!_tcoordLists[0].empty()))
{
// Create a new texture coordinate array for the detail texture
// coordinates
osg::Vec2Array *texcoords2 = new osg::Vec2Array(_tcoordLists[0].begin(),
_tcoordLists[0].end());
// Scale the texture coordinates from layer 0
for(unsigned int index=0;index<texcoords2->size();index++)
{
(*texcoords2)[index][0] *= _detailTexCoord_m;
(*texcoords2)[index][1] *= _detailTexCoord_n;
}
// Set the new texcoord array on layer 1 (this wipes out any existing
// texture coordinates there)
geom->setTexCoordArray(1,texcoords2);
}
if (!_colorList.empty())
{
@@ -222,7 +265,6 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom)
indexBase += *itr;
}
}
}

View File

@@ -1,8 +1,14 @@
#ifndef __FLT_GEOSETBUILDER_H
#define __FLT_GEOSETBUILDER_H
// Added DynGeoSet::setDetailTextureAttrData that is used to store texture Attributes
// Added DynGeoSet::setDetailTextureAttrData that is used to store texture
// Attributes
// Julian Ortiz, June 18th 2003.
// ---
// Added support for multiple layers of texture coordinates. Changed the
// detail texture support to only store the M & N scalar values instead of
// the whole AttrData structure.
// Jason Daly, Sept 25, 2004
#include <osg/ref_ptr>
#include <osg/Vec2>
@@ -13,8 +19,6 @@
#include <osg/Material>
#include <osg/StateSet>
#include "AttrData.h"
#include <map>
#include <vector>
@@ -52,7 +56,14 @@ class DynGeoSet : public osg::Referenced
{
COMPARE_DynGeoSet_Parameter(_color_binding)
COMPARE_DynGeoSet_Parameter(_normal_binding)
COMPARE_DynGeoSet_Parameter(_texture_binding)
for (unsigned int i = 0; i < _texture_bindings.size(); i++)
{
if (getTextureBinding(i)<rhs.getTextureBinding(i))
return -1;
if (getTextureBinding(i)>rhs.getTextureBinding(i))
return 1;
}
if (_color_binding == osg::Geometry::BIND_OVERALL)
{
@@ -74,7 +85,14 @@ class DynGeoSet : public osg::Referenced
{
COMPARE_DynGeoSet_Parameter(_color_binding)
COMPARE_DynGeoSet_Parameter(_texture_binding)
for (unsigned int i = 0; i < _texture_bindings.size(); i++)
{
if (getTextureBinding(i)<rhs.getTextureBinding(i))
return -1;
if (getTextureBinding(i)>rhs.getTextureBinding(i))
return 1;
}
int result=getStateSet()->compare(*rhs.getStateSet(), true);
if (result!=0) return result;
@@ -94,7 +112,6 @@ class DynGeoSet : public osg::Referenced
}
return 0;
}
bool operator < (const DynGeoSet& rhs) const { return compare(rhs)<0; }
@@ -110,11 +127,29 @@ class DynGeoSet : public osg::Referenced
void setColorBinding(osg::Geometry::AttributeBinding bind) { _color_binding = bind; }
void setNormalBinding(osg::Geometry::AttributeBinding bind) { _normal_binding = bind; }
void setTextureBinding(osg::Geometry::AttributeBinding bind) { _texture_binding = bind; }
void setTextureBinding(osg::Geometry::AttributeBinding bind)
{
setTextureBinding(0, bind);
}
void setTextureBinding(unsigned int index,
osg::Geometry::AttributeBinding bind)
{
if (_texture_bindings.size() <= index)
_texture_bindings.resize(index+1);
_texture_bindings[index] = bind;
}
osg::Geometry::AttributeBinding getColorBinding() const { return _color_binding; }
osg::Geometry::AttributeBinding getNormalBinding() const { return _normal_binding; }
osg::Geometry::AttributeBinding getTextureBinding() const { return _texture_binding; }
osg::Geometry::AttributeBinding getTextureBinding() const { return getTextureBinding(0); }
osg::Geometry::AttributeBinding getTextureBinding(unsigned int index) const
{
if (_texture_bindings.size() > index)
return _texture_bindings[index];
else
return osg::Geometry::BIND_OFF;
}
void setPrimType(osg::PrimitiveSet::Mode type) { _primtype=type; }
osg::PrimitiveSet::Mode getPrimType() const { return _primtype; }
@@ -123,17 +158,33 @@ class DynGeoSet : public osg::Referenced
inline void addCoord(const osg::Vec3& coord) { _coordList.push_back(coord); }
inline void addNormal(const osg::Vec3& normal) { _normalList.push_back(normal); }
inline void addColor(const osg::Vec4& color) { _colorList.push_back(color); }
inline void addTCoord(const osg::Vec2& tcoord) { _tcoordList.push_back(tcoord); }
inline void addTCoord(const osg::Vec2& tcoord) { addTCoord(0, tcoord); }
inline void addTCoord(unsigned int index, const osg::Vec2& tcoord)
{
if (_tcoordLists.size() <= index)
_tcoordLists.resize(index+1);
typedef std::vector<osg::Vec3> CoordList;
typedef std::vector<osg::Vec3> NormalList;
typedef std::vector<osg::Vec4> ColorList;
typedef std::vector<osg::Vec2> TcoordList;
_tcoordLists[index].push_back(tcoord);
}
typedef std::vector<osg::Vec3> CoordList;
typedef std::vector<osg::Vec3> NormalList;
typedef std::vector<osg::Vec4> ColorList;
typedef std::vector<osg::Vec2> TcoordList;
typedef std::vector<TcoordList> TcoordLists;
typedef std::vector<osg::Geometry::AttributeBinding> TextureBindings;
const CoordList& getCoordList() { return _coordList; }
const NormalList& getNormalList() { return _normalList; }
const ColorList& getColorList() { return _colorList; }
const TcoordList& getTcoordList() { return _tcoordList; }
const TcoordList& getTcoordList() { return getTcoordList(0); }
const TcoordList& getTcoordList(unsigned int index)
{
if (_tcoordLists.size() <= index)
_tcoordLists.resize(index+1);
return _tcoordLists[index];
}
void append(DynGeoSet* source);
void setBinding();
@@ -144,8 +195,27 @@ class DynGeoSet : public osg::Referenced
inline int coordListSize() const { return _coordList.size(); }
inline int normalListSize() const { return _normalList.size(); }
inline int colorListSize() const { return _colorList.size(); }
inline int tcoordListSize() const { return _tcoordList.size(); }
inline void setDetailTextureAttrData(AttrData *attrdata) {_attrdata=attrdata; }
inline int tcoordListSize() const { return tcoordListSize(0); }
inline int tcoordListSize(unsigned int index) const
{
if (_tcoordLists.size() <= index)
return _tcoordLists[index].size() ;
else
return 0;
}
inline void enableDetailTexture() { _detailTextureEnabled=true; }
inline void disableDetailTexture() { _detailTextureEnabled=false; }
inline void setDetailTexCoords(int32 m, int32 n)
{
// If somebody knows what the other TX_DETAIL parameters do,
// please add them. I looked through the OF specs as well as
// the SGIS_detail_texture extension, and I didn't find any
// clear explanation. The only reason this is here at all is
// because of Julian Ortiz' previous work.
_detailTexCoord_m = m;
_detailTexCoord_n = n;
}
osg::Geometry* getGeometry() {
CERR << "_geom.get(): " << _geom.get()
@@ -173,10 +243,12 @@ class DynGeoSet : public osg::Referenced
osg::Geometry::AttributeBinding _color_binding;
ColorList _colorList;
osg::Geometry::AttributeBinding _texture_binding;
TcoordList _tcoordList;
TextureBindings _texture_bindings;
TcoordLists _tcoordLists;
AttrData *_attrdata;
int32 _detailTexCoord_m;
int32 _detailTexCoord_n;
bool _detailTextureEnabled;
};

View File

@@ -1572,19 +1572,25 @@ void ConvertFromFLT::setTexture ( FaceRecord *rec, SFace *pSFace, osg::StateSet
}
}
//Now, an ugly thing,... we have detected that in Creator we defined that a texture will we used as
//detail texture, and we load it as it using texture unit 1,... but we also need to create texture
//coordinates to map this detail texture, I found that texture coordinates assigment is made in
//DynGeoSet::addToGeometry and the easy way I found to create those new coordinates is to add a method
//to DynGeoSet class named setDetailTextureStatus that pass detail Texture AttrData class, so when
//DynGeoSet::addToGeometry runs it reads this class and create new texture coordinates if we got a valid
//AttrData object. I now this is not a good way to do it, and I expect someone with more osg knowledge
//could make it in a better way.
// Julian Ortiz, June 18th 2003.
if (pSFace->iDetailTexturePattern != -1 && detailTextureAttrData && detailTextureAttrData->stateset)
dgset->setDetailTextureAttrData(detailTextureAttrData);
// If a detail texture structure exists, set the texture
// coordinate scalars on the current DynGeoSet, so the correct
// detail texture coordinates get generated later.
if (pSFace->iDetailTexturePattern != -1 &&
detailTextureAttrData &&
detailTextureAttrData->stateset)
{
// Set the texture coordinate scalars
dgset->setDetailTexCoords(detailTextureAttrData->txDetail_m,
detailTextureAttrData->txDetail_n);
// Make sure detail texturing is on
dgset->enableDetailTexture();
}
else
dgset->setDetailTextureAttrData(NULL);
{
// Make sure detail texturing is off
dgset->disableDetailTexture();
}
// Merge face stateset with texture stateset
osgStateSet->merge(*textureStateSet);
@@ -1671,9 +1677,18 @@ ConvertFromFLT::addMultiTexture( DynGeoSet* dgset, MultiTextureRecord* mtr )
return;
}
osg::StateSet *textureStateSet = dynamic_cast<osg::StateSet *> ((pTexturePool->getTexture((int)mt->data[l].texture,mtr->getFlightVersion()))->stateset);
// Get the texture attribute data from the texture pool
flt::AttrData *textureAttrData = dynamic_cast<flt::AttrData *> (pTexturePool->getTexture((int)mt->data[l].texture,mtr->getFlightVersion()));
CERR << "pTexturePool->getTexture((int)mt->data[l].texture): " << pTexturePool->getTexture((int)mt->data[l].texture,mtr->getFlightVersion()) << "\n";
if (!textureAttrData)
{
CERR << "unable to set up multi-texture layer." << std::endl;
return;
}
// Get the texture state set from the attribute data structure
osg::StateSet *textureStateSet = textureAttrData->stateset;
CERR << "textureStateSet: " << textureStateSet << "\n";
if (!textureStateSet)
@@ -1709,10 +1724,13 @@ ConvertFromFLT::addMultiTexture( DynGeoSet* dgset, MultiTextureRecord* mtr )
CERR << ", referenceCount: "
<< geom->referenceCount() << "\n";
// Get the state set from the current geometry
osg::StateSet* geom_stateset = geom->getStateSet();
CERR << "geom_stateset: " << geom_stateset << "\n";
// See if we need to merge or set the texture state set on the
// geometry
if ( geom_stateset )
{
geom_stateset->merge( *texture_stateset );
@@ -1722,6 +1740,10 @@ ConvertFromFLT::addMultiTexture( DynGeoSet* dgset, MultiTextureRecord* mtr )
CERR << "Setting layer " << i << "\n";
}
// Set the texture binding on the current texture unit to
// per-vertex
dgset->setTextureBinding(i, osg::Geometry::BIND_PER_VERTEX);
l++;
}
}
@@ -1730,9 +1752,7 @@ ConvertFromFLT::addMultiTexture( DynGeoSet* dgset, MultiTextureRecord* mtr )
void
ConvertFromFLT::addUVList( DynGeoSet* dgset, UVListRecord* uvr )
{
osg::Geometry* geom = dgset->getGeometry();
if (!geom || !uvr || !uvr->isAncillaryRecord())
if (!dgset || !uvr || !uvr->isAncillaryRecord())
{
osg::notify(osg::WARN)<<"ConvertFromFLT::addUVList( DynGeoSet*, UVListRecord*) has been passed invalid paramters."<<std::endl;
return;
@@ -1752,22 +1772,20 @@ ConvertFromFLT::addUVList( DynGeoSet* dgset, UVListRecord* uvr )
{
if ( (1 << (32-i)) & uvl->layers )
{
osg::Vec2Array* tcoords = new osg::Vec2Array;
CERR << "Has layer " << i << "\n";
// Assume we are working with vertex lists for now
for ( int v = l*num_coords; v < (l+1)*num_coords; v++ )
{
uvl->coords.vertex[v].endian();
CERR << "( u: " << uvl->coords.vertex[v].coords[1] << ", "
<< "v: " << uvl->coords.vertex[v].coords[0] << ")\n";
/// FIXME: should be (x,y) instead of (y,x) - ENDIAN problem???
tcoords->push_back( osg::Vec2( uvl->coords.vertex[v].coords[1],
uvl->coords.vertex[v].coords[0] ) );
}
if ( !tcoords->empty() )
{
CERR << "Setting tcoords " << i << ": " << tcoords << "\n";
geom->setTexCoordArray( i, tcoords );
<< "v: " << uvl->coords.vertex[v].coords[0] << ")\n";
/// FIXME: should be (x,y) instead of (y,x) - ENDIAN problem???
// Add the texture coordinates to the current DynGeoSet
dgset->addTCoord(i,
osg::Vec2(uvl->coords.vertex[v].coords[1],
uvl->coords.vertex[v].coords[0]));
}
l++;
@@ -1819,9 +1837,6 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, osg::Group& osgParent, F
// Vertices
addVertices(pBuilder, osgParent, rec);
// Add face to builder pool
pBuilder->addPrimitive();
// Visit ancillary records
for(int i=0; i < rec->getNumChildren(); i++)
{
@@ -1842,9 +1857,9 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, osg::Group& osgParent, F
}
// original code, but causes crash becayse addPrimitive can invalidate teh dgset pointer.
// addMultiTexture( dgset, mtr );
addMultiTexture( dgset, mtr );
addMultiTexture( pBuilder->getDynGeoSet(), mtr );
// addMultiTexture( pBuilder->getDynGeoSet(), mtr );
}
break;
@@ -1860,6 +1875,9 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, osg::Group& osgParent, F
}
}
// Add face to builder pool
pBuilder->addPrimitive();
// Look for subfaces
{
_nSubfaceLevel++;
@@ -3012,7 +3030,7 @@ uint32 ConvertFromFLT::setMeshNormals ( const uint32 &numVerts, const LocalVerte
{
if (!pool || !mesh || !geometry)
{
osg::notify(osg::WARN)<<"OpenFlight loader detected error:: ConvertFromFLT::setMeshTexCoordinates passed null objects."<<std::endl;
osg::notify(osg::WARN)<<"OpenFlight loader detected error:: ConvertFromFLT::setMeshNormals passed null objects."<<std::endl;
}
// If there aren't any coordinates...
@@ -3065,7 +3083,7 @@ uint32 ConvertFromFLT::setMeshColors ( const uint32 &numVerts, const LocalVertex
{
if (!pool || !mesh || !geometry)
{
osg::notify(osg::WARN)<<"OpenFlight loader detected error:: ConvertFromFLT::setMeshTexCoordinates passed null objects."<<std::endl;
osg::notify(osg::WARN)<<"OpenFlight loader detected error:: ConvertFromFLT::setMeshColors passed null objects."<<std::endl;
}
// If there aren't any colors...