Пример #1
0
void
_SoNurbsPickV4SurfaceMap::intersectTriangle()

//
////////////////////////////////////////////////////////////////////////
{
    SbVec3f             point;
    SbVec3f             barycentric;
    SbBool              onFrontSide;
    SoPickedPoint       *pp;

    if (!pickAction->intersect(SP[cacheIndices[0]].p,
                              SP[cacheIndices[1]].p,
                              SP[curPrimIndex].p,
                              point, barycentric, onFrontSide))
        return;

    pp = pickAction->addIntersection(point);
    if (pp != NULL) {

        SbVec3f         norm, n0, n1, n2;
        SbVec4f         texCoord;

        // Compute normal by interpolating vertex normals using
        // barycentric coordinates
	n0 = SP[0].norm;
	n1 = SP[1].norm;
	n2 = SP[2].norm;
	norm.setValue(barycentric, n0, n1, n2);
        norm.normalize();
        pp->setObjectNormal(norm);
        pp->setMaterialIndex(0);

        // Compute texture coordinates the same way
        texCoord[0] = barycentric[0] * TP[cacheIndices[0]][0] +
                      barycentric[1] * TP[cacheIndices[1]][0] +
                      barycentric[2] * TP[curPrimIndex][0];
        texCoord[1] = barycentric[0] * TP[cacheIndices[0]][1] +
                      barycentric[1] * TP[cacheIndices[1]][1] +
                      barycentric[2] * TP[curPrimIndex][1];
        texCoord[2] = 0.0;
        texCoord[3] = 1.0;
        pp->setObjectTextureCoords(texCoord);
    }
}
Пример #2
0
void SoRing::rayPick(SoRayPickAction * action)
{
  // Is it pickable ?
  if ( ! shouldRayPick(action) ) return;

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

  SoPickedPoint* pp;
  SbVec3f intersection;
  SbPlane XY(SbVec3f(0,0,1),0);
  if ( XY.intersect(action->getLine(), intersection) )
  {
    float x, y, z;
    intersection.getValue(x, y, z);

    // back to the case of a disk centered at (0,0)
    float Xc, Yc;
    center.getValue().getValue(Xc,Yc);
    x -= Xc;
    y -= Yc;

    // within radius ?
    if ( sqrt(x*x+y*y+z*z) > outerRadius.getValue() ) return;
    if ( sqrt(x*x+y*y+z*z) < innerRadius.getValue() ) return;

    // within angular section ?
    float theta = sweepAngle.getValue();
    float angle = atan2(y,x);
    if ( angle < 0. ) angle += 2*M_PI;
    if ( theta != 360 && 
         angle*180.F/M_PI > theta ) return;

    if ( action->isBetweenPlanes(intersection) &&
         (pp = action->addIntersection(intersection)) != NULL )
    {
      pp->setObjectNormal(normal);
      pp->setObjectTextureCoords(SbVec4f(0.5f*(1+cos(angle)),
                                         0.5f*(1+sin(angle)), 0, 1));
    }
  }

}
Пример #3
0
void
_SoNurbsPickV4CurveMap::intersectLine()

//
////////////////////////////////////////////////////////////////////////
{
    SbVec3f             point;
    SoPickedPoint       *pp;

    if (!pickAction->intersect(CP[0], CP[1], point))
        return;

    pp = pickAction->addIntersection(point);
    if (pp != NULL) {

        SbVec3f         norm;
        SbVec4f         texCoord;
        float           ratioFromV1;

        // Compute normal as vector pointing back along the pick ray.
	norm = -pickAction->getLine().getDirection();
        norm.normalize();
        pp->setObjectNormal(norm);
        pp->setMaterialIndex(0);

        // Compute interpolated texture coordinate 
        ratioFromV1 = ((point - CP[0]).length() /
                       (CP[1] - CP[0]).length());
        texCoord[0] = (TP[0][0] * (1.0 - ratioFromV1) +
                    TP[1][0] * ratioFromV1);
        texCoord[1] = (TP[0][1] * (1.0 - ratioFromV1) +
                    TP[1][1] * ratioFromV1);
        texCoord[2] = 0.0;
        texCoord[3] = 1.0;
        pp->setObjectTextureCoords(texCoord);
    }
}
Пример #4
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);
	    }
	}
    }
}