void Controller::displayDensityCurves(int x, int y) { SteerableViewMap * svm = _Canvas->getSteerableViewMap(); if (!svm) return; unsigned int i, j; typedef vector<Vec3r> densityCurve; vector<densityCurve> curves(svm->getNumberOfOrientations() + 1); vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels()); // collect the curves values unsigned nbCurves = svm->getNumberOfOrientations() + 1; unsigned nbPoints = svm->getNumberOfPyramidLevels(); if (!nbPoints) return; // build the density/nbLevels curves for each orientation for (i = 0; i < nbCurves; ++i) { for (j = 0; j < nbPoints; ++j) { curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0)); } } // build the density/nbOrientations curves for each level for (i = 0; i < nbPoints; ++i) { for (j = 0; j < nbCurves; ++j) { curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0)); } } // display the curves #if 0 for (i = 0; i < nbCurves; ++i) _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0, 0), Vec2d(nbPoints, 1), curves[i], "scale", "density"); for (i = 1; i <= 8; ++i) _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0, 0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density"); _pDensityCurvesWindow->show(); #endif }
void IndexedFaceSet::ComputeBBox() { real XMax = _Vertices[0]; real YMax = _Vertices[1]; real ZMax = _Vertices[2]; real XMin = _Vertices[0]; real YMin = _Vertices[1]; real ZMin = _Vertices[2]; // parse all the coordinates to find // the Xmax, YMax, ZMax real *v = _Vertices; for(unsigned i=0; i<_VSize/3; i++) { // X if(*v > XMax) XMax = *v; if(*v < XMin) XMin = *v; v++; if(*v > YMax) YMax = *v; if(*v < YMin) YMin = *v; v++; if(*v > ZMax) ZMax = *v; if(*v < ZMin) ZMin = *v; v++; } SetBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); }
/*! Calculates \a matWorldToLight and \a matEyeToLight for a directional light \a dirL and inverse viewing matrix \a matEyeToWorld. */ void ShaderShadowMapEngine::calcDirectionalLightMatrices( Matrixr &matWorldToLight, Matrixr &matEyeToLight, const DirectionalLight *dirL, const Matrixr &matEyeToWorld) { if(dirL->getBeacon() != NULL) dirL->getBeacon()->getToWorld(matWorldToLight); Quaternion rotLightDir (Vec3r(0.f, 0.f, 1.f), dirL->getDirection()); Matrixr matLightDir; matLightDir.setRotate(rotLightDir); matWorldToLight.mult (matLightDir); matWorldToLight.invert( ); matEyeToLight = matWorldToLight; matEyeToLight.mult(matEyeToWorld); }
Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig, const Vec3r& dir, double& t, double& u, double& v, unsigned timestamp){ Polygon3r *occluder = 0; Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm()); bool inter = initInfiniteRay(orig, dir, timestamp); if(!inter){ return 0; } firstIntersectionGridVisitor visitor(orig,dir,_cell_size); castRayInternal(visitor); occluder = visitor.occluder(); t = visitor.t_; u = visitor.u_; v = visitor.v_; return occluder; }
/*! Calculates \a matWorldToLight and \a matEyeToLight for a spot light \a spotL and inverse viewing matrix \a matEyeToWorld. */ void ShaderShadowMapEngine::calcSpotLightMatrices( Matrixr &matWorldToLight, Matrixr &matEyeToLight, const SpotLight *spotL, const Matrixr &matEyeToWorld) { if(spotL->getBeacon() != NULL) spotL->getBeacon()->getToWorld(matWorldToLight); Matrixr matLightPos; matLightPos.setTranslate(spotL->getPosition()); Matrixr matLightDir; Quaternion rotLightDir(Vec3r(0.f, 0.f, 1.f), -spotL->getDirection()); matLightDir.setRotate(rotLightDir); matWorldToLight.mult (matLightPos); matWorldToLight.mult (matLightDir); matWorldToLight.invert( ); matEyeToLight = matWorldToLight; matEyeToLight.mult(matEyeToWorld); }
void WFillGrid::addShape(WShape *shape) { vector<WVertex*> fvertices; vector<Vec3r> vectors; vector<WFace*> & faces = shape->GetFaceList(); for (vector<WFace*>::const_iterator f = faces.begin(); f != faces.end(); f++) { (*f)->RetrieveVertexList(fvertices); for (vector<WVertex*>::const_iterator wv = fvertices.begin(); wv != fvertices.end(); wv++) vectors.push_back(Vec3r((*wv)->GetVertex())); // occluder will be deleted by the grid Polygon3r *occluder = new Polygon3r(vectors, (*f)->GetNormal()); occluder->setId(_polygon_id++); occluder->userdata = (void*)(*f); _grid->insertOccluder(occluder); vectors.clear(); fvertices.clear(); } // faces.clear(); }
void ThirdPersonCamera::UpdateViewMatrix(real dt) { m_orientation.ToMatrix(m_viewMatrix.m_matrix); m_xAxis = Vec3r(m_viewMatrix.Access(0,0), m_viewMatrix.Access(1,0), m_viewMatrix.Access(2,0)); m_yAxis = Vec3r(m_viewMatrix.Access(0,1), m_viewMatrix.Access(1,1), m_viewMatrix.Access(2,1)); m_zAxis = Vec3r(m_viewMatrix.Access(0,2), m_viewMatrix.Access(1,2), m_viewMatrix.Access(2,2)); // Calculate the new camera position. The 'idealPosition' is where the // camera should be position. The camera should be positioned directly // behind the target at the required offset distance. What we're doing here // is rather than have the camera immediately snap to the 'idealPosition' // we slowly move the camera towards the 'idealPosition' using a spring // system. // // References: // Stone, Jonathan, "Third-Person Camera Navigation," Game Programming // Gems 4, Andrew Kirmse, Editor, Charles River Media, Inc., 2004. //Vec3r idealPosition = m_target + m_zAxis * m_offsetDistance; Vec3r idealPosition = m_target + m_targetZAxis * m_offsetDistance; Vec3r displacement = m_eye - idealPosition; Vec3r springAcceleration = (displacement * -m_springConstant) - (m_velocity * m_dampingConstant); m_velocity += springAcceleration * dt; m_eye += m_velocity * dt; // The view matrix is always relative to the camera's current position // 'm_eye'. Since a spring system is being used here 'm_eye' will be // relative to 'idealPosition'. When the camera is no longer being // moved 'm_eye' will become the same as 'idealPosition'. The local // x, y, and z axes that were extracted from the camera's orientation // 'm_orienation' is correct for the 'idealPosition' only. We need // to recompute these axes so that they're relative to 'm_eye'. Once // that's done we can use those axes to reconstruct the view matrix. m_zAxis = m_eye - m_target; m_zAxis.Normalise(); m_xAxis = Vec3r::CrossProduct(m_targetYAxis, m_zAxis); m_xAxis.Normalise(); m_yAxis = Vec3r::CrossProduct(m_zAxis, m_xAxis); m_yAxis.Normalise(); m_viewMatrix.SetToIdentity(); m_viewMatrix.Access(0,0) = m_xAxis.X; m_viewMatrix.Access(1,0) = m_xAxis.Y; m_viewMatrix.Access(2,0) = m_xAxis.Z; m_viewMatrix.Access(3,0) = -Vec3r::DotProduct(m_xAxis, m_eye); m_viewMatrix.Access(0,1) = m_yAxis.X; m_viewMatrix.Access(1,1) = m_yAxis.Y; m_viewMatrix.Access(2,1) = m_yAxis.Z; m_viewMatrix.Access(3,1) = -Vec3r::DotProduct(m_yAxis, m_eye); m_viewMatrix.Access(0,2) = m_zAxis.X; m_viewMatrix.Access(1,2) = m_zAxis.Y; m_viewMatrix.Access(2,2) = m_zAxis.Z; m_viewMatrix.Access(3,2) = -Vec3r::DotProduct(m_zAxis, m_eye); m_viewDir = m_zAxis * -1; }
SpikedFloor::SpikedFloor(Vec2r halfExtents, Vec2r worldPos) { m_halfExtents = halfExtents; m_pos = Vec3r(worldPos.X, worldPos.Y, -1); }
void PSStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const { if (_polylineOutput) { Stroke * stroke = iStrokeRep->getStroke(); _ofstream << "newpath" << endl; _ofstream << _polylineWidth << " setlinewidth\n"; _ofstream << "1 setlinejoin\n"; // select round line joins. default is miter, which creates protrustions at high-curvature areas bool first = true; for(Stroke::const_vertex_iterator v = stroke->vertices_begin(); v != stroke->vertices_end(); v++) { const StrokeVertex * vert = (*v); if (first) { const StrokeAttribute & attrib = vert->attribute(); Vec3f color = attrib.getColorRGB(); if (color[0] == 1 && color[1] == 1 && color[2] == 1) color = Vec3r (0,0,0); _ofstream << (color)[0] << " " << (color)[1] << " " << (color)[2] << " setrgbcolor" <<endl; } _ofstream << (double) vert->x() << " " << (double) vert->y() ; if (first) _ofstream << " moveto\n"; else _ofstream << " lineto\n"; real z = vert->z(); _ofstream << "%% "<< (double) z <<" depth\n"; first = false; } _ofstream << "stroke" << endl; // _ofstream << "closepath" << endl; // _ofstream << "fill" << endl; } else { vector<Strip*>& strips = iStrokeRep->getStrips(); for(vector<Strip*>::iterator s=strips.begin(); s!=strips.end(); ++s) { Strip::vertex_container& vertices = (*s)->vertices(); // output all the odd points, then all the even points in reverse Vec3f color = vertices[0]->color(); if (color == Vec3f(1,1,1)) color = Vec3r (0,0,0); _ofstream << "newpath" << endl; _ofstream << (color)[0] << " " << (color)[1] << " " << (color)[2] << " setrgbcolor" <<endl; bool first = true; for(int i=0;i<vertices.size(); i+=2) { StrokeVertexRep * svRep = vertices[i]; _ofstream << (double) svRep->point2d()[0] << " " << (double) svRep->point2d()[1]; if (first) _ofstream << " moveto\n"; else _ofstream << " lineto\n"; first = false; } for(int i=vertices.size()-1;i>=0;i-=2) { StrokeVertexRep * svRep = vertices[i]; _ofstream << (double) svRep->point2d()[0] << " " << (double) svRep->point2d()[1] << " lineto\n"; } _ofstream << "closepath" << endl; _ofstream << "fill" << endl; } } }
Vec3r WOEdge::getVec3r () { return Vec3r(_pbVertex->GetVertex() - _paVertex->GetVertex()); }
Boundary::Boundary() { psi=0.0; x=Vec3r(0.0); v=Vec3r(0.0); }
void Controller::ComputeViewMap() { if (!_ListOfModels.size()) return; if (NULL != _ViewMap) { delete _ViewMap; _ViewMap = NULL; } _pView->DetachDebug(); if (NULL != _DebugNode) { int ref = _DebugNode->destroy(); if (0 == ref) _DebugNode->addRef(); } _pView->DetachSilhouette(); if (NULL != _SilhouetteNode) { int ref = _SilhouetteNode->destroy(); if (0 == ref) delete _SilhouetteNode; } #if 0 if (NULL != _ProjectedSilhouette) { int ref = _ProjectedSilhouette->destroy(); if (0 == ref) delete _ProjectedSilhouette; } if (NULL != _VisibleProjectedSilhouette) { int ref = _VisibleProjectedSilhouette->destroy(); if (0 == ref) { delete _VisibleProjectedSilhouette; _VisibleProjectedSilhouette = NULL; } } #endif // retrieve the 3D viewpoint and transformations information //---------------------------------------------------------- // Save the viewpoint context at the view level in order // to be able to restore it later: // Restore the context of view: // we need to perform all these operations while the // 3D context is on. Vec3r vp(freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "mv" << endl; } #endif real mv[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { mv[i][j] = freestyle_mv[i][j]; #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << mv[i][j] << " "; } #endif } #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << endl; } #endif } #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "\nproj" << endl; } #endif real proj[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { proj[i][j] = freestyle_proj[i][j]; #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << proj[i][j] << " "; } #endif } #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << endl; } #endif } int viewport[4]; for (int i = 0; i < 4; i++) viewport[i] = freestyle_viewport[i]; #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl; } #endif // Flag the WXEdge structure for silhouette edge detection: //---------------------------------------------------------- if (G.debug & G_DEBUG_FREESTYLE) { cout << "\n=== Detecting silhouette edges ===" << endl; } _Chrono.start(); edgeDetector.setViewpoint(Vec3r(vp)); edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0); edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges); edgeDetector.enableSuggestiveContours(_ComputeSuggestive); edgeDetector.enableMaterialBoundaries(_ComputeMaterialBoundaries); edgeDetector.enableFaceSmoothness(_EnableFaceSmoothness); edgeDetector.setCreaseAngle(_creaseAngle); edgeDetector.setSphereRadius(_sphereRadius); edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon); edgeDetector.setRenderMonitor(_pRenderMonitor); edgeDetector.processShapes(*_winged_edge); real duration = _Chrono.stop(); if (G.debug & G_DEBUG_FREESTYLE) { printf("Feature lines : %lf\n", duration); } if (_pRenderMonitor->testBreak()) return; // Builds the view map structure from the flagged WSEdge structure: //---------------------------------------------------------- ViewMapBuilder vmBuilder; vmBuilder.setEnableQI(_EnableQI); vmBuilder.setViewpoint(Vec3r(vp)); vmBuilder.setTransform(mv, proj, viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian()); vmBuilder.setFrustum(_pView->znear(), _pView->zfar()); vmBuilder.setGrid(&_Grid); vmBuilder.setRenderMonitor(_pRenderMonitor); // Builds a tesselated form of the silhouette for display purpose: //--------------------------------------------------------------- ViewMapTesselator3D sTesselator3d; #if 0 ViewMapTesselator2D sTesselator2d; sTesselator2d.setNature(_edgeTesselationNature); #endif sTesselator3d.setNature(_edgeTesselationNature); if (G.debug & G_DEBUG_FREESTYLE) { cout << "\n=== Building the view map ===" << endl; } _Chrono.start(); // Build View Map _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON, _Scene3dBBox, _SceneNumFaces); _ViewMap->setScene3dBBox(_Scene3dBBox); if (G.debug & G_DEBUG_FREESTYLE) { printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size()); } // Tesselate the 3D edges: _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap); _SilhouetteNode->addRef(); // Tesselate 2D edges #if 0 _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap); _ProjectedSilhouette->addRef(); #endif duration = _Chrono.stop(); if (G.debug & G_DEBUG_FREESTYLE) { printf("ViewMap building : %lf\n", duration); } _pView->AddSilhouette(_SilhouetteNode); #if 0 _pView->AddSilhouette(_WRoot); _pView->Add2DSilhouette(_ProjectedSilhouette); _pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette); #endif _pView->AddDebug(_DebugNode); // Draw the steerable density map: //-------------------------------- if (_ComputeSteerableViewMap) { ComputeSteerableViewMap(); } // Reset Style modules modification flags resetModified(true); DeleteWingedEdge(); }
SolidFixture() { sim = createSimulator(); sim->setGravity( Vec3r( 0, -9.81, 0 ) ); s = sim->createSolid(); }
/* splits an edge into several edges. * The edge's vertices are passed rather than * the edge itself. This way, all feature edges (SILHOUETTE, * CREASE, BORDER) are splitted in the same time. * The processed edges are flagged as done (using the userdata * flag).One single new vertex is created whereas * several splitted edges might created for the different * kinds of edges. These new elements are added to the lists * maintained by the shape. * new chains are also created. * ioA * The first vertex for the edge that gets splitted * ioB * The second vertex for the edge that gets splitted * iParameters * A vector containing 2D real vectors indicating the parameters * giving the intersections coordinates in 3D and in 2D. * These intersections points must be sorted from B to A. * Each parameter defines the intersection point I as I=A+T*AB. * T<0 and T>1 are then incorrect insofar as they give intersections * points that lie outside the segment. * ioNewEdges * The edges that are newly created (the initial edges are not * included) are added to this list. */ void SShape::SplitEdge(FEdge *fe, const vector<Vec2r>& iParameters, vector<FEdge*>& ioNewEdges) { SVertex *ioA = fe->vertexA(); SVertex *ioB = fe->vertexB(); Vec3r A = ioA->point3D(); Vec3r B = ioB->point3D(); Vec3r a = ioA->point2D(); Vec3r b = ioB->point2D(); SVertex *svA, *svB; Vec3r newpoint3d,newpoint2d; vector<SVertex*> intersections; real t,T; for(vector<Vec2r>::const_iterator p=iParameters.begin(),pend=iParameters.end(); p!=pend; p++) { T=(*p)[0]; t=(*p)[1]; if((t < 0) || (t > 1)) cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - " << ioB->getId() << endl; // compute the 3D and 2D coordinates for the intersections points: newpoint3d = Vec3r(A + T*(B-A)); newpoint2d = Vec3r(a + t*(b-a)); // create new SVertex: // (we keep B's id) SVertex* newVertex = new SVertex(newpoint3d, ioB->getId()); newVertex->SetPoint2D(newpoint2d); // Add this vertex to the intersections list: intersections.push_back(newVertex); // Add this vertex to this sshape: AddNewVertex(newVertex); } for(vector<SVertex*>::iterator sv=intersections.begin(),svend=intersections.end(); sv!=svend; sv++) { svA = fe->vertexA(); svB = fe->vertexB(); // We split edge AB into AA' and A'B. A' and A'B are created. // AB becomes (address speaking) AA'. B is updated. //-------------------------------------------------- // The edge AB becomes edge AA'. (fe)->SetVertexB((*sv)); // a new edge, A'B is created. FEdge *newEdge; if (fe->getNature() & Nature::ALL_INTERSECTION) { newEdge = new FEdgeIntersection((*sv), svB); FEdgeIntersection * se = dynamic_cast<FEdgeIntersection*>(newEdge); FEdgeIntersection * fes = dynamic_cast<FEdgeIntersection*>(fe); se->SetMaterialIndex(fes->materialIndex()); se->SetFaces(fes->getFace1(), fes->getFace2()); #ifdef DEBUG_INTERSECTION void debugFES(FEdgeIntersection * newEdge); debugFES(se); debugFES(fes); #endif } else if(fe->isSmooth()){ newEdge = new FEdgeSmooth((*sv), svB); FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge); FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe); se->SetMaterialIndex(fes->materialIndex()); }else{ newEdge = new FEdgeSharp((*sv), svB); FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge); FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(fe); se->SetaMaterialIndex(fes->aMaterialIndex()); se->SetbMaterialIndex(fes->bMaterialIndex()); se->SetEdge(fes->edge()); } newEdge->SetNature((fe)->getNature()); // to build a new chain: AddChain(newEdge); // add the new edge to the sshape edges list. AddEdge(newEdge); // add new edge to the list of new edges passed as argument: ioNewEdges.push_back(newEdge); // update edge A'B for the next pointing edge newEdge->SetNextEdge((fe)->nextEdge()); fe->nextEdge()->SetPreviousEdge(newEdge); Id id(fe->getId().getFirst(), fe->getId().getSecond()+1); newEdge->SetId(fe->getId()); fe->SetId(id); // update edge AA' for the next pointing edge //ioEdge->SetNextEdge(newEdge); (fe)->SetNextEdge(NULL); // update vertex pointing edges list: // -- vertex B -- svB->Replace((fe), newEdge); // -- vertex A' -- (*sv)->AddFEdge((fe)); (*sv)->AddFEdge(newEdge); } }
namespace Freestyle { Vec3r SilhouetteGeomEngine::_Viewpoint = Vec3r(0, 0, 0); real SilhouetteGeomEngine::_translation[3] = {0, 0, 0}; real SilhouetteGeomEngine::_modelViewMatrix[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; real SilhouetteGeomEngine::_projectionMatrix[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; real SilhouetteGeomEngine::_transform[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; int SilhouetteGeomEngine::_viewport[4] = {1, 1, 1, 1}; real SilhouetteGeomEngine::_Focal = 0.0; real SilhouetteGeomEngine::_glProjectionMatrix[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; real SilhouetteGeomEngine::_glModelViewMatrix[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; real SilhouetteGeomEngine::_znear = 0.0; real SilhouetteGeomEngine::_zfar = 100.0; bool SilhouetteGeomEngine::_isOrthographicProjection = false; SilhouetteGeomEngine *SilhouetteGeomEngine::_pInstance = NULL; void SilhouetteGeomEngine::setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], const int iViewport[4], real iFocal) { unsigned int i, j; _translation[0] = iModelViewMatrix[3][0]; _translation[1] = iModelViewMatrix[3][1]; _translation[2] = iModelViewMatrix[3][2]; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { _modelViewMatrix[i][j] = iModelViewMatrix[j][i]; _glModelViewMatrix[i][j] = iModelViewMatrix[i][j]; } } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { _projectionMatrix[i][j] = iProjectionMatrix[j][i]; _glProjectionMatrix[i][j] = iProjectionMatrix[i][j]; } } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { _transform[i][j] = 0; for (unsigned int k = 0; k < 4; k++) _transform[i][j] += _projectionMatrix[i][k] * _modelViewMatrix[k][j]; } } for (i = 0; i < 4; i++) { _viewport[i] = iViewport[i]; } _Focal = iFocal; _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0); } void SilhouetteGeomEngine::setFrustum(real iZNear, real iZFar) { _znear = iZNear; _zfar = iZFar; } void SilhouetteGeomEngine::retrieveViewport(int viewport[4]) { memcpy(viewport, _viewport, 4 * sizeof(int)); } void SilhouetteGeomEngine::ProjectSilhouette(vector<SVertex*>& ioVertices) { Vec3r newPoint; vector<SVertex*>::iterator sv, svend; for (sv = ioVertices.begin(), svend = ioVertices.end(); sv != svend; sv++) { GeomUtils::fromWorldToImage((*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); (*sv)->setPoint2D(newPoint); } } void SilhouetteGeomEngine::ProjectSilhouette(SVertex *ioVertex) { Vec3r newPoint; GeomUtils::fromWorldToImage(ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); ioVertex->setPoint2D(newPoint); } real SilhouetteGeomEngine::ImageToWorldParameter(FEdge *fe, real t) { if (_isOrthographicProjection) return t; // we need to compute for each parameter t the corresponding parameter T which gives the intersection in 3D. real T; // suffix w for world, c for camera, r for retina, i for image Vec3r Aw = (fe)->vertexA()->point3D(); Vec3r Bw = (fe)->vertexB()->point3D(); Vec3r Ac, Bc; GeomUtils::fromWorldToCamera(Aw, Ac, _modelViewMatrix); GeomUtils::fromWorldToCamera(Bw, Bc, _modelViewMatrix); Vec3r ABc = Bc - Ac; #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "Ac " << Ac << endl; cout << "Bc " << Bc << endl; cout << "ABc " << ABc << endl; } #endif Vec3r Ai = (fe)->vertexA()->point2D(); Vec3r Bi = (fe)->vertexB()->point2D(); Vec3r Ii = Ai + t * (Bi - Ai); // the intersection point in the 2D image space Vec3r Ir, Ic; GeomUtils::fromImageToRetina(Ii, Ir, _viewport); real alpha, beta, denom; real m11 = _projectionMatrix[0][0]; real m13 = _projectionMatrix[0][2]; real m22 = _projectionMatrix[1][1]; real m23 = _projectionMatrix[1][2]; if (fabs(ABc[0]) > 1.0e-6) { alpha = ABc[2] / ABc[0]; beta = Ac[2] - alpha * Ac[0]; denom = alpha * (Ir[0] + m13) + m11; if (fabs(denom) < 1.0e-6) goto iter; Ic[0] = -beta * (Ir[0] + m13) / denom; #if 0 Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22; Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2]; #endif T = (Ic[0] - Ac[0]) / ABc[0]; } else if (fabs(ABc[1]) > 1.0e-6) { alpha = ABc[2] / ABc[1]; beta = Ac[2] - alpha * Ac[1]; denom = alpha * (Ir[1] + m23) + m22; if (fabs(denom) < 1.0e-6) goto iter; Ic[1] = -beta * (Ir[1] + m23) / denom; #if 0 Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11; Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2]; #endif T = (Ic[1] - Ac[1]) / ABc[1]; } else { iter: bool x_coords, less_than; if (fabs(Bi[0] - Ai[0]) > 1.0e-6) { x_coords = true; less_than = Ai[0] < Bi[0]; } else { x_coords = false; less_than = Ai[1] < Bi[1]; } Vec3r Pc, Pr, Pi; real T_sta = 0.0; real T_end = 1.0; real delta_x, delta_y, dist, dist_threshold = 1.0e-6; int i, max_iters = 100; for (i = 0; i < max_iters; i++) { T = T_sta + 0.5 * (T_end - T_sta); Pc = Ac + T * ABc; GeomUtils::fromCameraToRetina(Pc, Pr, _projectionMatrix); GeomUtils::fromRetinaToImage(Pr, Pi, _viewport); delta_x = Ii[0] - Pi[0]; delta_y = Ii[1] - Pi[1]; dist = sqrt(delta_x * delta_x + delta_y * delta_y); if (dist < dist_threshold) break; if (x_coords) { if (less_than) { if (Pi[0] < Ii[0]) T_sta = T; else T_end = T; } else { if (Pi[0] > Ii[0]) T_sta = T; else T_end = T; } } else { if (less_than) { if (Pi[1] < Ii[1]) T_sta = T; else T_end = T; } else { if (Pi[1] > Ii[1]) T_sta = T; else T_end = T; } } } #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "SilhouetteGeomEngine::ImageToWorldParameter(): #iters = " << i << ", dist = " << dist << "\n"; } #endif if (i == max_iters && G.debug & G_DEBUG_FREESTYLE) { cout << "SilhouetteGeomEngine::ImageToWorldParameter(): reached to max_iters (dist = " << dist << ")\n"; } } return T; } Vec3r SilhouetteGeomEngine::WorldToImage(const Vec3r& M) { Vec3r newPoint; GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport); return newPoint; } Vec3r SilhouetteGeomEngine::CameraToImage(const Vec3r& M) { Vec3r newPoint, p; GeomUtils::fromCameraToRetina(M, p, _projectionMatrix); GeomUtils::fromRetinaToImage(p, newPoint, _viewport); return newPoint; } } /* namespace Freestyle */
void FEdgeXDetector::computeCurvatures(WXVertex *vertex) { // TODO: for some reason, the 'vertex' may have no associated edges // (i.e., WVertex::_EdgeList is empty), which causes a crash due to // a subsequent call of WVertex::_EdgeList.front(). if (vertex->GetEdges().empty()) { if (G.debug & G_DEBUG_FREESTYLE) { printf("Warning: WVertex %d has no associated edges.\n", vertex->GetId()); } return; } // CURVATURE LAYER // store all the curvature datas for each vertex //soc unused - real K1, K2 real cos2theta, sin2theta; Vec3r e1, n, v; // one vertex curvature info : CurvatureInfo *C; float radius = _sphereRadius * _meanEdgeSize; // view independent stuff if (_computeViewIndependent) { C = new CurvatureInfo(); vertex->setCurvatures(C); OGF::NormalCycle ncycle; ncycle.begin(); if (radius > 0) { OGF::compute_curvature_tensor(vertex, radius, ncycle); } else { OGF::compute_curvature_tensor_one_ring(vertex, ncycle); } ncycle.end(); C->K1 = ncycle.kmin(); C->K2 = ncycle.kmax(); C->e1 = ncycle.Kmax(); //ncycle.kmin() * ncycle.Kmax(); C->e2 = ncycle.Kmin(); //ncycle.kmax() * ncycle.Kmin(); real absK1 = fabs(C->K1); _meanK1 += absK1; if (absK1 > _maxK1) _maxK1 = absK1; if (absK1 < _minK1) _minK1 = absK1; } // view dependant C = vertex->curvatures(); if (C == 0) return; // compute radial curvature : n = C->e1 ^ C->e2; if (_orthographicProjection) { v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z()); } else { v = Vec3r(_Viewpoint - vertex->GetVertex()); } C->er = v - (v * n) * n; C->er.normalize(); e1 = C->e1; e1.normalize(); cos2theta = C->er * e1; cos2theta *= cos2theta; sin2theta = 1 - cos2theta; C->Kr = C->K1 * cos2theta + C->K2 * sin2theta; real absKr = fabs(C->Kr); _meanKr += absKr; if (absKr > _maxKr) _maxKr = absKr; if (absKr < _minKr) _minKr = absKr; ++_nPoints; }
FlatFloor::FlatFloor(UInt segmentNum, Vec2r worldPos) : m_segmentNum(segmentNum) { m_pos = Vec3r(worldPos.X, worldPos.Y, -1); }
/*! gts_vertex_principal_directions: * @v: a #WVertex. * @s: a #GtsSurface. * @Kh: mean curvature normal (a #Vec3r). * @Kg: Gaussian curvature (a real). * @e1: first principal curvature direction (direction of largest curvature). * @e2: second principal curvature direction. * * Computes the principal curvature directions at a point given @Kh and @Kg, the mean curvature normal and * Gaussian curvatures at that point, computed with gts_vertex_mean_curvature_normal() and * gts_vertex_gaussian_curvature(), respectively. * * Note that this computation is very approximate and tends to be unstable. Smoothing of the surface or the principal * directions may be necessary to achieve reasonable results. */ void gts_vertex_principal_directions(WVertex *v, Vec3r Kh, real Kg, Vec3r &e1, Vec3r &e2) { Vec3r N; real normKh; Vec3r basis1, basis2, d, eig; real ve2, vdotN; real aterm_da, bterm_da, cterm_da, const_da; real aterm_db, bterm_db, cterm_db, const_db; real a, b, c; real K1, K2; real *weights, *kappas, *d1s, *d2s; int edge_count; real err_e1, err_e2; int e; WVertex::incoming_edge_iterator itE; /* compute unit normal */ normKh = Kh.norm(); if (normKh > 0.0) { Kh.normalize(); } else { /* This vertex is a point of zero mean curvature (flat or saddle point). Compute a normal by averaging * the adjacent triangles */ N[0] = N[1] = N[2] = 0.0; for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) N = Vec3r(N + (*itE)->GetaFace()->GetNormal()); real normN = N.norm(); if (normN <= 0.0) return; N.normalize(); } /* construct a basis from N: */ /* set basis1 to any component not the largest of N */ basis1[0] = basis1[1] = basis1[2] = 0.0; if (fabs (N[0]) > fabs (N[1])) basis1[1] = 1.0; else basis1[0] = 1.0; /* make basis2 orthogonal to N */ basis2 = (N ^ basis1); basis2.normalize(); /* make basis1 orthogonal to N and basis2 */ basis1 = (N ^ basis2); basis1.normalize(); aterm_da = bterm_da = cterm_da = const_da = 0.0; aterm_db = bterm_db = cterm_db = const_db = 0.0; int nb_edges = v->GetEdges().size(); weights = (real *)malloc(sizeof(real) * nb_edges); kappas = (real *)malloc(sizeof(real) * nb_edges); d1s = (real *)malloc(sizeof(real) * nb_edges); d2s = (real *)malloc(sizeof(real) * nb_edges); edge_count = 0; for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) { WOEdge *e; WFace *f1, *f2; real weight, kappa, d1, d2; Vec3r vec_edge; if (!*itE) continue; e = *itE; /* since this vertex passed the tests in gts_vertex_mean_curvature_normal(), this should be true. */ //g_assert(gts_edge_face_number (e, s) == 2); /* identify the two triangles bordering e in s */ f1 = e->GetaFace(); f2 = e->GetbFace(); /* We are solving for the values of the curvature tensor * B = [ a b ; b c ]. * The computations here are from section 5 of [Meyer et al 2002]. * * The first step is to calculate the linear equations governing the values of (a,b,c). These can be computed * by setting the derivatives of the error E to zero (section 5.3). * * Since a + c = norm(Kh), we only compute the linear equations for dE/da and dE/db. (NB: [Meyer et al 2002] * has the equation a + b = norm(Kh), but I'm almost positive this is incorrect). * * Note that the w_ij (defined in section 5.2) are all scaled by (1/8*A_mixed). We drop this uniform scale * factor because the solution of the linear equations doesn't rely on it. * * The terms of the linear equations are xterm_dy with x in {a,b,c} and y in {a,b}. There are also const_dy * terms that are the constant factors in the equations. */ /* find the vector from v along edge e */ vec_edge = Vec3r(-1 * e->GetVec()); ve2 = vec_edge.squareNorm(); vdotN = vec_edge * N; /* section 5.2 - There is a typo in the computation of kappa. The edges should be x_j-x_i. */ kappa = 2.0 * vdotN / ve2; /* section 5.2 */ /* I don't like performing a minimization where some of the weights can be negative (as can be the case * if f1 or f2 are obtuse). To ensure all-positive weights, we check for obtuseness. */ weight = 0.0; if (!triangle_obtuse(v, f1)) { weight += ve2 * cotan(f1->GetNextOEdge(e->twin())->GetbVertex(), e->GetaVertex(), e->GetbVertex()) / 8.0; } else { if (angle_obtuse(v, f1)) { weight += ve2 * f1->getArea() / 4.0; } else { weight += ve2 * f1->getArea() / 8.0; } } if (!triangle_obtuse(v, f2)) { weight += ve2 * cotan (f2->GetNextOEdge(e)->GetbVertex(), e->GetaVertex(), e->GetbVertex()) / 8.0; } else { if (angle_obtuse(v, f2)) { weight += ve2 * f1->getArea() / 4.0; } else { weight += ve2 * f1->getArea() / 8.0; } } /* projection of edge perpendicular to N (section 5.3) */ d[0] = vec_edge[0] - vdotN * N[0]; d[1] = vec_edge[1] - vdotN * N[1]; d[2] = vec_edge[2] - vdotN * N[2]; d.normalize(); /* not explicit in the paper, but necessary. Move d to 2D basis. */ d1 = d * basis1; d2 = d * basis2; /* store off the curvature, direction of edge, and weights for later use */ weights[edge_count] = weight; kappas[edge_count] = kappa; d1s[edge_count] = d1; d2s[edge_count] = d2; edge_count++; /* Finally, update the linear equations */ aterm_da += weight * d1 * d1 * d1 * d1; bterm_da += weight * d1 * d1 * 2 * d1 * d2; cterm_da += weight * d1 * d1 * d2 * d2; const_da += weight * d1 * d1 * (-kappa); aterm_db += weight * d1 * d2 * d1 * d1; bterm_db += weight * d1 * d2 * 2 * d1 * d2; cterm_db += weight * d1 * d2 * d2 * d2; const_db += weight * d1 * d2 * (-kappa); } /* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */ aterm_da -= cterm_da; const_da += cterm_da * normKh; aterm_db -= cterm_db; const_db += cterm_db * normKh; /* check for solvability of the linear system */ if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) && ((const_da != 0.0) || (const_db != 0.0))) { linsolve(aterm_da, bterm_da, -const_da, aterm_db, bterm_db, -const_db, &a, &b); c = normKh - a; eigenvector(a, b, c, eig); } else { /* region of v is planar */ eig[0] = 1.0; eig[1] = 0.0; } /* Although the eigenvectors of B are good estimates of the principal directions, it seems that which one is * attached to which curvature direction is a bit arbitrary. This may be a bug in my implementation, or just * a side-effect of the inaccuracy of B due to the discrete nature of the sampling. * * To overcome this behavior, we'll evaluate which assignment best matches the given eigenvectors by comparing * the curvature estimates computed above and the curvatures calculated from the discrete differential operators. */ gts_vertex_principal_curvatures(0.5 * normKh, Kg, &K1, &K2); err_e1 = err_e2 = 0.0; /* loop through the values previously saved */ for (e = 0; e < edge_count; e++) { real weight, kappa, d1, d2; real temp1, temp2; real delta; weight = weights[e]; kappa = kappas[e]; d1 = d1s[e]; d2 = d2s[e]; temp1 = fabs (eig[0] * d1 + eig[1] * d2); temp1 = temp1 * temp1; temp2 = fabs (eig[1] * d1 - eig[0] * d2); temp2 = temp2 * temp2; /* err_e1 is for K1 associated with e1 */ delta = K1 * temp1 + K2 * temp2 - kappa; err_e1 += weight * delta * delta; /* err_e2 is for K1 associated with e2 */ delta = K2 * temp1 + K1 * temp2 - kappa; err_e2 += weight * delta * delta; } free (weights); free (kappas); free (d1s); free (d2s); /* rotate eig by a right angle if that would decrease the error */ if (err_e2 < err_e1) { real temp = eig[0]; eig[0] = eig[1]; eig[1] = -temp; } e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0]; e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1]; e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2]; e1.normalize(); /* make N,e1,e2 a right handed coordinate sytem */ e2 = N ^ e1; e2.normalize(); }
Key::Key(Vec2r halfExtents, Vec2r worldPos): m_pDoor(nullptr) { m_halfExtents = halfExtents; m_pos = Vec3r(worldPos.X, worldPos.Y, -1); }
void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials, const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, const unsigned *tindices, const unsigned nvertices) { unsigned nDoneVertices = 2; // number of vertices already treated unsigned nTriangle = 0; // number of the triangle currently being treated //int nVertex = 0; // vertex number WShape *currentShape = _current_wshape; // the current shape being built vector<WVertex *> triangleVertices; vector<Vec3r> triangleNormals; vector<Vec2r> triangleTexCoords; vector<bool> triangleFaceEdgeMarks; while (nDoneVertices < nvertices) { //clear the vertices list: triangleVertices.clear(); //Then rebuild it: if (0 == nTriangle % 2) { // if nTriangle is even triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle] / 3]); triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 1] / 3]); triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 2] / 3]); triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]], normals[nindices[nTriangle] + 1], normals[nindices[nTriangle] + 2])); triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 1]], normals[nindices[nTriangle + 1] + 1], normals[nindices[nTriangle + 1] + 2])); triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 2]], normals[nindices[nTriangle + 2] + 1], normals[nindices[nTriangle + 2] + 2])); if (texCoords) { triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]], texCoords[tindices[nTriangle] + 1])); triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 1]], texCoords[tindices[nTriangle + 1] + 1])); triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 2]], texCoords[tindices[nTriangle + 2] + 1])); } } else { // if nTriangle is odd triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle] / 3]); triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 2] / 3]); triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 1] / 3]); triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]], normals[nindices[nTriangle] + 1], normals[nindices[nTriangle] + 2])); triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 2]], normals[nindices[nTriangle + 2] + 1], normals[nindices[nTriangle + 2] + 2])); triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 1]], normals[nindices[nTriangle + 1] + 1], normals[nindices[nTriangle + 1] + 2])); if (texCoords) { triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]], texCoords[tindices[nTriangle] + 1])); triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 2]], texCoords[tindices[nTriangle + 2] + 1])); triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 1]], texCoords[tindices[nTriangle + 1] + 1])); } } triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::FACE_MARK) != 0); triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V1V2) != 0); triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V2V3) != 0); triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V3V1) != 0); if (mindices) { currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, mindices[nTriangle / 3]); } else { currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0); } nDoneVertices++; // with a strip, each triangle is one vertex more nTriangle++; } }
Vec3r BoxGrid::Transform::operator()(const Vec3r& point) const { return Vec3r(point[0], point[1], -point[2]); }
void Grid::insertOccluder(Polygon3r* occluder) { const vector<Vec3r> vertices = occluder->getVertices(); if (vertices.size() == 0) return; // add this occluder to the grid's occluders list addOccluder(occluder); // find the bbox associated to this polygon Vec3r min, max; occluder->getBBox(min, max); // Retrieve the cell x, y, z cordinates associated with these min and max Vec3u imax, imin; getCellCoordinates(max, imax); getCellCoordinates(min, imin); // We are now going to fill in the cells overlapping with the // polygon bbox. // If the polygon is a triangle (most of cases), we also // check for each of these cells if it is overlapping with // the triangle in order to only fill in the ones really overlapping // the triangle. unsigned i, x, y, z; vector<Vec3r>::const_iterator it; Vec3u coord; if (vertices.size() == 3) { // Triangle case Vec3r triverts[3]; i = 0; for(it = vertices.begin(); it != vertices.end(); it++) { triverts[i] = Vec3r(*it); i++; } Vec3r boxmin, boxmax; for (z = imin[2]; z <= imax[2]; z++) for (y = imin[1]; y <= imax[1]; y++) for (x = imin[0]; x <= imax[0]; x++) { coord[0] = x; coord[1] = y; coord[2] = z; // We retrieve the box coordinates of the current cell getCellBox(coord, boxmin, boxmax); // We check whether the triangle and the box ovewrlap: Vec3r boxcenter((boxmin + boxmax) / 2.0); Vec3r boxhalfsize(_cell_size / 2.0); if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) { // We must then create the Cell and add it to the cells list // if it does not exist yet. // We must then add the occluder to the occluders list of this cell. Cell* cell = getCell(coord); if (!cell) { cell = new Cell(boxmin); fillCell(coord, *cell); } cell->addOccluder(occluder); } } } else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox. for (z = imin[2]; z <= imax[2]; z++) for (y = imin[1]; y <= imax[1]; y++) for (x = imin[0]; x <= imax[0]; x++) { coord[0] = x; coord[1] = y; coord[2] = z; Cell* cell = getCell(coord); if (!cell) { Vec3r orig; getCellOrigin(coord, orig); cell = new Cell(orig); fillCell(coord, *cell); } cell->addOccluder(occluder); } } }