I found a solution which involves computing the barycentric coordinates.
However it seems that is not working properly.
To compute the barycentric coordinates I need to associate to the vertices of
the triangles a coordinate among
(1,0,0) (0,1,0) (0,0,1)
for doing that I use the following function, which is based on the assumption I
load the 3d model using the option noTriStripPolygons so that each polygon is a
triangle (and not a strip of triangles).
Code:
void OSGGraphicsUtils::setBarycentricCoordinates(osg::Node * object,
osg::Program *shaderProgram)
{
GeodeFinder myGeodeFinder;
std::vector< osg::Geode *> listOfGeodes;
object->accept(myGeodeFinder);
listOfGeodes = myGeodeFinder.getNodeList();
std::cout << "there are " << listOfGeodes.size() << " geodes" << std::endl;
for (int j = 0; j < listOfGeodes.size() ; j++)
{
//get the current geode
osg::Geode* currentGeode = listOfGeodes.at(j);
if (currentGeode != NULL)
{
for (int i = 0; i < currentGeode->getNumDrawables(); i++)
{
osg::Geometry *cubeGeometry =
currentGeode->getDrawable(i)->asGeometry();
if (!cubeGeometry) continue;
int numAttribs =
cubeGeometry->getVertexArray()->getNumElements();
std::cout<< "number of vertices is "<<numAttribs<<std::endl;
osg::ref_ptr <osg::Vec3Array> cubeVertexVector;
if (! strcmp (cubeGeometry->getVertexArray()->className(),
"Vec3Array"))
{
cubeVertexVector = (osg::Vec3Array *)
cubeGeometry->getVertexArray();
} else {
//handle the error however you want -- here all I do is
print a warning and bail out.
std::cerr << "Unexpected VertexArray className.\n" <<
std::endl;
return;
}
osg::Vec3Array *array = new
osg::Vec3Array(cubeVertexVector->size());
std::map <osg::Vec3, int> vertexMap;
osg::Vec3 nextVertex;
int j = 0;
for (int i = 0; i < cubeVertexVector->size(); i++) {
nextVertex = cubeVertexVector->at(i);
if (j == 3) j = 0;
if(vertexMap.find(nextVertex) == vertexMap.end())
{//check if it is the first, the second o the third vertex
of the triangle and associate appropriate attribute
if (j==0)
{
array->at(i) = (osg::Vec3(1.0,0.0,0.0));
vertexMap[nextVertex] = i;
}
else if (j==1)
{
array->at(i) = (osg::Vec3(0.0,1.0,0.0));
vertexMap[nextVertex] = i;
}
else if (j==2)
{
array->at(i) = (osg::Vec3(0.0,0.0,1.0));
vertexMap[nextVertex] = i;
}
}
else
{
//std::cout<< "Vertex already present in the map at
index "<< vertexMap[nextVertex] << std::endl;
array->at(i) =
osg::Vec3(array->at(vertexMap[nextVertex]));
}
j++;
}
if( !cubeGeometry->getVertexAttribArray( 31 ) )
{
//cubeGeometry->setVertexAttribData(31,
osg::Geometry::ArrayData(array,osg::Geometry::BIND_PER_VERTEX, GL_FALSE ) );
std::cout << "setting barycentric attr unit array of size "
<< array->getNumElements() << std::endl;
cubeGeometry->setVertexAttribArray(31, array);
cubeGeometry->setVertexAttribBinding(BARYCENTRIC_ATTR_UNIT,
osg::Geometry::BIND_PER_VERTEX);
}
}
}
}
}
The attribute is binded to the program with the line of code
Code:
void OSGGraphicsUtils::loadShaders(osg::ref_ptr<osg::StateSet> &objectStateSet,
const char *vsSource, const char *fsSource, osg::ref_ptr<osg::Node> object,
const char *shaderName)
{
// set shader for mammoth
osg::ref_ptr<osg::Program> shaderProgram = new osg::Program;
shaderProgram->setName(shaderName);
shaderProgram->addShader( new osg::Shader( osg::Shader::VERTEX, vsSource )
);
shaderProgram->addShader( new osg::Shader( osg::Shader::FRAGMENT, fsSource
) );
objectStateSet = object->getOrCreateStateSet();
objectStateSet->setAttributeAndModes(shaderProgram, osg::StateAttribute::ON
);
if (strcmp(shaderName,"ShaderWireframe")==0)
{
std::cout << "adding barycentric coordinate attribute to the shader" <<
std::endl;
shaderProgram->addBindAttribLocation("a_BaryCoord", 31);
OSGGraphicsUtils::setBarycentricCoordinates(object.get(),
shaderProgram.get());
}
}
This is the vertex shader
Code:
precision highp float;
varying vec3 vBC;
attribute vec3 a_BaryCoord;
void main(void)
{
vBC = a_BaryCoord;
gl_Position = ftransform();
}
This is the fragment shader I use for testing.
Code:
precision highp float;
varying vec3 vBC;
void main (void)
{
gl_FragColor = vec4(vBC.r, vBC.g, vBC.b, 1.0);
}
In theory with a correct binding of the attribute I should obtain triangles
with a red, a green and a blue vertex and the colors inside the triangle should
interpolate based on these three vertices. All the triangles of the model
should look like this http://www.arcsynthesis.org/gltut/Basics/VertexColors.png
However the result is bizzarre and unexpected. As a matter of fact I have a
cube with three black sides and one side red, one side green and one side blue.
Can you help me, please? I feel I am near to the solution but I can't find the
error!
Thank you very much for your time,
John
[/code]
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=57059#57059
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org