//
// This is a patch for the Inventor 2.0 SoPointSet node, which will
// generate incorrect normal indices when its startIndex field is not
// zero.
//
// To apply this patch, compile this file into a .o and then link
// the .o before -lInventor. The linker may give a warning.
// This is normal and expected.
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void
SoPointSet::generatePrimitives(SoAction *action)
{
// When generating primitives for picking, delay computing default
// texture coordinates
SbBool forPicking = action->isOfType(SoRayPickAction::getClassTypeId());
SbBool materialPerPoint, normalPerPoint;
long numPts;
int curCoord, i;
SoPrimitiveVertex pv;
SoPointDetail detail;
// Push state, just in case we decide to set the NormalElement
// because we're doing auto-normal generation.
SoState *state = action->getState();
state->push();
// This extra level of brackets is to make bundle constructors get
// called before state->pop() is called:
{
const SoGLCoordinateElement *ce = (const SoGLCoordinateElement *)
SoCoordinateElement::getInstance(action->getState());
// Figure out number of points in set
curCoord = (int) startIndex.getValue();
numPts = numPoints.getValue();
if (numPts == SO_POINT_SET_USE_REST_OF_POINTS)
numPts = ce->getNum() - curCoord;
materialPerPoint = areMaterialsPerPoint(action);
normalPerPoint = areNormalsPerPoint(action);
// Test for auto-normal case; since this modifies an element this
// MUST BE DONE BEFORE ANY BUNDLES ARE CREATED!
SbVec3f defaultNormal(0, 0, 1);
const SoNormalElement *ne = SoNormalElement::getInstance(state);
if (SoNormalBindingElement::get(state) ==
SoNormalBindingElement::DEFAULT &&
curCoord + numPts > ne->getNum()) {
SoNormalElement::set(state, this, 1, &defaultNormal);
normalPerPoint = FALSE;
}
if (forPicking)
pv.setTextureCoords(SbVec4f(0.0, 0.0, 0.0, 0.0));
pv.setDetail(&detail);
SoNormalBundle nb(action, FALSE);
SoTextureCoordinateBundle tcb(action, FALSE, ! forPicking);
pv.setMaterialIndex(curCoord);
detail.setMaterialIndex(curCoord);
if (! normalPerPoint) {
pv.setNormal(nb.get(0));
detail.setNormalIndex(0);
}
// Get the complexity element and decide how points will be skipped
// during processing; note that we don't want to skip anything
// when picking.
float cmplxValue = SoComplexityElement::get(action->getState());
float delta = 1.8 * (0.5 - ((cmplxValue < 0.5) ? cmplxValue : 0.5));
float fraction = 0.0;
if (forPicking)
delta = 0.0;
for (i = 0; i < numPts; i++, fraction += delta) {
// Check to see if this point should be skipped due to complexity
if (fraction >= 1.0) {
fraction -= 1.0;
curCoord++;
continue;
}
// Set coordinates, normal, and texture coordinates in
// detail
pv.setPoint(ce->get3(curCoord));
detail.setCoordinateIndex(curCoord);
if (normalPerPoint) {
pv.setNormal(nb.get(curCoord));
detail.setNormalIndex(curCoord);
}
if (materialPerPoint) {
pv.setMaterialIndex(curCoord);
detail.setMaterialIndex(curCoord);
}
if (tcb.isFunction()) {
if (! forPicking)
pv.setTextureCoords(tcb.get(pv.getPoint(),
pv.getNormal()));
detail.setTextureCoordIndex(0);
}
else {
pv.setTextureCoords(tcb.get(curCoord));
detail.setTextureCoordIndex(curCoord);
}
// Generate a point primitive
invokePointCallbacks(action, &pv);
curCoord++;
}
}
state->pop(); // Restore NormalElement
}
http://www.sgi.com/tech/Inventor/workarounds/PointSet2.0.C
(possibly inaccurate URL)
01/1995