Beispiel #1
0
bool
XipGeomUtils::isIntersect(const SbVec3f &u, const SbVec3f &v, const SbPlane &plane)
{
    float d0 = u.dot(plane.getNormal()) - plane.getDistanceFromOrigin();
    float d1 = v.dot(plane.getNormal()) - plane.getDistanceFromOrigin();

    if ( d0*d1>XIP_EPSILON ) return false;

    return true;
}
Beispiel #2
0
bool
XipGeomUtils::intersect(const SbVec3f &u, const SbVec3f &v, const SbPlane &plane, SbVec3f &pt)
{
    float d0 = u.dot(plane.getNormal()) - plane.getDistanceFromOrigin();
    float d1 = v.dot(plane.getNormal()) - plane.getDistanceFromOrigin();

    if ( d0*d1> -XIP_EPSILON ) return false;

    return XipGeomUtils::intersect(SbLine(u, v), plane, pt);
}
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 RayTracer::should_transmit(SbVec3f *ray_direction, SbVec3f *normal_at_intersection, float refractive_index){
    float ret;
    SbVec3f V;
    SbVec3f N;
    float ri;

    V = -1 * *ray_direction;
    N = *normal_at_intersection;
    ri = refractive_index;
    ret = 1- ((ri*ri)*(1-( N.dot(V) * N.dot(V) )));
    if (ret < 0) ret = -1;
    return ret;
}
Beispiel #5
0
double
angleBetweenVectors( const SbVec3f& u, const SbVec3f& v )
{
	double cosAngle = v.dot( u ) / ( u.length() * v.length() );

	return acos( cosAngle );
}
Beispiel #6
0
double
angleBetweenVectors( const SbVec3f& u, const SbVec3f& v, const SbVec3f& normal )
{
	double cosAngle = v.dot( u ) / ( u.length() * v.length() );
	float     angle = acos( cosAngle );

	// FIXME: Check if this is required
	//
	SbVec3f cross  = u.cross( v );
	
	if( cross.dot( normal ) < 0 )
		angle = 2 * M_PI - angle;
	//

	return angle;
}
    bool isVisibleFace(int faceIndex, const SbVec2f& pos, Gui::View3DInventorViewer* viewer)
    {
        SoSeparator* root = new SoSeparator;
        root->ref();
        root->addChild(viewer->getSoRenderManager()->getCamera());
        root->addChild(vp->getRoot());

        SoSearchAction searchAction;
        searchAction.setType(PartGui::SoBrepFaceSet::getClassTypeId());
        searchAction.setInterest(SoSearchAction::FIRST);
        searchAction.apply(root);
        SoPath* selectionPath = searchAction.getPath();

        SoRayPickAction rp(viewer->getSoRenderManager()->getViewportRegion());
        rp.setNormalizedPoint(pos);
        rp.apply(selectionPath);
        root->unref();

        SoPickedPoint* pick = rp.getPickedPoint();
        if (pick) {
            const SoDetail* detail = pick->getDetail();
            if (detail && detail->isOfType(SoFaceDetail::getClassTypeId())) {
                int index = static_cast<const SoFaceDetail*>(detail)->getPartIndex();
                if (faceIndex != index)
                    return false;
                SbVec3f dir = viewer->getViewDirection();
                const SbVec3f& nor = pick->getNormal();
                if (dir.dot(nor) > 0)
                    return false; // bottom side points to user
                return true;
            }
        }

        return false;
    }
Beispiel #8
0
void InvPlaneMover::setPosition(SbVec3f &point)
{

    // make sure that the normal points in direction to the camera
    SbVec3f camPos = renderer->viewer->getCamera()->position.getValue();
    SbVec3f no;
    if (camPos.dot(planeNormal_) < 0)
    {
        no = planeNormal_;
    }
    else
    {
        no = -planeNormal_;
    }

    fprintf(stderr, "inorm=(%f %f %f), no=(%f %f %f)\n",
            iNorm_[0], iNorm_[1], iNorm_[2],
            no[0], no[1], no[2]);

    SbRotation rota(iNorm_, no);

    distOffset_ = point;
    nnn_ = no;

    // the handle lays in front of the plane by this distance
    float offset_of_handle = 0.001 * scale_->scaleFactor.getValue()[0];

    //   if (!show) {
    transl_->translation = point - offset_of_handle * no;
    fullRot_->rotation = rota;
    //   }
    SbVec3f t(0, 0, 0);
    jDrag_->translation.setValue(t);
    jDrag_->rotation.setValue(SbRotation::identity());
}
Beispiel #9
0
bool
XipGeomUtils::isOnPlane(const SbVec3f& pt, const SbPlane &plane)
{
    float dist = pt.dot(plane.getNormal()) - plane.getDistanceFromOrigin();
    if ( fabs(dist)<XIP_EPSILON ) return true;

    return false;
}
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
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;
}
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
/*! 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;
}
Beispiel #14
0
/*!
  Check if \a point is on the frontside or the backside of the
  cylinder.
*/
SbBool
SbSphereProjector::isPointInFront(const SbVec3f & point) const
{
  const SbViewVolume & vv = this->getViewVolume();
  SbVec3f camdir;
  if (vv.getProjectionType() == SbViewVolume::PERSPECTIVE) {
    SbVec3f campos;
    this->worldToWorking.multVecMatrix(vv.getProjectionPoint(), campos);
    camdir = campos - this->sphere.getCenter();
  }
  else {
    this->worldToWorking.multDirMatrix( vv.zVector(), camdir);
  }
  SbVec3f ptdir = point - this->sphere.getCenter();
  return ptdir.dot(camdir) >= 0.0f;
}
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 #16
0
//////////////////////////////////////////////////////////////////////////////
//
// Sphere line intersection - this sets the parameter intersection,
// and returns TRUE if the line and sphere really do intersect.
//
// line-sphere intersection algorithm lifted from Eric Haines chapter in 
// Glassner's "Introduction to Ray Tracing", pp. 35-7
//
SbBool
SbSphere::intersect(const SbLine &l, SbVec3f &intersection) const
//
//////////////////////////////////////////////////////////////////////////////
{
    float   B,C;	// At^2 + Bt + C = 0, but A is 1 since we normalize Rd
    float   discr;	// discriminant (B^2 - 4AC)
    SbVec3f v;
    float   t,sqroot;
    SbBool  doesIntersect = TRUE;

    // setup B,C
    v = l.getPosition() - center;
    B = 2.0 * (l.getDirection().dot(v));
    C = v.dot(v) - (radius * radius);

    // compute discriminant
    // if negative, there is no intersection
    discr = B*B - 4.0*C;
    if (discr < 0.0) {
	// line and sphere do not intersect
	doesIntersect = FALSE;
    }
    else {
	// compute t0: (-B - sqrt(B^2 - 4AC)) / 2A  (A = 1)
	sqroot = sqrtf(discr);
	t = (-B - sqroot) * 0.5;
	if (t < 0.0) {
	    // no intersection, try t1: (-B + sqrt(B^2 - 4AC)) / 2A  (A = 1)
	    t = (-B + sqroot) * 0.5;
	}

	if (t < 0.0) {
	    // line and sphere do not intersect
	    doesIntersect = FALSE;
	}
	else {
	    // intersection! point is (point + (dir * t))
	    intersection = l.getPosition() + (l.getDirection() * t);
	}
    }

    return doesIntersect;
}
Beispiel #17
0
//////////////////////////////////////////////////////////////////////////////
//
// Sphere line intersection - this sets the parameter intersection,
// and returns TRUE if the line and sphere really do intersect.
//
// line-sphere intersection algorithm lifted from Eric Haines chapter in 
// Glassner's "Introduction to Ray Tracing", pp. 35-7
//
SbBool
SbSphere::intersect(const SbLine &l, SbVec3f &enter, SbVec3f &exit) const
//
//////////////////////////////////////////////////////////////////////////////
{
    float   B,C;	// At^2 + Bt + C = 0, but A is 1 since we normalize Rd
    float   discr;	// discriminant (B^2 - 4AC)
    SbVec3f v;
    float   sqroot;
    SbBool  doesIntersect = TRUE;

    // setup B,C
    v = l.getPosition() - center;
    B = 2.0 * (l.getDirection().dot(v));
    C = v.dot(v) - (radius * radius);

    // compute discriminant
    // if negative, there is no intersection
    discr = B*B - 4.0*C;

    if (discr < 0.0) {
	// line and sphere do not intersect
	doesIntersect = FALSE;
    }
    else {
	sqroot = sqrtf(discr);
	    
	float t0 = (-B - sqroot) * 0.5;
	enter = l.getPosition() + (l.getDirection() * t0);
	
	float t1 = (-B + sqroot) * 0.5;
	exit = l.getPosition() + (l.getDirection() * t1);
    }

    return doesIntersect;
}
Beispiel #18
0
bool
XipGeomUtils::intersect(const SbMatrix &mpr, const SbMatrix &model, SbMatrix &newMpr, int width, int height, int depth, bool shifted)
{
    SbVec3f t, s ;
    SbRotation r, so ;
    model.getTransform ( t, r, s, so ) ;

    SbVec3f vsize, origin;
    SbVec3f axisX, axisY, axisZ;
    axisX[0] = model[0][0];
    axisX[1] = model[0][1];
    axisX[2] = model[0][2];
    axisX.normalize();

    axisY[0] = model[1][0];
    axisY[1] = model[1][1];
    axisY[2] = model[1][2];
    axisY.normalize();

    axisZ[0] = model[2][0];
    axisZ[1] = model[2][1];
    axisZ[2] = model[2][2];
    axisZ.normalize();

    if ( shifted )
    {
        vsize[0] = s[0] / static_cast<float>(width);
        vsize[1] = s[1] / static_cast<float>(height);
        vsize[2] = s[2] / static_cast<float>(depth);

        origin = t - 0.5f*vsize[0]*axisX - 0.5f*vsize[1]*axisY - 0.5f*vsize[2]*axisZ;
    }
    else
    {
        origin[0] = t[0];
        origin[1] = t[1];
        origin[2] = t[2];
    }

    axisX[0] = model[0][0];
    axisX[1] = model[0][1];
    axisX[2] = model[0][2];

    axisY[0] = model[1][0];
    axisY[1] = model[1][1];
    axisY[2] = model[1][2];

    axisZ[0] = model[2][0];
    axisZ[1] = model[2][1];
    axisZ[2] = model[2][2];

    SbVec3f vert[8];
    vert[0] = origin;
    vert[1] = origin + axisX;
    vert[2] = origin + axisX + axisY;
    vert[3] = origin + axisY;

    vert[4] = vert[0] + axisZ;
    vert[5] = vert[1] + axisZ;
    vert[6] = vert[2] + axisZ;
    vert[7] = vert[3] + axisZ;

    mpr.getTransform ( t, r, s, so ) ;
    axisX[0] = mpr[0][0];
    axisX[1] = mpr[0][1];
    axisX[2] = mpr[0][2];
    axisX.normalize();

    axisY[0] = mpr[1][0];
    axisY[1] = mpr[1][1];
    axisY[2] = mpr[1][2];
    axisY.normalize();

    SbPlane plane(t, t+axisX, t+axisY);

    vector<SbVec3f> pts;
    pts.clear();
    SbVec3f pt;
    for (int i=0; i<12; ++i)
    {
        if ( intersect(vert[edge[i][0]], vert[edge[i][1]], plane, pt) )
        {
            pts.push_back(pt);
        }
    }

    for (int i=0; i<8; ++i)
    {
        if ( isOnPlane(vert[i], plane) )
        {
            pts.push_back(vert[i]);
        }
    }

    if ( pts.size()<3 ) return false;

    SbVec3f u;
    SbVec2f minv(numeric_limits<float>::max(), numeric_limits<float>::max());
    SbVec2f maxv(-numeric_limits<float>::max(), -numeric_limits<float>::max());
    float tmp;
    for (size_t i=0; i<pts.size(); ++i)
    {
        u = pts[i] - t;
        tmp = u.dot(axisX);
        if ( minv[0]>tmp ) minv[0] = tmp;
        if ( maxv[0]<tmp ) maxv[0] = tmp;

        tmp = u.dot(axisY);
        if ( minv[1]>tmp ) minv[1] = tmp;
        if ( maxv[1]<tmp ) maxv[1] = tmp;
    }

    SbVec2f center = 0.5f*(minv+maxv);

    origin = t + center[0]*axisX + center[1]*axisY;

    if ( !XipGeomUtils::isOnPlane(origin, mpr) )
    {
        XipDebug::output("Error: new center is not on the plane");
    }

    SbVec3f pt0 = t + minv[0]*axisX + minv[1]*axisY;
    SbVec3f pt1 = t + maxv[0]*axisX + minv[1]*axisY;
    SbVec3f pt2 = t + maxv[0]*axisX + maxv[1]*axisY;

    float scale = (pt1 - pt0).length();
    u = pt2 - pt1;
    if ( scale<u.length() ) scale = u.length();
    scale *= 1.01f;

    newMpr.setTransform(origin, r, SbVec3f(scale, scale, scale), so);
    //XipDebug::output("%f --> %f", s[0], scale);

    return true;
}
Beispiel #19
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 #20
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 #21
0
/*!
  Returns the two closest points on the lines.  If the lines are
  parallel, all points are equally close and we return \c FALSE. If
  the lines are not parallel, the point positions will be stored in \a
  ptOnThis and \a ptOnLine2, and we'll return \c TRUE.

  Note that both SbLine instances are considered to be infinite in
  both directions from their definition points, as far as this
  function is concerned.

  \sa getClosestPoint().
*/
SbBool
SbLine::getClosestPoints(const SbLine& line2,
                         SbVec3f& ptOnThis, SbVec3f& ptOnLine2) const
{
#if 1 
  // new optimized version based on formulas from from Boyko Bantchev

  // p1 = point on line 1
  // p2 = point on line 2
  // d1 = line 1 direction
  // d2 = line 2 direction
  // q1 = closest point on line 1
  // q2 = closest point on line 2

  // The solution (q1 and q2) must be on their respective 
  // lines:
  //
  // q1 = p1 + t1 * d1                               (0)
  // q2 = p2 + t2 * d2
  //
  // we set u = p2 - p1, and get:
  //
  // q2 - q1 = u + t2*d2 - t1*d1                     (1)
  //
  // the solution line q2 - q1 is orthogonal to d1 and d2 
  // (or a null vector if the lines intersect), which yields:
  //
  // (u + t2*d2 - t1*d1) · d1 = 0                    (2)
  // (u + t2*d2 - t1*d1) · d2 = 0
  //
  // we know |d1| and |d2| == 1, and set d1 · d2 = t
  //
  // t1 - t*t2 = u · d1
  // t*t1 - t2 = u · d2
  //
  // Solve for t1, and find q1 using (0):
  //
  // t1 = (u·d1 - t * (u·d2))/ (1 - t^2)
  //
  // just find q2 by using line2.getClosestPoint(q1)

  SbVec3f p1 = this->pos;
  SbVec3f p2 = line2.pos;
  
  SbVec3f d1 = this->dir;
  SbVec3f d2 = line2.dir;

  SbVec3f u = p2-p1;
  float t = d1.dot(d2);

  const float eps = 1.0e-06f;
  if (t < -1.0f + eps || t > 1.0f-eps) {
    // lines are parallel
    return FALSE;
  }
  t = (u.dot(d1) - t * u.dot(d2)) / (1-t*t);
  ptOnThis = p1 + t * d1;
  ptOnLine2 = line2.getClosestPoint(ptOnThis);
  return TRUE;
#else // old version

#if COIN_DEBUG
  if(this->getDirection().length() == 0.0)
    SoDebugError::postWarning("SbLine::getClosestPoints",
                              "This line has no direction (zero vector).");
  if(line2.getDirection().length() == 0.0)
    SoDebugError::postWarning("SbLine::getClosestPoints",
                              "argument line has no direction (zero vector).");
#endif // COIN_DEBUG

  // Check if the lines are parallel.
  // FIXME: should probably use equals() here.
  if(line2.dir == this->dir) return FALSE;
  else if(line2.dir == -this->dir) return FALSE;


  // From the discussion on getClosestPoint(), we know that the point
  // we wish to find on a line can be expressed as:
  //
  //                  (Q1-P0)·D0
  //   Q0 = P0 + D0 * ----------
  //                     |D0|
  //
  // ...where P0 is a point on the first line, D0 is the direction
  // vector and Q1 is the "closest point" on the other line. From this
  // we get two equations with two unknowns. By substituting for
  // Q1 we get a new equation with a single unknown, Q0:
  //
  //                   (         (Q0 - P1)·D1    )
  //                   (P1 + D1 * ------------ - P0) · D0
  //                   (             |D1|        )
  //   Q0 = P0 + D0 * ------------------------------------
  //                                |D0|
  //
  // Which obviously is bloody hard (perhaps impossible?) to solve
  // analytically. Damn. Back to the pen and pencil stuff.
  //
  // Ok, new try. Since we're looking for the minimum distance between the
  // two lines, we should be able to solve it by expressing the distance
  // between the points we want to find as a parametrized function and
  // take the derivative:
  //
  //   f(t0, t1) = |Q1 - Q0| = |P1+D1*t1 - (P0+D0*t0)|
  //
  //                         (t1*D1 - P0)·D0
  // t0 can be expressed as  ---------------  which gives us
  //                               |D0|
  //
  //   f(t) = |P1 + D1*t - P0 - D0N * ((t*D1 - P0)·D0)|, t = t1
  //                                                     D0N = D0 normalized
  //                               _____________
  // ..which is eual to   f(t) = \/Þ² + ß² + ð²  , where Þ, ß, and ð
  // is the full expression above with the x, y, and z components
  // of the vectors.
  //
  // Since we're looking for the minimum value of the function, we can just
  // ignore the square root. We'll do the next parts of the math on a
  // general components case, since it's the same for the x, y and z parts.
  //
  // Expanding any of the Þ, ß, or ð expressions, we get this:
  //   (P1[i] - D1[i]*t - P0[i] - D0N[i]*D0[x]*D1[x]*t + D0N[i]*D0[x]*P0[x]
  //      - D0N[i]*D0[y]*D1[y]*t + D0N[i]*D0[y]*P0[y] - D0N[i]*D0[z]*D1[z]*t
  //      + D0N[i]*D0[z]*P0[z])² ,
  // where i=[x|y|z].
  //
  // Derivating this by using the chain rule (i.e. g(t)² =
  // 2*g(t)*g'(t)), we'll get this equation for finding the t yielding
  // the minimum distance between two points Q0 and Q1 on the lines:
  //
  //      -(cx*dx+cy*dy+cz*dz)
  //  t = --------------------
  //        dx² + dy² + dz²
  //
  //  di = D1[i] - D0N[i] * (D0[x]*D1[x] + D0[y]*D1[y] + D0[z]*D1[z])
  // and
  //  ci = P1[i] - P0[i] + D0N[i] * (D0[x]*P0[x] + D0[y]*P0[y] + D0[z]*P0[z])
  // where i=[x|y|z].
  //
  // Now we'll substitute t back in for t1 in   Q1 = P1 + D1*t1, which'll
  // also let us find Q0 by an invocation of getClosestPoint().
  //
  // That's it. I can't believe this took me 4 hours to complete. Code worked
  // on the first run, though. :-)
  //                                                           19980815 mortene.

  SbVec3f P0 = this->pos;
  SbVec3f P1 = line2.pos;
  SbVec3f D0 = this->dir;
  SbVec3f D1 = line2.dir;
  SbVec3f D0N = D0;

  // we warn about lines with no direction above, just normalize
  (void) D0N.normalize();

  float c[3], d[3];

  for (int i=0; i < 3; i++) {
    d[i] =
      D1[i] - D0N[i]*(D0[0]*D1[0] + D0[1]*D1[1] + D0[2]*D1[2]);
    c[i] =
      P1[i] - P0[i] + D0N[i]*(D0[0]*P0[0] + D0[1]*P0[1] + D0[2]*P0[2]);
  }

  float t = -(c[0]*d[0]+c[1]*d[1]+c[2]*d[2]) / (d[0]*d[0]+d[1]*d[1]+d[2]*d[2]);

  ptOnLine2 = line2.pos + line2.dir * t;
  ptOnThis = this->getClosestPoint(ptOnLine2);

  return TRUE;
#endif
}
Beispiel #22
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;
}
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());
	}
    }

}