Hi,
I finally found another post that gets pretty close to what I wanted, but did
not work right out of the box (see
http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/2009-January/021653.html).
I wrote the following function starting from the above post's code and it
seems to work well, at least for my few test models.
Code:
float GetAlphaAtTexCoords(const osgUtil::LineSegmentIntersector::Intersection
*hit)
{
osg::Vec2 tc(0.0f,0.0f);
float alpha = -1.0f;
osg::Drawable* drawable = hit->drawable.get();
osg::Geometry* geometry = drawable ? drawable->asGeometry() : NULL;
osg::Vec3Array* vertices = geometry ?
dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : NULL;
if (vertices)
{
// get the vertex indices.
const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices
= hit->indexList;
const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios
= hit->ratioList;
if (3 == ratios.size() && 3 == indices.size())
{
osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ?
geometry->getTexCoordArray(0) : NULL;
osg::Vec2Array* texcoords_Vec2Array =
dynamic_cast<osg::Vec2Array*>(texcoords);
if (texcoords_Vec2Array)
{
osg::Vec2 tc0 = (*texcoords_Vec2Array)[indices[0]];
osg::Vec2 tc1 = (*texcoords_Vec2Array)[indices[1]];
osg::Vec2 tc2 = (*texcoords_Vec2Array)[indices[2]];
tc = tc0 * ratios[0] + tc1 * ratios[1] + tc2 * ratios[2];
}
else
return alpha;
}
else
return alpha;
}
else
return alpha;
osg::TexMat* activeTexMat = NULL;
osg::Texture2D* activeTexture = NULL;
osg::Image* activeImage = NULL;
if (geometry->getStateSet())
{
osg::TexMat* texMat =
dynamic_cast<osg::TexMat*>(geometry->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT));
if (texMat)
activeTexMat = texMat;
osg::Texture2D* texture =
dynamic_cast<osg::Texture2D*>(geometry->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXTURE));
if (texture)
activeTexture = texture;
else
return alpha;
activeImage = activeTexture->getImage();
}
else if (drawable->getNumParents() > 0)
{
// XXX - assumes texture info is at most one level up
for (unsigned int i = 0; i < drawable->getNumParents(); ++i)
{
// reset all ptrs just in case
activeTexMat = NULL;
activeTexture = NULL;
activeImage = NULL;
// get the current parent ptr
osg::Node *p = drawable->getParent(i);
if (p->getStateSet())
{
osg::TexMat* texMat =
dynamic_cast<osg::TexMat*>(p->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT));
if (texMat)
activeTexMat = texMat;
osg::Texture2D* texture =
dynamic_cast<osg::Texture2D*>(p->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXTURE));
if (texture)
activeTexture = texture;
else
continue;
activeImage = activeTexture->getImage();
if (activeImage)
break;// bail from the for loop
}
}
}
if (activeTexMat)
{
osg::Vec4 tc_transformed = osg::Vec4(tc.x(),tc.y(),0.0f,0.0f) *
activeTexMat->getMatrix();
tc.x() = tc_transformed.x();
tc.y() = tc_transformed.y();
}
if (activeImage)
{
// handle s wrapping
switch (activeTexture->getWrap(osg::Texture::WRAP_S))
{
case osg::Texture::CLAMP:
case osg::Texture::CLAMP_TO_BORDER:
case osg::Texture::CLAMP_TO_EDGE:
if (tc.x() < 0.0f)
tc.x() = 0.0f;
if (tc.x() > 1.0f)
tc.x() = 1.0f;
break;
case osg::Texture::MIRROR:
tc.x() = tc.x() - floor(tc.x());
if ((int)(floor(tc.x())) % 2)
tc.x() = 1.0f - tc.x();
break;
case osg::Texture::REPEAT:
tc.x() = tc.x() - floor(tc.x());
break;
}
// handle t wrapping
switch (activeTexture->getWrap(osg::Texture::WRAP_T))
{
case osg::Texture::CLAMP:
case osg::Texture::CLAMP_TO_BORDER:
case osg::Texture::CLAMP_TO_EDGE:
if (tc.y() < 0.0f)
tc.y() = 0.0f;
if (tc.y() > 1.0f)
tc.y() = 1.0f;
break;
case osg::Texture::MIRROR:
tc.y() = tc.y() - floor(tc.y());
if ((int)(floor(tc.y())) % 2)
tc.y() = 1.0f - tc.y();
break;
case osg::Texture::REPEAT:
tc.y() = tc.y() - floor(tc.y());
break;
}
osg::Vec4 rgba = activeImage->getColor(tc);
alpha = rgba.a();
}
return alpha;
}
Any comments on this function would be greatly appreciated. Thanks again for
your replies.
On a side note, during my testing I found that the indices vector (indices =
hit->indexList in the above code) from the
osgUtil::My_LineSegmentIntersector::Intersection class was corrupted. To be
more specific, the values in the vector's internal array were correct, but the
vector's internal members that keep track of its beginning, end, etc were
incorrect. This resulted in access violations and even failure when attempting
to clear the vector as well as incorrect reporting of its size. At first I
thought a leak was causing this, but found no corruption in the surrounding
memory and found that regardless of the order to the struct Intersection
members the index vector was the only member affected. Also, interestingly the
problem disappears if I switch the vector from unsigned int to signed int. My
guess is that this problem is caused by code that is improperly accessing the
vector memory via a raw pointer instead of the vector's normal interface. None
of my code does th
is, so I am left assuming that code somewhere in osg is doing this. In any
case, I have not yet found the cause. If anyone has any insight, I would
greatly appreciate it.
Thank you!
Cheers,
Matthew
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=19003#19003
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org