/*! \param upVec
 *  \param dir
 *  \return orientation
 */
SbRotation kCamera::calcOrientation(const SbVec3f upVec, const SbVec3f dir)
{
	// from comp.graphics.api.inventor ... "Setting SoCamera orientation"
	SbVec3f z = -dir;
	SbVec3f y = upVec;
	z.normalize();
	y.normalize();
	SbVec3f x = y.cross(z);

	// recompute y to create a valid coordinate system
	y	= z.cross(x);

	// create a rotation matrix
	SbMatrix rot = SbMatrix::identity();
	rot[0][0] = x[0];
	rot[0][1] = x[1];
	rot[0][2] = x[2];

	rot[1][0] = y[0];
	rot[1][1] = y[1];
	rot[1][2] = y[2];

	rot[2][0] = z[0];
	rot[2][1] = z[1];
	rot[2][2] = z[2];

	// convert matrix into rotation
	return SbRotation(rot);
}
/*! Rotates the upVector by the current upVector angle
 * \param lookDir
 * \param plump
 */
SbVec3f kCamera::calcUpVector(const SbVec3f lookDir, const SbVec3f plump)
{
	SbVec3f upVec;
	upVec = calcPerfectUpVector(lookDir, plump);
	upVec.normalize();
	rotateVector(upVec,lookDir,currentUpVecAngle);
	upVec.normalize();
	return upVec;
}
Beispiel #3
0
/*!
  Clip polygon against \a plane. This might change the number of
  vertices in the polygon. For each time a new vertex is created, the
  callback supplied in the constructor (if != NULL) is called with the
  line being clipped and the new vertex calculated. The callback
  should return a new void pointer to be stored by the clipper.
*/
void
SbClip::clip(const SbPlane & plane)
{
  int n = this->array[this->curr].getLength();

  if (n == 0) return;

  // create loop
  SbClipData dummy = this->array[this->curr][0];
  this->array[this->curr].append(dummy);

  const SbVec3f & planeN = plane.getNormal();

  for (int i = 0; i < n; i++) {
    SbVec3f v0, v1;
    void * data0, *data1;
    this->array[this->curr][i].get(v0, data0);
    this->array[this->curr][i+1].get(v1, data1);

    float d0 = plane.getDistance(v0);
    float d1 = plane.getDistance(v1);

    if (d0 >= 0.0f && d1 < 0.0f) { // exit plane
      SbVec3f dir = v1-v0;
      // we know that v0 != v1 since we got here
      (void) dir.normalize();
      float dot = dir.dot(planeN);
      SbVec3f newvertex = v0 - dir * (d0/dot);
      void * newdata = NULL;
      if (this->callback) {
        newdata = this->callback(v0, data0, v1, data1, newvertex, this->cbdata);
      }
      outputVertex(newvertex, newdata);
    }
    else if (d0 < 0.0f && d1 >= 0.0f) { // enter plane
      SbVec3f dir = v1-v0;
      // we know that v0 != v1 since we got here
      (void) dir.normalize();
      float dot = dir.dot(planeN);
      SbVec3f newvertex = v0 - dir * (d0/dot);
      void * newdata = NULL;
      if (this->callback) {
        newdata = this->callback(v0, data0, v1, data1, newvertex, this->cbdata);
      }
      outputVertex(newvertex, newdata);
      outputVertex(v1, data1);
    }
    else if (d0 >= 0.0f && d1 >= 0.0f) { // in plane
      outputVertex(v1, data1);
    }
  }
  this->array[this->curr].truncate(0);
  this->curr ^= 1;
}
Beispiel #4
0
float XipGeomUtils::angleBetweenVectors(SbVec3f vectorA, SbVec3f vectorB)
{
    vectorA.normalize();
    vectorB.normalize();

    float dotProduct = vectorA.dot(vectorB);
    if (dotProduct > 1.f) dotProduct = 1.f;
    if (dotProduct < -1.f) dotProduct = -1.f;

    float angle = acos(dotProduct);

    return angle;
}
/*! Returns the dot-product (1 = parallel, 0 = right angle, -1 = opposite)
 *  \param lookDir
 *  \param upVec
 *  \return dotproduct ( +1 = parallel, 0 = orthogonal, -1 = 180 deg )
 */
float kCamera::getUpVecAngleDir(const SbVec3f lookDir, const SbVec3f upVec)
{
	SbVec3f perfectUpVec = calcPerfectUpVector(lookDir,NormPlump);
	perfectUpVec.normalize();

	SbVec3f crossproduct;
	crossproduct = upVec.cross(perfectUpVec);
	crossproduct.normalize();

	float dotproduct = crossproduct.dot(lookDir);

	//SoDebugError::postInfo("_____________________     MASTER-WINKEL: ",kBasics::FloatToString(angleDiff).c_str());

	return dotproduct;
}
/*! \param[in,out] vect vector to rotate
 *  \param axis
 *  \param angle
 */
void kCamera::rotateVector(SbVec3f& vect, const SbVec3f axis, const double angle)
{
	SbRotation vecRotation;
	vecRotation.setValue(axis,angle);
	vecRotation.multVec(vect,vect);
	vect.normalize();
}
void RDragger::drag()
{
    projector.setViewVolume(this->getViewVolume());
    projector.setWorkingSpace(this->getLocalToWorldMatrix());

    SbVec3f hitPoint;
    if (!projector.tryProject(getNormalizedLocaterPosition(), 0.0, hitPoint))
        return;
    hitPoint.normalize();

    SbVec3f startingPoint = getLocalStartingPoint();
    startingPoint.normalize();

    SbRotation localRotation(startingPoint, hitPoint);
    //getting some slop from this. grab vector and put it absolute.
    SbVec3f tempVec;
    float tempRadians;
    localRotation.getValue(tempVec, tempRadians);
    tempVec[0] = 0.0;
    tempVec[1] = 0.0;
    tempVec.normalize();
    if (tempVec[2] < 0.0)
    {
        tempRadians *= -1.0;
        tempVec.negate();
    }
    int incrementCount = roundIncrement(tempRadians);
    rotationIncrementCount.setValue(incrementCount);
    localRotation = SbRotation(tempVec, incrementCount * static_cast<float>(rotationIncrement.getValue()));

    //same problem as described in tDragger::drag.
    if (localRotation.equals(SbRotation(SbVec3f(0.0, 0.0, 1.0), 0.0), 0.00001f))
    {
        setMotionMatrix(getStartMotionMatrix());
        this->valueChanged();
    }
    else
        setMotionMatrix(appendRotation(getStartMotionMatrix(), localRotation, SbVec3f(0.0, 0.0, 0.0)));
    
    Base::Quantity quantity(
      static_cast<double>(rotationIncrementCount.getValue())  * (180.0 / M_PI) *
      rotationIncrement.getValue(), Base::Unit::Angle);
    
    QString message(QObject::tr("Rotation: "));
    message += quantity.getUserString();
    getMainWindow()->showMessage(message, 3000);
}
Beispiel #8
0
SbBool XipGeomUtils::mprIntersect(const SbMatrix & m1, const SbMatrix & m2, SbVec3f line[2], float viewportAspectRatio)
{
    SbLine objLine, worldLine;
    SbVec3f pt1, pt2;
    int pc = 0;
    SbPlane p1 = planeFromMatrix(m1);
    SbPlane p2 = planeFromMatrix(m2);

    float width = viewportAspectRatio < 1.f ? 1.f : viewportAspectRatio;
    float height = viewportAspectRatio > 1.f ? 1.f : 1.f / viewportAspectRatio;

    const SbLine frameLines[4] =
    {
        SbLine(SbVec3f(-width, -height, 0), SbVec3f(-width,  height, 0)),
        SbLine(SbVec3f(-width, -height, 0), SbVec3f( width, -height, 0)),
        SbLine(SbVec3f( width,  height, 0), SbVec3f(-width,  height, 0)),
        SbLine(SbVec3f( width,  height, 0), SbVec3f( width, -height, 0))
    };

    // First, get intersecting line of the two planes.
    if (!planeIntersect(p1, p2, worldLine)) return FALSE;


    // Convert intersection line from world into object space before
    // testing against frame lines, which are also in object space.
    m1.inverse().multLineMatrix(worldLine, objLine);

    SbVec3f normal = objLine.getDirection();
    normal.normalize();

    objLine = SbLine(objLine.getPosition(), objLine.getPosition() + normal);

    // Intersect with the 4 lines of frame.
    for (int i = 0; i < 4; i++)
    {
        //if (objLine.getClosestPoints(frameLines[i], pt1, pt2))
        //{
        //	// Valid intersection point. Convert back to world space.
        //	m1.multVecMatrix(pt1, pt2);
        //	line[pc++] = pt2;
        //	if (pc > 1) break;
        //}

        if ((1.0f - abs(objLine.getDirection().dot(frameLines[i].getDirection()))) > 0.1f)
        {
            if (objLine.getClosestPoints(frameLines[i], pt1, pt2))
            {
                // Valid intersection point. Convert back to world space.
                m1.multVecMatrix(pt1, pt2);
                line[pc++] = pt2;
                if (pc > 1) break;
            }
        }

    }

    return (pc == 2);
}
Beispiel #9
0
SbRotation
SoBillboard::calculateRotation(SoState *state)
{
    SbRotation rot;
#ifdef INVENTORRENDERER
    const SbViewVolume &viewVolume = SoViewVolumeElement::get(state);

    if (SbVec3f(0.0f, 0.0f, 0.0f) == axis.getValue())
    {
        rot = viewVolume.getAlignRotation();
    }
#else
    const SbMatrix &mm = SoModelMatrixElement::get(state);
    SbMatrix imm = mm.inverse();

    SbVec3f toviewer;
    SbVec3f cameray(0.0f, 1.0f, 0.0f);
    const SbViewVolume &vv = SoViewVolumeElement::get(state);

    toviewer = -vv.getProjectionDirection();
    imm.multDirMatrix(toviewer, toviewer);

    (void)toviewer.normalize();

    SbVec3f rotaxis = this->axis.getValue();

    if (rotaxis == SbVec3f(0.0f, 0.0f, 0.0f))
    {
        // 1. Compute the billboard-to-viewer vector.
        // 2. Rotate the Z-axis of the billboard to be collinear with the
        //    billboard-to-viewer vector and pointing towards the viewer's position.
        // 3. Rotate the Y-axis of the billboard to be parallel and oriented in the
        //    same direction as the Y-axis of the viewer.
        rot.setValue(SbVec3f(0.f, 0.0f, 1.0f), toviewer);
        SbVec3f viewup = vv.getViewUp();
        imm.multDirMatrix(viewup, viewup);

        SbVec3f yaxis(0.0f, 1.0f, 0.0f);
        rot.multVec(yaxis, yaxis);
        SbRotation rot2(yaxis, viewup);

        SbVec3f axis;
        float angle;
        rot.getValue(axis, angle);
        rot2.getValue(axis, angle);
        rot = rot * rot2;
        //SoModelMatrixElement::rotateBy(state, (SoNode*) this, rot);
    }
#endif
    else
    {
        fprintf(stderr, "SoBillboard: axis != (0.0, 0.0, 0.0) not implemented\n");
    }

    return rot;
}
Beispiel #10
0
/*! \param orientation
 *  \param[out] upVec
 *  \param[out] lookDir
 *  \param[out] upVecAngle
 */
void kCamera::splitOrientation(const SbRotation orientation, SbVec3f& upVec, SbVec3f& lookDir, double& upVecAngle)
{
	// Extrahieren der lookDir aus der aktuellen orientation
	lookDir.setValue(0.0, 0.0, -1.0); //! init to default lookat direction (DIRECTION!)
    orientation.multVec(lookDir, lookDir);
	lookDir.normalize();

	// Extrahieren des upVectors aus der aktuellen orientation
	upVec.setValue(0.0, 1.0, 0.0); // init to default up vector direction
	orientation.multVec(upVec, upVec);
	upVec.normalize();

	// Ermitteln des perfekten upVectors (upVector ohne zusätzliche Drehung um die Sichtachse)
	SbVec3f perfectUpVec;
	if (fabs(lookDir.dot(NormPlump))>(1.0-epsilon)) //! wenn lookDir und perfectUpVec parallel, dann gleich setzen (Vermeidung von Berechnungsfehlern
		perfectUpVec = upVec;
	else
		perfectUpVec = calcPerfectUpVector(lookDir,NormPlump);

	perfectUpVec.normalize();

	// a dot b = |a|*|b|+cos(a,b)
	double tempDot = upVec.dot(perfectUpVec); //! Es gab Fälle, in denen war .dot minimal größer als 1.0 -> acos = 1.#IND
	if (tempDot>1.0) tempDot = 1.0;	if (tempDot<-1.0) tempDot = -1.0;
	upVecAngle = acos(tempDot); //! 1.0 = Produkt der beiden Längen ... sind aber normalisiert


	// Ermittlung der Drehrichtung des Winkels und ggf. Erhöhung um 180Grad
	// Im R3 gibt es zuerst einmal keine positiven und negativen drehwinkel.
	// Erst wenn man die Ebene, die die beiden Vektoren definieren, orientiert, geht das.
	// Man kann also festlegen, dass der Winkel positiv ist, wenn Hesse-Normalenvektor der Ebene und Kreuzprodukt in dieselbe Richtung zeigen.
	if (getUpVecAngleDir(lookDir,upVec)>epsilon && (upVecAngle<(kBasics::PI-epsilon)))
		upVecAngle = kBasics::PI + (kBasics::PI - upVecAngle);

	// Vermeidung von Winkeln > 2*PI
	if (upVecAngle>(2*(kBasics::PI-epsilon)))
		upVecAngle = upVecAngle - 2*kBasics::PI;

	// Sehr kleine Winkel werden auf 0.0 gesetzt
	if (fabs(upVecAngle)<epsilon)
		upVecAngle = 0.0; //! sonst kommt es zu Dingen wie 1.#IND
}
Beispiel #11
0
// this function calculates the normal using the local coordinates;
SbVec3f Sphere::calculate_normal(SbVec3f *starting_position, SbVec3f *ray_direction, float t) {
    SbVec3f normal;
    SbVec3f sp = *starting_position ;
    SbVec3f rd = *ray_direction;
    SbVec3f origin(0.0,0.0,0.0);

    sp = multiply_with_inverse(sp);
    rd = multiply_with_inverse(rd);
    origin = multiply_with_inverse(origin);
    rd = rd - origin;
    rd.normalize();

    normal = (sp + (t *(rd))); //ntc
    //normal += nn;
    //normal = multiply_with_transformation(normal) - multiply_with_transformation(origin);
    //normal.normalize();
    // normal = offset_normal(normal, 0.31f);
    normal.normalize();
    return normal;
}
void ViewProviderMeasureDistance::updateData(const App::Property* prop)
{
    if (prop->getTypeId() == App::PropertyVector::getClassTypeId() ||
        prop == &Mirror || prop == &DistFactor) {
        if (strcmp(prop->getName(),"P1") == 0) {
            Base::Vector3d v = static_cast<const App::PropertyVector*>(prop)->getValue();
            pCoords->point.set1Value(0, SbVec3f(v.x,v.y,v.z));
        }
        else if (strcmp(prop->getName(),"P2") == 0) {
            Base::Vector3d v = static_cast<const App::PropertyVector*>(prop)->getValue();
            pCoords->point.set1Value(1, SbVec3f(v.x,v.y,v.z));
        }

        SbVec3f pt1 = pCoords->point[0];
        SbVec3f pt2 = pCoords->point[1];
        SbVec3f dif = pt1-pt2;

        float length = fabs(dif.length())*DistFactor.getValue();
        if (Mirror.getValue())
            length = -length;


        if (dif.sqrLength() < 10.0e-6f) {
            pCoords->point.set1Value(2, pt1+SbVec3f(0.0f,0.0f,length));
            pCoords->point.set1Value(3, pt2+SbVec3f(0.0f,0.0f,length));
        }
        else {
            SbVec3f dir = dif.cross(SbVec3f(1.0f,0.0f,0.0f));
            if (dir.sqrLength() < 10.0e-6f)
                dir = dif.cross(SbVec3f(0.0f,1.0f,0.0f));
            if (dir.sqrLength() < 10.0e-6f)
                dir = dif.cross(SbVec3f(0.0f,0.0f,1.0f));
            dir.normalize();
            if (dir.dot(SbVec3f(0.0f,0.0f,1.0f)) < 0.0f)
                length = -length;
            pCoords->point.set1Value(2, pt1 + length*dir);
            pCoords->point.set1Value(3, pt2 + length*dir);
        }

        SbVec3f pos = (pCoords->point[2]+pCoords->point[3])/2.0f;
        pTranslation->translation.setValue(pos);

        std::stringstream s;
        s.precision(3);
        s.setf(std::ios::fixed | std::ios::showpoint);
        s << dif.length();
        pLabel->string.setValue(s.str().c_str());
    }

    ViewProviderDocumentObject::updateData(prop);
}
Beispiel #13
0
/*! \param angle */
void kCamera::rotateCam(double angle)
{
	// UpVec rotieren - bisher nur um die Sichtachse, also kein Kippen gegenüber der Sichtrichtung
	// Bei anderen Rotationen müssten dann sowohl UpVec wie auch lookDir gedreht werden

	currentUpVecAngle = currentUpVecAngle + angle;

	SbVec3f perfectUpVec = calcPerfectUpVector(currentLookDir,NormPlump);
	perfectUpVec.normalize();
	rotateVector(perfectUpVec,currentLookDir, currentUpVecAngle);
	currentUpVec = perfectUpVec;

	currentOrientation = calcOrientation(currentUpVec,currentLookDir); //! Berechnet neue orientation
	//writeOrientation(currentOrientation); //! Schreibt orientation in ObjMgr
}
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;
}
Beispiel #15
0
// the below two function use the local coordinates to determine the point of intersection
SbVec3f Cone::point_of_intersection(SbVec3f *starting_position, SbVec3f *ray_direction, float T){
	double a, b, c,d;
	SbVec3f sp = *starting_position ;
	SbVec3f rd = *ray_direction;
	SbVec3f origin(0.0, 0.0, 0.0);
	SbVec3f poi;

	sp = multiply_with_inverse(sp);
	rd = multiply_with_inverse(rd);
	origin = multiply_with_inverse(origin);
    rd = rd - origin;

	rd.normalize();
	poi= sp + (T * (rd));
	poi = this->multiply_with_transformation(poi); //ntc
	return poi;
}
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seekToPoint(const SbVec3f& scenepos)
{
    SbVec3f hitpoint(scenepos);

    m_camerastartposition = getSoRenderManager()->getCamera()->position.getValue();
    m_camerastartorient = getSoRenderManager()->getCamera()->orientation.getValue();

    // move point to the camera coordinate system, consider
    // transformations before camera in the scene graph
    SbMatrix cameramatrix, camerainverse;
    getCameraCoordinateSystem(getSoRenderManager()->getCamera(),
                              getSceneGraph(),
                              cameramatrix,
                              camerainverse);
    camerainverse.multVecMatrix(hitpoint, hitpoint);

    float fd = m_seekdistance;

    if(!m_seekdistanceabs)
        fd *= (hitpoint - getSoRenderManager()->getCamera()->position.getValue()).length()/100.0f;

    getSoRenderManager()->getCamera()->focalDistance = fd;

    SbVec3f dir = hitpoint - m_camerastartposition;
    dir.normalize();

    // find a rotation that rotates current camera direction into new
    // camera direction.
    SbVec3f olddir;
    getSoRenderManager()->getCamera()->orientation.getValue().multVec(SbVec3f(0, 0, -1), olddir);
    SbRotation diffrot(olddir, dir);
    m_cameraendposition = hitpoint - fd * dir;
    m_cameraendorient = getSoRenderManager()->getCamera()->orientation.getValue() * diffrot;

    if(m_seeksensor->isScheduled()) {
        m_seeksensor->unschedule();
        interactiveCountDec();
    }

    m_seeksensor->setBaseTime(SbTime::getTimeOfDay());
    m_seeksensor->schedule();
    interactiveCountInc();
}
void RDragger::dragStart()
{
    SoSwitch *sw;
    sw = SO_GET_ANY_PART(this, "rotatorSwitch", SoSwitch);
    SoInteractionKit::setSwitchValue(sw, 1);

    projector.setViewVolume(this->getViewVolume());
    projector.setWorkingSpace(this->getLocalToWorldMatrix());
    projector.setPlane(SbPlane(SbVec3f(0.0, 0.0, 1.0), 0.0));

    SbVec3f hitPoint;
    if (!projector.tryProject(getNormalizedLocaterPosition(), 0.0, hitPoint))
        return;
    hitPoint.normalize();

    SbMatrix localToWorld = getLocalToWorldMatrix();
    localToWorld.multVecMatrix(hitPoint, hitPoint);
    setStartingPoint((hitPoint));

    rotationIncrementCount.setValue(0);
}
Beispiel #18
0
void Command::adjustCameraPosition()
{
    Gui::Document* doc = Gui::Application::Instance->activeDocument();
    if (doc) {
        Gui::View3DInventor* view = static_cast<Gui::View3DInventor*>(doc->getActiveView());
        Gui::View3DInventorViewer* viewer = view->getViewer();
        SoCamera* camera = viewer->getSoRenderManager()->getCamera();
        if (!camera || !camera->isOfType(SoOrthographicCamera::getClassTypeId()))
            return;

        // get scene bounding box
        SoGetBoundingBoxAction action(viewer->getSoRenderManager()->getViewportRegion());
        action.apply(viewer->getSceneGraph());
        SbBox3f box = action.getBoundingBox();
        if (box.isEmpty()) return;

        // get cirumscribing sphere and check if camera is inside
        SbVec3f cam_pos = camera->position.getValue();
        SbVec3f box_cnt = box.getCenter();
        SbSphere bs;
        bs.circumscribe(box);
        float radius = bs.getRadius();
        float distance_to_midpoint = (box_cnt-cam_pos).length();
        if (radius >= distance_to_midpoint) {
            // Move the camera to the edge of the bounding sphere, while still
            // pointing at the scene.
            SbVec3f direction = cam_pos - box_cnt;
            (void) direction.normalize(); // we know this is not a null vector
            camera->position.setValue(box_cnt + direction * radius);

            // New distance to mid point
            distance_to_midpoint =
                (camera->position.getValue() - box.getCenter()).length();
            camera->nearDistance = distance_to_midpoint - radius;
            camera->farDistance = distance_to_midpoint + radius;
            camera->focalDistance = distance_to_midpoint;
        }
    }
}
Beispiel #19
0
void ManipWidget::orientToCamera(void)
{
	assert(isActive); // why would we need to orient inactive manipwidget?

	SbVec3f cameraPos = viewer->getCamera()->position.getValue();
	SbRotation cameraRot = viewer->getCamera()->orientation.getValue();

	SbVec3f widgetPos = applyMatrix(
							localToWorldMatrix(),
							SbVec3f(0, 0, 0));
	SbVec3f d = cameraPos - widgetPos;
	d.normalize();

	// compensate for rotation
	SbVec3f trans;
	SbRotation rot, scaleOrient;
	SbVec3f scale;
	localToWorldMatrix().inverse().getTransform(trans, rot, scale, scaleOrient);
	rot.multVec(d, d);

	cameraUpdatedVirtual(d, cameraRot * rot);
}
Beispiel #20
0
void SoWidgetShape::generatePrimitives(SoAction *action)
{
    if (this->image.isNull()) return;

    SoState *state = action->getState();
    state->push();

    SbVec2s size;
    SbVec3f v0, v1, v2, v3;
    this->getQuad(action->getState(), v0, v1, v2, v3);

    SbVec3f n = (v1-v0).cross(v2-v0);
    n.normalize();

    this->beginShape(action, SoShape::QUADS);
    SoPrimitiveVertex vertex;
    vertex.setNormal(n);

    vertex.setTextureCoords(SbVec2f(0,0));
    vertex.setPoint(v0);
    this->shapeVertex(&vertex);

    vertex.setTextureCoords(SbVec2f(1,0));
    vertex.setPoint(v1);
    this->shapeVertex(&vertex);

    vertex.setTextureCoords(SbVec2f(1,1));
    vertex.setPoint(v2);
    this->shapeVertex(&vertex);

    vertex.setTextureCoords(SbVec2f(0,1));
    vertex.setPoint(v3);
    this->shapeVertex(&vertex);

    this->endShape();

    state->pop();
}
Beispiel #21
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);
    }
}
void SoSpring::applyForce()
{
    // Calculate the forces according to Hooke's Law
    // k * (DISTij-LENij) * Vij
	SbVec3f resultingForces;
 	SbVec3f deltaVector = endpos.getValue()-startpos.getValue();
    float elongation; 
	
	SbVec3f acc1 = acc.getValue();
	SbVec3f vel1 = vel.getValue();

	elongation = deltaVector.length();
	deltaVector.normalize();
	resultingForces=stiffness.getValue()*elongation*deltaVector;

	// debug 
	// printf("a1%f,a2%f,a3%f, v1%f,v2%f,v3%f,p1%f,p2%f,p3%f \n", acc1[0],acc1[1],acc1[2],vel1[0],vel1[1],vel1[2],startpos.getValue()[0],startpos.getValue()[1],startpos.getValue()[2] );
	acc1 = resultingForces*(1.0f/mass.getValue());
 	vel1 = vel1 + (acc1*timeStep.getValue());
	vel1  *= damp.getValue();

	vel.setValue(vel1);
	acc.setValue(acc1);

	if ( (vel1.length()<treshold.getValue())& (acc1.length()<treshold.getValue() ) )
		{
		// debug
		//printf("INFO: treasold reached!! \n");
		
		timer->unschedule();
		}
	else // update
		{
	startpos.setValue(startpos.getValue()+ vel1*timeStep.getValue()) ;
		}
}
Beispiel #23
0
int XipGeomUtils::orthoOrientations(const SbMatrix &orientation, SbMatrix &orthoF, SbMatrix &orthoL, SbMatrix &orthoA)
{
    int i;
    SbMatrix defOrient = orientation;

    SbVec3f defNormal = SbVec3f(defOrient[2][0], defOrient[2][1], defOrient[2][2]);
    defNormal.normalize();

    SbVec3f defUp = SbVec3f(defOrient[1][0], defOrient[1][1], defOrient[1][2]);
    defUp.normalize();

    // find best match of the default orientation to one of the standard orientations (F, L, A)
    float angle[6] =
    {
        XipGeomUtils::angleBetweenVectors(defNormal, SbVec3f(0, 0, -1)),	// F
        XipGeomUtils::angleBetweenVectors(defNormal, SbVec3f(1, 0, 0)),		// L
        XipGeomUtils::angleBetweenVectors(defNormal, SbVec3f(0, -1, 0)),	// A
        XipGeomUtils::angleBetweenVectors(defNormal, SbVec3f(0, 0, 1)),		// H
        XipGeomUtils::angleBetweenVectors(defNormal, SbVec3f(-1, 0, 0)),	// R
        XipGeomUtils::angleBetweenVectors(defNormal, SbVec3f(0, 1, 0))		// P
    };

    int which = 0;
    for (i = 0; i < 6; i++)
    {
        if (angle[i] < angle[which])
            which = i;
    }

    SbMatrix rot1, rot2;

    if (which > 2)
    {
        // H, R or P: flip orientation around to show F, L or A
        which -= 3;
        defNormal *= -1;
        rot1.setRotate(SbRotation(defUp, static_cast<float>(M_PI)));
        defOrient = rot1 * defOrient;
    }

    switch (which)
    {
    case 0:	// F
    {
        float a = XipGeomUtils::angleBetweenVectors(SbVec3f(defUp[0], defUp[1], 0), SbVec3f(0, -1, 0));
        int numRots = static_cast<int>((a / (0.5f * M_PI)) + 0.5f);
        a = numRots * (0.5f * static_cast<float>(M_PI));
        rot1.setRotate(SbRotation(defNormal, -a));
        defOrient = rot1 * defOrient;

        orthoF = defOrient;
        rot1.setRotate(SbRotation(SbVec3f(1, 0, 0), static_cast<float>(-M_PI) / 2.f));
        orthoA = rot1 * defOrient;
        rot2.setRotate(SbRotation(SbVec3f(0, 1, 0), static_cast<float>(M_PI) / 2.f));
        orthoL = rot2 * rot1 * defOrient;
    }
    break;
    case 1:	// L
    {
        float a = XipGeomUtils::angleBetweenVectors(SbVec3f(0, defUp[1], defUp[2]), SbVec3f(0, 0, 1));
        int numRots = static_cast<int>((a / (0.5f * M_PI)) + 0.5f);
        a = numRots * (0.5f * static_cast<float>(M_PI));
        rot1.setRotate(SbRotation(defNormal, -a));
        defOrient = rot1 * defOrient;

        orthoL = defOrient;
        rot2.setRotate(SbRotation(SbVec3f(0, 1, 0), static_cast<float>(-M_PI) / 2.f));
        orthoA = rot2 * defOrient;
        rot1.setRotate(SbRotation(SbVec3f(0, 1, 0), static_cast<float>(-M_PI) / 2.f));
        rot2.setRotate(SbRotation(SbVec3f(1, 0, 0), static_cast<float>(M_PI) / 2.f));
        orthoF = rot2 * rot1 * defOrient;
    }
    break;
    case 2:	// A
    {
        float a = XipGeomUtils::angleBetweenVectors(SbVec3f(defUp[0], 0, defUp[2]), SbVec3f(0, 0, 1));
        int numRots = static_cast<int>((a / (0.5f * M_PI)) + 0.5f);
        a = numRots * (0.5f * static_cast<float>(M_PI));
        rot1.setRotate(SbRotation(defNormal, -a));
        defOrient = rot1 * defOrient;

        orthoA = defOrient;
        rot1.setRotate(SbRotation(SbVec3f(1, 0, 0), static_cast<float>(M_PI) / 2.f));
        orthoF = rot1 * defOrient;
        rot1.setRotate(SbRotation(SbVec3f(0, 1, 0), static_cast<float>(M_PI) / 2.f));
        orthoL = rot1 * defOrient;
    }
    break;
    }

    return which;
}
Beispiel #24
0
/*!
  Generates one normal per triangle strips (avarages all triangle normals).
*/
void
SoNormalCache::generatePerStrip(const SbVec3f * const coords,
                                const unsigned int numcoords,
                                const int32_t * cind,
                                const int nv,
                                const SbBool ccw)
{
#if NORMALCACHE_DEBUG && COIN_DEBUG
  SoDebugError::postInfo("SoNormalCache::generatePerStrip", "generating normals");
#endif

  this->clearGenerator();
  PRIVATE(this)->indices.truncate(0);
  PRIVATE(this)->normalArray.truncate(0, TRUE);

  const int32_t * cstart = cind;
  const int32_t * endptr = cind + nv;

  const SbVec3f * c0, * c1, * c2;
  SbVec3f n;

  SbBool flip = ccw;

  const int maxcoordidx = numcoords - 1;

  while (cind + 2 < endptr) {
    if (cind[0] < 0 || cind[1] < 0 || cind[2] < 0 ||
        cind[0] > maxcoordidx || cind[1] > maxcoordidx || cind[2] > maxcoordidx) {
#if COIN_DEBUG
      SoDebugError::postWarning("SoNormalCache::generatePerStrip", "Erroneous "
                                "coordinate index detected (offset: %d, [%d %d %d]). Should be "
                                "within [0, %d].",
                                cind - cstart, *(cind), *(cind+1), *(cind+2), maxcoordidx);
#endif // COIN_DEBUG
      // Insert dummy normal for robustness
      SbVec3f dummynormal;
      dummynormal.setValue(0.0f, 0.0f, 0.0f);
      PRIVATE(this)->normalArray.append(dummynormal);

      // Skip to next possibly valid index
      if (cind[0] < 0 || cind[0] > maxcoordidx) {
        cind += 1;
      }
      else if (cind[1] < 0 || cind[1] > maxcoordidx) {
        cind += 2;
      }
      else if (cind + 3 < endptr && (cind[2] < 0 || cind[2] > maxcoordidx)) {
        cind += 3;
      }
      else {
        cind += 3; // For robustness check after while loop
        break;
      }

      continue;
    }
    
    flip = ccw;
    c0 = &coords[*cind++];
    c1 = &coords[*cind++];
    c2 = &coords[*cind++];

    if (!flip)
      n = (*c0 - *c1).cross(*c2 - *c1);
    else
      n = (*c2 - *c1).cross(*c0 - *c1);

    int idx = cind < endptr ? *cind++ : -1;
    while (idx >= 0 && idx <= maxcoordidx) {
      c0 = c1;
      c1 = c2;
      c2 = &coords[idx];
      flip = !flip;
      if (!flip)
        n += (*c0 - *c1).cross(*c2 - *c1);
      else
        n += (*c2 - *c1).cross(*c0 - *c1);
      idx = cind < endptr ? *cind++ : -1;
    }

#if COIN_DEBUG
    if (idx > maxcoordidx) {
      static uint32_t normgenerrors_strip = 0;
      if (normgenerrors_strip < 1) {
        SoDebugError::postWarning("SoNormalCache::generatePerStrip",
                                  "Erroneous polygon specification in model. "
                                  "Index out of bounds: %d. Max index: %d. "
                                  "(this warning will be printed only once, "
                                  "but there might be more errors).", 
                                  idx, maxcoordidx);
      }
      normgenerrors_strip++;
    }
#endif // COIN_DEBUG

    if ((n.normalize() == 0.0f) && coin_debug_extra()) {
      static uint32_t normgenerrors_strip = 0;
      if (normgenerrors_strip < 1) {
        SoDebugError::postWarning("SoNormalCache::generatePerStrip",
                                  "Erroneous polygon specification in model.  "
                                  "Unable to generate non-zero normal. Using "
                                  "dummy normal. "
                                  "(this warning will be printed only once, "
                                  "but there might be more errors).");
      }
      normgenerrors_strip++;
    }
    
    PRIVATE(this)->normalArray.append(n);
  }

  if (endptr - cind > 0) {
#if COIN_DEBUG
    SoDebugError::postWarning("SoNormalCache::generatePerStrip", "Strip did "
                              "not end with a valid polygon. Too few points");
#endif // COIN_DEBUG
    SbVec3f dummynormal;
    dummynormal.setValue(0.0, 0.0, 0.0);
    PRIVATE(this)->normalArray.append(dummynormal);
  }

  if (PRIVATE(this)->normalArray.getLength()) {
    PRIVATE(this)->normalData.normals = PRIVATE(this)->normalArray.getArrayPtr();
    PRIVATE(this)->numNormals = PRIVATE(this)->normalArray.getLength();
  }

#if NORMALCACHE_DEBUG && COIN_DEBUG
  SoDebugError::postInfo("SoNormalCache::generatePerStrip",
                         "generated normals per strip: %p %d\n",
                         PRIVATE(this)->normalData.normals, PRIVATE(this)->numNormals);
#endif

}
Beispiel #25
0
/*!
  Generates per face normals for quad data.
*/
void
SoNormalCache::generatePerFaceQuad(const SbVec3f * const coords,
                                   const unsigned int numcoords,
                                   const int vPerRow,
                                   const int vPerColumn,
                                   const SbBool ccw)
{
#if NORMALCACHE_DEBUG && COIN_DEBUG
  SoDebugError::postInfo("SoNormalCache::generatePerFaceQuad", "generating normals");
#endif

  this->clearGenerator();
  PRIVATE(this)->normalArray.truncate(0, TRUE);
  // avoid reallocations in growable array by setting the buffer size first
  PRIVATE(this)->normalArray.ensureCapacity((vPerRow-1)*(vPerColumn-1));
  
#if COIN_DEBUG
  if (vPerRow <= 1 || vPerColumn <= 1 || 
      static_cast<unsigned int>(vPerRow * vPerColumn) > numcoords) {

    SoDebugError::postWarning("SoNormalCache::generatePerFaceQuad", "Illegal "
                              "facequad dimension: [%d %d] with %d coordinates "
                              "available. verticesPerRow and verticesPerColumn "
                              "should be > 1, and verticesPerRow * verticesPerColumn "
                              "<= number of coordinates available.", 
                              vPerRow, vPerColumn, numcoords);
  }
#endif // COIN_DEBUG

#define IDX(r, c) ((r)*(vPerRow)+(c))

  for (int i = 0; i < vPerColumn-1; i++) {
    for (int j = 0; j < vPerRow-1; j++) {
      const unsigned int idx1 = IDX(i, j);
      const unsigned int idx2 = IDX(i+1, j);
      const unsigned int idx3 = IDX(i, j+1);

      if (idx2 < numcoords) { // Check the largest index only
        SbVec3f n = (coords[idx2] - coords[idx1]).cross(coords[idx3] - coords[idx1]);

        // Be robust when it comes to erroneously specified polygons.
        if ((n.normalize() == 0.0f) && coin_debug_extra())  {
          static uint32_t normgenerrors_facequad = 0;
          if (normgenerrors_facequad < 1) {
            SoDebugError::postWarning("SoNormalCache::generatePerFaceQuad",
                                      "Erroneous triangle specification in model "
                                      "(indices= [%d, %d, %d], "
                                      "coords=<%f, %f, %f>, <%f, %f, %f>, <%f, %f, %f>) "
                                      "(this warning will be printed only once, "
                                      "but there might be more errors).",
                                      idx1, idx2, idx3,
                                      coords[idx1][0], coords[idx1][1], coords[idx1][2],
                                      coords[idx2][0], coords[idx2][1], coords[idx2][2],
                                      coords[idx3][0], coords[idx3][1], coords[idx3][2]);
          }
          normgenerrors_facequad++;
        }
        
        PRIVATE(this)->normalArray.append(ccw ? -n : n);
      }
      else {
        // Generate normals even for invalid input
        SbVec3f dummynormal(0.0, 0.0, 0.0);
        PRIVATE(this)->normalArray.append(ccw ? -dummynormal : dummynormal);
      }
    }
  }

#undef IDX

  if (PRIVATE(this)->normalArray.getLength()) {
    PRIVATE(this)->normalData.normals = PRIVATE(this)->normalArray.getArrayPtr();
    PRIVATE(this)->numNormals = PRIVATE(this)->normalArray.getLength();
  }

#if NORMALCACHE_DEBUG && COIN_DEBUG
  SoDebugError::postInfo("SoNormalCache::generatePerFaceQuad",
                         "generated normals per face quad: %p %d\n",
                         PRIVATE(this)->normalData.normals, PRIVATE(this)->numNormals);
#endif

}
Beispiel #26
0
bool RayTracer::shade(SbVec3f *ray_origin, SbVec3f *ray_direction, SbVec3f *retColor, int recursionDepth, int flag){
	float t_value, t_min = 999;
	float epsilon = 0.01;
	SbVec3f normal_at_intersection;
	SbVec3f normal_at_intersection1, actual_ray_direction ;
	bool should_color = false;
    SbVec3f color;
    color[0] = 0.0;
    color[1] = 0.0;
    color[2] = 0.0;
    //Cone *tempCone = new Cone();
    for(int k =0; k<objects.size(); k++){
        //Object temp1 ;
        //temp1 = spheres.at(k);
        Sphere tempSphere;
        Cube tempCube;
        Cone tempCone;
        Object temp;
        bool intersects = false;
        int shapetype = 0;
        shapetype = objects.at(k).shapeType ;
        if(shapetype == 1){
            tempSphere = objects.at(k);
            intersects = tempSphere.intersection(ray_origin, ray_direction, &t_value);
        }
        else if (shapetype ==2){
            //std::cout<<"cube";
            tempCube = objects.at(k);
            intersects = tempCube.intersection(ray_origin, ray_direction, &t_value);
            //temp = (Cube)tempCube;
        }else{
            tempCone = objects.at(k);
            intersects = tempCone.intersection(ray_origin, ray_direction, &t_value);

        }

        if(intersects)
        {
            if(t_value < t_min && t_value > 0 && t_value !=999) {
                t_min = t_value;
                SbVec3f V = -(*ray_direction); //view vector
                V.normalize();
                SbVec3f point_of_intersection ;

                if(shapetype == 1){
                    normal_at_intersection = tempSphere.calculate_normal(ray_origin, ray_direction, t_value);
                    normal_at_intersection.normalize(); // N vector at the point of intersection
                    point_of_intersection = tempSphere.point_of_intersection( ray_origin, ray_direction, t_value);
                    temp = tempSphere;
                }else if(shapetype == 2){
                    normal_at_intersection = tempCube.calculate_normal(ray_origin, ray_direction, t_value);
                    normal_at_intersection.normalize(); // N vector at the point of intersection
                    point_of_intersection = tempCube.point_of_intersection( ray_origin, ray_direction, t_value);
                    temp = tempCube;
                }
                else{
                    normal_at_intersection = tempCone.calculate_normal(ray_origin, ray_direction, t_value);
                    normal_at_intersection.normalize(); // N vector at the point of intersection
                    point_of_intersection = tempCone.point_of_intersection( ray_origin, ray_direction, t_value);
                    temp = tempCone;

                }


                for(int i = 0; i <3; i++) {// set the ambient color component
                        color[i] = (0.2 *  temp.material->ambientColor[0][i] * (1 - temp.transparency ));
                }
                //*retColor = color; return true;//ntc
                // iterate through all the lights and add the diffuse and specular component
                for(int j = 0; j < lights.size(); j++){
                        SbVec3f poi;

                        actual_ray_direction = lights.at(j).position - point_of_intersection ;
                        actual_ray_direction.normalize();
                        poi = point_of_intersection + (epsilon * actual_ray_direction);
                        bool shadowFlag = false;
                        if(shadow_on == 0 || shadow_on == 1)
                        {
                            if(shadow_on == 1)
                                shadowFlag = shadow_ray_intersection(&poi, &actual_ray_direction , j );
                            //shadowFlag = true;
                            if(!shadowFlag)
                            {
                                SbVec3f L = lights.at(j).position - point_of_intersection;
                                L.normalize();
                                SbVec3f R;
                                R = (2 * normal_at_intersection.dot(L) * normal_at_intersection) - L;
                                R.normalize();

                                float NdotL = normal_at_intersection.dot(L);
                                float cos_theta = V.dot(R);

                                for(int i = 0; i <3; i++){
                                    if(NdotL > 0)
                                        color[i] += (( NdotL * temp.material->diffuseColor[0][i] * lights.at(j).intensity * lights.at(j).color[i]  * (1 - temp.transparency )));
                                    if(cos_theta > 0)
                                        color[i] += (( pow(cos_theta, 50) * temp.material->specularColor[0][i]* lights.at(j).intensity * lights.at(j).color[i]) );
                                }
                            }
                        }
                    else
                    { // soft shadows
                            {

                         //shadowLevel = soft_shadow_ray_intersection(&point_of_intersection, j );
                            SbVec3f actual_ray_direction, offset_ray_direction;
                            SbVec3f tempu, tempv, tempn;
                            int number_of_shadow_rays;
                            number_of_shadow_rays = NUMBER_OF_SHADOW_RAYS;
                            float epsilon = 0.01;
                            float R = 0.1;
                            actual_ray_direction = lights.at(j).position - point_of_intersection ;
                            actual_ray_direction.normalize();
                            SbVec3f point = point_of_intersection + (epsilon * actual_ray_direction);

                            calculate_coordinate_system(&tempu, &tempv, &tempn, actual_ray_direction);

                            for(int ir =0; ir< number_of_shadow_rays; ir++){

                                    float du, dv;
                                    //float t;
                                    du = get_random_number();
                                    dv = get_random_number();
                                    du = R * (du - 0.5);
                                    dv = R * (dv - 0.5);
                                    offset_ray_direction = actual_ray_direction + (du * tempu) + (dv * tempv);
                                    offset_ray_direction.normalize();

                                    //offset_ray_direction = actual_ray_direction - (R/2 * u) - (R/2 * v) + (du * R * u) + (dv *R * v);
                                    SbVec3f poi;
                                    poi = point + (epsilon * offset_ray_direction);
                                    //offset_ray_direction = actual_ray_direction;
                                    if(!shadow_ray_intersection(&poi, &offset_ray_direction, j)){
                                        //normal_at_intersection = temp.calculate_normal(&poi, &offset_ray_direction, t_value);
                                        //normal_at_intersection.normalize();
                                        SbVec3f V = -1 * (*ray_direction); //view vector
                                        V.normalize();
                                        SbVec3f L = offset_ray_direction;
                                        L.normalize();
                                        SbVec3f R;
                                        R = (2 * normal_at_intersection.dot(L) * normal_at_intersection) - L;
                                        R.normalize();

                                        float NdotL = normal_at_intersection.dot(L);
                                        float cos_theta = V.dot(R);
                                        //if(temp.transparency > 0) std::cout<<"trnas";
                                        for(int i = 0; i <3; i++){
                                            {
                                                if(NdotL > 0)
                                                    color[i] += (( NdotL * temp.material->diffuseColor[0][i] * lights.at(j).intensity * lights.at(j).color[i]  * (1 - temp.transparency ))/ number_of_shadow_rays);
                                                if(cos_theta > 0)
                                                    color[i] += (( pow(cos_theta, 50) * temp.material->specularColor[0][i]* lights.at(j).intensity * lights.at(j).color[i]) / number_of_shadow_rays);
                                            }
                                        }

                                    }

                    }

                    }

                        }
                }
                SbVec3f refColor(0.0,0.0,0.0);
                SbVec3f refracColor(0.0,0.0,0.0);
                // if the current depth of recustion is less than the maximum depth,
                //reflect the ray and add the color returned dude to the result of reflection
                //std::cout<<"here";
                if(refraction_on && recursionDepth < 2){
                    if(temp.isTransparent){
                        SbVec3f T;
                        if(refract(ray_direction, &normal_at_intersection, &T)){
                            T.normalize();
                            SbVec3f poi;
                            poi = point_of_intersection + (epsilon * T);
                            shade(&poi, &T, &refracColor, recursionDepth+1);
                            color = color + (temp.transparency * refracColor);
                        }

                    }
                }
                if(reflection_on && recursionDepth < 2){

                    if(temp.isShiny){//} && !temp.isTransparent){
                        // compute replection of the ray, R1
                        SbVec3f R1;
                        R1 = reflect(&normal_at_intersection, ray_direction);
                        SbVec3f poi;
                        poi = point_of_intersection + (epsilon * R1);
                        shade(&poi, &R1, &refColor, recursionDepth+1);
                        color = color + ((1 - temp.transparency) * temp.shininess * refColor);

                    }
                }

                should_color = true;
            }

        }
    }
    *retColor = color;
    return should_color;
}
Beispiel #27
0
SbVec3f RayTracer::reflect(SbVec3f *normal_at_intersection, SbVec3f *ray_direction){
    SbVec3f  R;
    R = (-2 *(normal_at_intersection->dot(*ray_direction)* *normal_at_intersection)) + *ray_direction;
    R.normalize();
    return R;
}
SbRotation
SbSphereSectionProjector::getRotation(const SbVec3f &p1, const SbVec3f &p2)
//
////////////////////////////////////////////////////////////////////////
{
    SbBool tol1 = isWithinTolerance(p1);
    SbBool tol2 = isWithinTolerance(p2);

    if (tol1 && tol2) {
	// both points in tolerance, rotate about
	// sphere center

	return SbRotation(
	    p1 - sphere.getCenter(),
	    p2 - sphere.getCenter());
    }
    else if (!tol1 && !tol2) {
	// both points out of tolerance, rotate about
	// plane point

	// Would like to just use this:
	SbRotation badRot = SbRotation(p1 - planePoint, p2 - planePoint);
	// but fp instablity gives back a goofy axis, so we don't get
	// pure roll.

	// So we need to snap the axis to be parallel to plane dir
	SbVec3f badAxis; float goodAngle;
	badRot.getValue(badAxis, goodAngle);

	SbVec3f goodAxis;
	if (badAxis.dot(planeDir) > 0.0)
	    goodAxis = planeDir;
	else 	    
	    goodAxis = -planeDir;

	SbRotation rollRot(goodAxis, goodAngle);

	//Now find rotation in the direction perpendicular to this:
	SbVec3f diff1 = p1 - planePoint;
	SbVec3f diff2 = p2 - planePoint;
	float d = diff2.length() - diff1.length();

	// Check for degenerate cases
	float theta = d / sphere.getRadius();
	if ( fabs(theta) < 0.000001 || fabs(theta) > 1.0 )
	    return rollRot;

	diff1.normalize();
	SbVec3f pullAxis = planeDir.cross( diff1 );
	pullAxis.normalize();
	SbRotation pullRot(pullAxis, getRadialFactor() * theta );

	SbRotation totalRot = rollRot * pullRot;
	return totalRot;

    }
    else {
	// one point in, one point out, so rotate about
	// the center of the sphere from the point on the
	// sphere to the intersection of the plane and the
	// sphere closest to the point off the sphere

	SbLine planeLine;
	SbVec3f intersection;

	if (tol1) {
	    planeLine.setValue(planePoint, p2);
	}
	else {
	    planeLine.setValue(planePoint, p1);
	}

	if (! sphere.intersect(planeLine, intersection))
#ifdef DEBUG
	    SoDebugError::post("SbSphereSectionProjector::getRotation",
			       "Couldn't intersect plane line with sphere");
#else
	/* Do nothing */;
#endif

	if (tol1) {
	    // went off sphere
	    return SbRotation(
		p1 - sphere.getCenter(),
		intersection - sphere.getCenter());
	}
	else {
	    // came on to sphere
	    // "Hey cutie. You've got quite a radius..."
	    return SbRotation(
		intersection - sphere.getCenter(),
		p2 - sphere.getCenter());
	}
    }

}
Beispiel #29
0
// internal callback
void InvPlaneMover::dragFinishCB(void *me, SoDragger *drag)
{

    InvPlaneMover *mee = static_cast<InvPlaneMover *>(me);

    if (mee->show_)
    {

        SbVec3f t = ((SoJackDragger *)drag)->translation.getValue();

        int i;
        for (i = 0; i < 3; ++i)
            t[i] *= mee->scale_->scaleFactor.getValue()[i];

        SbRotation r = ((SoJackDragger *)drag)->rotation.getValue();

        SbVec3f n;
        SbVec3f ax;
        float angle;
        r.getValue(ax, angle);

        SbVec3f axN;
        mee->fullRot_->rotation.getValue().multVec(ax, axN);

        r.setValue(axN, angle);

        r.multVec(mee->nnn_, n);

        // we have to rotate the translation around the x-axis
        // (because we have a y-axis dragger)
        SbVec3f tt;
        n.normalize();

        // snap normal to the closest coordinate axis
        // here done by snaping it to the axis with the biggest projection onto it.
        if (mee->motionMode_ == InvPlaneMover::SNAP)
        {
            int axis;
            float mmax;
            int dir = 1;
            SbVec3f nn;

            if (n[0] * n[0] < n[1] * n[1])
            {
                axis = 1;
                mmax = n[1];
                if (n[1] < 0)
                    dir = -1;
                else
                    dir = +1;
                //dir = (int) copysign(1,n[1]);
            }
            else
            {
                axis = 0;
                mmax = n[0];
                if (n[0] < 0)
                    dir = -1;
                else
                    dir = +1;
                //dir = (int) copysign(1,n[0]);
            }
            if (mmax * mmax < n[2] * n[2])
            {
                axis = 2;
                if (n[2] < 0)
                    dir = -1;
                else
                    dir = +1;
                //dir = (int) copysign(1,n[2]);
            }

            switch (axis)
            {
            case 0:
                nn.setValue(1, 0, 0);
                break;
            case 1:
                nn.setValue(0, 1, 0);
                break;
            case 2:
                nn.setValue(0, 0, 1);
                break;
            }
            n = dir * nn;
        }

        tt = t[1] * n;

        float d;
        d = n.dot(tt + mee->distOffset_);

        float data[4];
        data[0] = n[0];
        data[1] = n[1];
        data[2] = n[2];
        data[3] = d;

        // send feedback message to contoller
        ((InvPlaneMover *)me)->sendFeedback(data);
    }
}
Beispiel #30
0
bool RayTracer::shade(SbVec3f *ray_origin, SbVec3f *ray_direction, SbVec3f *retColor, int recursionDepth){
	float t_value, t_min = 999;
	SbVec3f normal_at_intersection;
	bool should_color = false;
    SbVec3f color;
    color[0] = 0.0;
    color[1] = 0.0;
    color[2] = 0.0;
    for(int k =0; k<spheres.size(); k++){
        Sphere temp = spheres.at(k);

        if(temp.intersection(ray_origin, ray_direction, &t_value))
        {
            if(t_value < t_min && t_value > 0 && t_value !=999) {

                t_min = t_value;
                SbVec3f V = -(*ray_direction); //view vector
                V.normalize();
                normal_at_intersection = temp.calculate_normal(ray_origin, ray_direction, t_value);
                normal_at_intersection.normalize(); // N vector at the point of intersection
                SbVec3f point_of_intersection = temp.point_of_intersection( ray_origin, ray_direction, t_value);

                for(int i = 0; i <3; i++) {// set the ambient color component
                        color[i] = (0.2 *  temp.material->ambientColor[0][i]);
                }
                // iterate through all the lights and add the diffuse and specular component
                for(int j = 0; j < lights.size(); j++){

                        bool shadowFlag = false;
                        if(shadow_on )
                            shadowFlag = shadow_ray_intersection(&point_of_intersection, j );
                        if(!shadowFlag){

                            SbVec3f L = lights.at(j).position - point_of_intersection;
                            L.normalize();
                            SbVec3f R;
                            R = (2 * normal_at_intersection.dot(L) * normal_at_intersection) - L;
                            R.normalize();
                            //SbVec3f H = (V + L);//is using half way vector
                            //H.normalize();//is using half way vector
                            //float cos_theta = H.dot(normal_at_intersection); //is using half way vector

                            float NdotL = normal_at_intersection.dot(L);
                            float cos_theta = V.dot(R);

                            for(int i = 0; i <3; i++){
                                if(NdotL > 0)
                                    color[i] += ( NdotL * temp.material->diffuseColor[0][i] * lights.at(j).intensity * lights.at(j).color[i]);
                                if(cos_theta > 0)
                                    color[i] += ( pow(cos_theta, 20) * temp.material->specularColor[0][i]* lights.at(j).intensity * lights.at(j).color[i]);
                            }
                        }

                }
                SbVec3f refColor(0.0,0.0,0.0);
                // if the current depth of recustion is less than the maximum depth,
                //reflect the ray and add the color returned dude to the result of reflection
                if(reflection_on && recursionDepth < 4){
                        if(temp.isShiny){
                            // compute replection of the ray, R1
                            SbVec3f R1;
                            R1 = (-2 *(normal_at_intersection.dot(*ray_direction)* normal_at_intersection)) + *ray_direction;
                            R1.normalize();
                            shade(&point_of_intersection, &R1, &refColor, recursionDepth+1);
                            color = color + (temp.shininess * refColor);

                        }
                    }
                should_color = true;
            }

        }
    }
    *retColor = color;
    return should_color;
}