const SbVec4f &
SoTextureCoordinateEnvironment::valueCallback(void *action,
    const SbVec3f &point,
    const SbVec3f &normal)
//
////////////////////////////////////////////////////////////////////////
{
    SoAction *a = (SoAction *)action;

    //
    // See the glTexGen() man page for the math here.
    //

    // First, map normal and point into eye space:
    const SbMatrix &mm = SoModelMatrixElement::get(a->getState());
    const SbMatrix &vm = SoViewingMatrixElement::get(a->getState());

    // Compute the matrix that transforms normals from object-space to
    // eye-space; use the inverse transpose to scale correctly
    SbVec3f normalE;
    SbMatrix nm = (vm * mm).inverse().transpose();
    nm.multDirMatrix(normal, normalE);

    SbVec3f pointE;
    mm.multVecMatrix(point, pointE);  // Gives world-space point
    vm.multVecMatrix(pointE, pointE); // ... to eye-space.

    // Get the normalized vector from the eye (which is conveniently
    // at 0,0,0 in eye space) to the point.
    pointE.normalize();

    // Now, figure out reflection vector, from formula:
    // R = P - 2 (N . N) pointE
    SbVec3f reflection = pointE - 2.0 * normalE.dot(normalE) * pointE;

    // Finally, compute s/t coordinates...
    reflection[2] += 1.0;
    float magnitude = reflection.length();

    // This is static so we can return a reference to it
    static SbVec4f result;
    result.setValue(reflection[0] / magnitude + 0.5,
		    reflection[1] / magnitude + 0.5,
		    0.0, 1.0);

    return result;
}
bool ObjMgrCommunicator::getObjAttributeVec4f(const string ObjID, const string LayerID, const string InfoID, SbVec4f& vec4f)
{
  omAttribute attr;
  if (getObjAttribute(ObjID,LayerID,InfoID, attr))
  {
    vector<string> VecSplit;
    kBasics::split(attr.getStringValue(),' ',4,&VecSplit);

    if (VecSplit.size()!=4)
    {
      kDebug::Debug("WrongSplitSize: " + kBasics::IntToString(VecSplit.size()),kDebug::DL_HIGH);
      return false;
    }

    vec4f.setValue(kBasics::StringToFloat(VecSplit[0]),kBasics::StringToFloat(VecSplit[1]),kBasics::StringToFloat(VecSplit[2]),kBasics::StringToFloat(VecSplit[3]));
    return true;
  }
  return false;
}
Example #3
0
void
SoCylinder::rayPick(SoRayPickAction *action)
//
////////////////////////////////////////////////////////////////////////
{
    // First see if the object is pickable
    if (! shouldRayPick(action))
	return;

    int			curParts =(parts.isIgnored() ? ALL : parts.getValue());
    SbLine		pickLine;
    float		radius, halfHeight;
    SbVec3f		enterPoint, exitPoint, normal;
    SbVec4f		texCoord;
    SoPickedPoint	*pp;
    SoCylinderDetail	*detail;
    SbBool		materialPerPart;
    int			numHits = 0;

    // Compute the picking ray in our current object space
    computeObjectSpaceRay(action);

    // Get size of this cylinder
    getSize(radius, halfHeight);

    // Construct an infinite cylinder to test sides for intersection
    SbCylinder	infiniteCyl;
    infiniteCyl.setRadius(radius);

    SoMaterialBindingElement::Binding mbe =
	SoMaterialBindingElement::get(action->getState());
    materialPerPart =
	(mbe == SoMaterialBindingElement::PER_PART_INDEXED ||
	 mbe == SoMaterialBindingElement::PER_PART);

    // See if the line intersects the cylinder
    if (HAS_PART(curParts, SIDES) &&
	infiniteCyl.intersect(action->getLine(), enterPoint, exitPoint)) {

	// See if the enter point is within the real cylinder and is
	// between the near and far clipping planes.
	if (enterPoint[1] <= halfHeight && enterPoint[1] >= -halfHeight) {

	    numHits++;

	    if (action->isBetweenPlanes(enterPoint) &&
		(pp = action->addIntersection(enterPoint)) != NULL) {

		// The normal at the point is the same as the point but
		// with a 0 y coordinate
		normal.setValue(enterPoint[0], 0.0, enterPoint[2]);
		normal.normalize();
		pp->setObjectNormal(normal);

		texCoord.setValue(atan2f(enterPoint[0], enterPoint[2])
				  * (1.0 / (2.0 * M_PI)) + 0.5,
				  (enterPoint[1] + halfHeight) /
				  (2.0 * halfHeight),
				  0.0, 1.0);
		pp->setObjectTextureCoords(texCoord);

		detail = new SoCylinderDetail();
		detail->setPart(SIDES);
		pp->setDetail(detail, this);
	    }
	}

	// Do same for exit point
	if (exitPoint[1] <= halfHeight && exitPoint[1] >= -halfHeight) {
	    numHits++;

	    if (action->isBetweenPlanes(exitPoint) &&
		(pp = action->addIntersection(exitPoint)) != NULL) {
		normal.setValue(exitPoint[0], 0.0, exitPoint[2]);
		normal.normalize();
		pp->setObjectNormal(normal);
		texCoord.setValue(atan2f(exitPoint[0], exitPoint[2])
				  * (1.0 / (2.0 * M_PI)) + 0.5,
				  (exitPoint[1] + halfHeight) /
				  (2.0 * halfHeight),
				  0.0, 1.0);
		pp->setObjectTextureCoords(texCoord);
		detail = new SoCylinderDetail();
		detail->setPart(SIDES);
		pp->setDetail(detail, this);
	    }
	}
    }

    // If we haven't hit the cylinder twice already, check for an
    // intersection with the top face
    if (numHits < 2 && HAS_PART(curParts, TOP)) {
	SbVec3f	norm(0.0, 1.0, 0.0);

	// Construct a plane containing the top face
	SbPlane	topFacePlane(norm, halfHeight);

	// See if the ray hits this plane
	if (topFacePlane.intersect(action->getLine(), enterPoint)) {

	    // See if the intersection is within the correct radius
	    // and is within the clipping planes
	    float distFromYAxisSquared = (enterPoint[0] * enterPoint[0] +
					  enterPoint[2] * enterPoint[2]);

	    if (distFromYAxisSquared <= radius * radius) {

		numHits++;

		if (action->isBetweenPlanes(enterPoint) &&
		    (pp = action->addIntersection(enterPoint)) != NULL) {
		    pp->setObjectNormal(norm);
		    texCoord.setValue(0.5 + enterPoint[0] / (2.0 * radius),
				      0.5 - enterPoint[2] / (2.0 * radius),
				      0.0, 1.0);
		    pp->setObjectTextureCoords(texCoord);
		    if (materialPerPart)
			pp->setMaterialIndex(1);
		    detail = new SoCylinderDetail();
		    detail->setPart(TOP);
		    pp->setDetail(detail, this);
		}
	    }
	}
    }

    // If we haven't hit the cylinder twice already, check for an
    // intersection with the bottom face
    if (numHits < 2 && HAS_PART(curParts, BOTTOM)) {
	SbVec3f	norm(0.0, -1.0, 0.0);

	// Construct a plane containing the bottom face
	SbPlane		bottomFacePlane(norm, halfHeight);

	// See if the ray hits this plane
	if (bottomFacePlane.intersect(action->getLine(), enterPoint)) {

	    // See if the intersection is within the correct radius
	    // and is within the clipping planes
	    float distFromYAxisSquared = (enterPoint[0] * enterPoint[0] +
					  enterPoint[2] * enterPoint[2]);

	    if (distFromYAxisSquared <= radius * radius &&
		action->isBetweenPlanes(enterPoint) &&
		(pp = action->addIntersection(enterPoint)) != NULL) {
		pp->setObjectNormal(norm);
		texCoord.setValue(0.5 + enterPoint[0] / (2.0 * radius),
				  0.5 + enterPoint[2] / (2.0 * radius),
				  0.0, 1.0);
		pp->setObjectTextureCoords(texCoord);
		if (materialPerPart)
		    pp->setMaterialIndex(2);
		detail = new SoCylinderDetail();
		detail->setPart(BOTTOM);
		pp->setDetail(detail, this);
	    }
	}
    }
}