/*! \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; }
/*! 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; }
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); }
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); }
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; }
/*! \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 }
// 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); }
/*! \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; }
// 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); }
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; } } }
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); }
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(); }
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()) ; } }
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; }
/*! 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 }
/*! 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 }
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; }
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()); } } }
// 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); } }
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; }