bool RArcData::moveReferencePoint(const RVector& referencePoint, const RVector& targetPoint) { bool ret = false; if (referencePoint.equalsFuzzy(center)) { center = targetPoint; ret = true; } else if (referencePoint.equalsFuzzy(getStartPoint())) { moveStartPoint(targetPoint); ret = true; } else if (referencePoint.equalsFuzzy(getEndPoint())) { moveEndPoint(targetPoint); ret = true; } else if (referencePoint.equalsFuzzy(center + RVector(radius, 0)) || referencePoint.equalsFuzzy(center + RVector(0, radius)) || referencePoint.equalsFuzzy(center - RVector(radius, 0)) || referencePoint.equalsFuzzy(center - RVector(0, radius))) { radius = center.getDistanceTo(targetPoint); ret = true; } else if (referencePoint.equalsFuzzy(getMiddlePoint())) { moveMiddlePoint(targetPoint); ret = true; } return ret; }
QList<RVector> RSpline::getMiddlePoints() const { QList<RVector> ret; ret.append(getMiddlePoint()); return ret; }
RS_Vector RS_Line::getNearestPointOnEntity(const RS_Vector& coord, bool onEntity, double* dist, RS_Entity** entity)const { if (entity!=NULL) { *entity = const_cast<RS_Line*>(this); } //std::cout<<"RS_Line::getNearestPointOnEntity():"<<coord<<std::endl; RS_Vector direction = data.endpoint-data.startpoint; RS_Vector vpc=coord-data.startpoint; double a=direction.squared(); if( a < RS_TOLERANCE*RS_TOLERANCE) { //line too short vpc=getMiddlePoint(); }else{ //find projection on line vpc = data.startpoint + direction*RS_Vector::dotP(vpc,direction)/a; if( !isHelpLayer() && onEntity && ! vpc.isInWindowOrdered(minV,maxV) ){ // !( vpc.x>= minV.x && vpc.x <= maxV.x && vpc.y>= minV.y && vpc.y<=maxV.y) ) { //projection point not within range, find the nearest endpoint // std::cout<<"not within window, returning endpoints\n"; return getNearestEndpoint(coord,dist); } } if (dist!=NULL) { *dist = vpc.distanceTo(coord); } return vpc; }
RS_Vector RS_Line::getNearestPointOnEntity(const RS_Vector& coord, bool onEntity, double* dist, RS_Entity** entity)const { if (entity) { *entity = const_cast<RS_Line*>(this); } RS_Vector direction = data.endpoint-data.startpoint; RS_Vector vpc=coord-data.startpoint; double a=direction.squared(); if( a < RS_TOLERANCE2) { //line too short vpc=getMiddlePoint(); }else{ //find projection on line const double t=RS_Vector::dotP(vpc,direction)/a; if( !isConstruction() && onEntity && ( t<=-RS_TOLERANCE || t>=1.+RS_TOLERANCE ) ){ // !( vpc.x>= minV.x && vpc.x <= maxV.x && vpc.y>= minV.y && vpc.y<=maxV.y) ) { //projection point not within range, find the nearest endpoint // std::cout<<"not within window, returning endpoints\n"; return getNearestEndpoint(coord,dist); } vpc = data.startpoint + direction*t; } if (dist) { *dist = vpc.distanceTo(coord); } return vpc; }
QList<RRefPoint> RArcData::getReferencePoints(RS::ProjectionRenderingHint hint) const { Q_UNUSED(hint) QList<RRefPoint> ret; ret.append(RRefPoint(center, RRefPoint::Center)); ret.append(getStartPoint()); ret.append(getEndPoint()); ret.append(RRefPoint(getMiddlePoint(), RRefPoint::Secondary)); QList<RRefPoint> p; p.append(RRefPoint(center + RVector(radius, 0), RRefPoint::Secondary)); p.append(RRefPoint(center + RVector(0, radius), RRefPoint::Secondary)); p.append(RRefPoint(center - RVector(radius, 0), RRefPoint::Secondary)); p.append(RRefPoint(center - RVector(0, radius), RRefPoint::Secondary)); for (int i=0; i<p.size(); i++) { if (RMath::isAngleBetween(center.getAngleTo(p[i]), startAngle, endAngle, reversed)) { ret.append(p[i]); } } return ret; }
RS_Vector RS_Line::getNearestPointOnEntity(const RS_Vector& coord, bool onEntity, double* dist, RS_Entity** entity) const { if (entity) { *entity = const_cast<RS_Line*>(this); } RS_Vector direction {data.endpoint - data.startpoint}; RS_Vector vpc {coord - data.startpoint}; double a {direction.squared()}; if( a < RS_TOLERANCE2) { //line too short vpc = getMiddlePoint(); } else { //find projection on line const double t {RS_Vector::dotP( vpc, direction) / a}; if( !isConstruction() && onEntity && ( t <= -RS_TOLERANCE || t >= 1. + RS_TOLERANCE ) ) { //projection point not within range, find the nearest endpoint return getNearestEndpoint( coord, dist); } vpc = data.startpoint + direction * t; } if (dist) { *dist = vpc.distanceTo( coord); } return vpc; }
/*---------------------------------------------------------------------------------- Author: MaxAshton function: createPoints Description: create the initial points using 4 squares each set perpendiculars to each other ----------------------------------------------------------------------------------*/ void IcoSphereGeometry::createPoints() { // create 12 vertices of a icosahedron float ft = ( 1.0 + sqrt( 5.0 ) ) / 2.0; addVertex( new osg::Vec3f( -1.0f, ft, 0.0f ) ); addVertex( new osg::Vec3f( 1.0f, ft, 0.0f ) ); addVertex( new osg::Vec3f( -1.0f, -ft, 0.0f ) ); addVertex( new osg::Vec3f( 1.0f, -ft, 0.0f ) ); addVertex( new osg::Vec3f( 0.0f, -1.0f, ft ) ); addVertex( new osg::Vec3f( 0.0f, 1.0f, ft ) ); addVertex( new osg::Vec3f( 0.0f, -1.0f, -ft ) ); addVertex( new osg::Vec3f( 0.0f, 1.0f, -ft ) ); addVertex( new osg::Vec3f( ft, 0.0f, -1.0f ) ); addVertex( new osg::Vec3f( ft, 0.0f, 1.0f ) ); addVertex( new osg::Vec3f( -ft, 0.0f, -1.0f ) ); addVertex( new osg::Vec3f( -ft, 0.0f, 1.0f ) ); // 5 faces around point 0 _pvTriangleIndexes->push_back( new osg::Vec3f( 0, 11, 5 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 0, 5, 1 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 0, 1, 7 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 0, 7, 10) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 0, 10, 11 ) ); // 5 adjacent faces _pvTriangleIndexes->push_back( new osg::Vec3f( 1, 5, 9 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 5, 11, 4 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 11, 10, 2 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 10, 7, 6 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 7, 1, 8 ) ); // 5 faces around point 3 _pvTriangleIndexes->push_back( new osg::Vec3f( 3, 9, 4 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 3, 4, 2 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 3, 2, 6 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 3, 6, 8 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 3, 8, 9 ) ); // 5 adjacent faces _pvTriangleIndexes->push_back( new osg::Vec3f( 4, 9, 5 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 2, 4, 11 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 6, 2, 10 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 8, 6, 7 ) ); _pvTriangleIndexes->push_back( new osg::Vec3f( 9, 8, 1 ) ); // refine triangles for ( unsigned int i = 0; i < _uiRecursionLevel; i++ ) { std::vector<osg::Vec3f*>* pvNewFaces = new std::vector<osg::Vec3f*>(); for( std::vector<osg::Vec3f*>::iterator i = _pvTriangleIndexes->begin(); i != _pvTriangleIndexes->end(); i++ ) { // replace triangle by 4 triangles int a = getMiddlePoint( ( *i )->x(), ( *i )->y() ); int b = getMiddlePoint( ( *i )->y() , ( *i )->z() ); int c = getMiddlePoint( ( *i )->z() , ( *i )->x() ); pvNewFaces->push_back( new osg::Vec3f( ( *i )->x(), a, c ) ); pvNewFaces->push_back( new osg::Vec3f( ( *i )->y(), b, a ) ); pvNewFaces->push_back( new osg::Vec3f( ( *i )->z(), c, b ) ); pvNewFaces->push_back( new osg::Vec3f( a, b, c ) ); } _pvTriangleIndexes->empty(); delete _pvTriangleIndexes; _pvTriangleIndexes = 0; _pvTriangleIndexes = pvNewFaces; } }
void ege::icoSphere::create(etk::Hash<ememory::SharedPtr<ege::Material>>& _materials, etk::Hash<FaceIndexing>& _listFaces, std::vector<vec3>& _listVertex, std::vector<vec2>& _listUV, const std::string& _materialName, float _size, int32_t _recursionLevel) { /* 5 o /| / | / | / | 11 / | 9 Z o--------/...---------0 1 | y | 4o o....|......|--o | / | |. 0 | | / | / | .| . |/ | / | . | . | |/ | / | . .| o-------x | / | . / | o--/....|........../--o 10 / | 7o / 8 / . . / / . . / o---------------o 2 | / 3 | / |/ o 6 */ // create 12 vertices of a icosahedron double size = 1.0; double ttt = (1.0 + sqrt(5.0)) / 2.0*size; EGE_ERROR("podition : " << ttt); _listVertex.push_back(vec3(-size, ttt, 0.0).normalize()); // 0 _listVertex.push_back(vec3( size, ttt, 0.0).normalize()); // 1 _listVertex.push_back(vec3(-size, -ttt, 0.0).normalize()); // 2 _listVertex.push_back(vec3( size, -ttt, 0.0).normalize()); // 3 _listVertex.push_back(vec3( 0.0, -1, ttt).normalize()); // 4 _listVertex.push_back(vec3( 0.0, 1, ttt).normalize()); // 5 _listVertex.push_back(vec3( 0.0, -1, -ttt).normalize()); // 6 _listVertex.push_back(vec3( 0.0, 1, -ttt).normalize()); // 7 _listVertex.push_back(vec3( ttt, 0.0, -size).normalize()); // 8 _listVertex.push_back(vec3( ttt, 0.0, size).normalize()); // 9 _listVertex.push_back(vec3(-ttt, 0.0, -size).normalize()); // 10 _listVertex.push_back(vec3(-ttt, 0.0, size).normalize()); // 11 // _listUV ==> TODO : very bad code ... get from viewBox .... _listUV.push_back(vec2(0.0, 0.0 )); // 0 _listUV.push_back(vec2(0.0, 1.0 )); // 1 _listUV.push_back(vec2(1.0, 0.0 )); // 2 for (auto &elem : _listVertex) { EGE_INFO("plop : " << etk::to_string(elem)); } if (_listFaces.exist(_materialName) == false) { FaceIndexing empty; _listFaces.add(_materialName, empty); } { FaceIndexing& tmpElement = _listFaces[_materialName]; // 5 faces around point 0 tmpElement.m_faces.push_back(Face(0,0, 11,1, 5,2)); tmpElement.m_faces.push_back(Face(0,0, 5,1, 1,2)); tmpElement.m_faces.push_back(Face(0,0, 1,1, 7,2)); tmpElement.m_faces.push_back(Face(0,0, 7,1, 10,2)); tmpElement.m_faces.push_back(Face(0,0, 10,1, 11,2)); // 5 adjacent faces tmpElement.m_faces.push_back(Face( 1,0, 5,1, 9,2)); tmpElement.m_faces.push_back(Face( 5,0, 11,1, 4,2)); tmpElement.m_faces.push_back(Face(11,0, 10,1, 2,2)); tmpElement.m_faces.push_back(Face(10,0, 7,1, 6,2)); tmpElement.m_faces.push_back(Face( 7,0, 1,1, 8,2)); // 5 faces around point 3 tmpElement.m_faces.push_back(Face(3,0, 9,1, 4,2)); tmpElement.m_faces.push_back(Face(3,0, 4,1, 2,2)); tmpElement.m_faces.push_back(Face(3,0, 2,1, 6,2)); tmpElement.m_faces.push_back(Face(3,0, 6,1, 8,2)); tmpElement.m_faces.push_back(Face(3,0, 8,1, 9,2)); // 5 adjacent faces tmpElement.m_faces.push_back(Face(4,0, 9,1, 5,2)); tmpElement.m_faces.push_back(Face(2,0, 4,1, 11,2)); tmpElement.m_faces.push_back(Face(6,0, 2,1, 10,2)); tmpElement.m_faces.push_back(Face(8,0, 6,1, 7,2)); tmpElement.m_faces.push_back(Face(9,0, 8,1, 1,2)); // refine triangles for (int i = 0; i < _recursionLevel; i++) { std::vector<Face> listFaces; for (auto &tri : tmpElement.m_faces) { // replace triangle by 4 triangles int32_t a = getMiddlePoint(_listVertex, tri.m_vertex[0], tri.m_vertex[1]); int32_t b = getMiddlePoint(_listVertex, tri.m_vertex[1], tri.m_vertex[2]); int32_t c = getMiddlePoint(_listVertex, tri.m_vertex[2], tri.m_vertex[0]); listFaces.push_back(Face(tri.m_vertex[0],0, a,1, c,2)); listFaces.push_back(Face(tri.m_vertex[1],0, b,1, a,2)); listFaces.push_back(Face(tri.m_vertex[2],0, c,1, b,2)); listFaces.push_back(Face(a,0, b,1, c,2)); } tmpElement.m_faces = listFaces; } // update UV mapping with generic projection: _listUV.clear(); for (auto &vert : _listVertex) { vec2 texturePos; // projection sur le plan XY: float proj = vert.x()*vert.x() + vert.y()*vert.y(); proj = std::sqrt(proj); float angle = M_PI; if (proj != 0.0f) { angle = std::acos(std::abs(vert.x()) / proj); } if (vert.x()<0) { if (vert.y()<0) { angle = -M_PI + angle; } else { angle = M_PI - angle; } } else { if (vert.y()<0) { angle = -angle; } } //EGE_WARNING( "angle = " << (angle/M_PI*180.0f) << " from: vert=" << etk::to_string(vert) << " proj=" << proj ); texturePos.setX(angle/(2.0f*M_PI)+0.5f); angle = std::acos(proj/1.0f); if (vert.z()<0) { angle = -angle; } //EGE_WARNING( "angle = " << (angle/M_PI*180.0f) << " from: vert=" << etk::to_string(vert) << " proj=" << proj ); texturePos.setY(angle/(M_PI)+0.5); texturePos.setMax(vec2(0.0f, 0.0f)); texturePos.setMin(vec2(1.0f, 1.0f)); //EGE_WARNING("texturePosition = " << texturePos); _listUV.push_back(texturePos); } for (auto &face : tmpElement.m_faces) { float y0 = _listVertex[face.m_vertex[0]].y(); float y1 = _listVertex[face.m_vertex[1]].y(); float y2 = _listVertex[face.m_vertex[2]].y(); face.m_uv[0] = face.m_vertex[0]; face.m_uv[1] = face.m_vertex[1]; face.m_uv[2] = face.m_vertex[2]; // mauvaus coter ... if ( _listVertex[face.m_vertex[0]].x() < 0 || _listVertex[face.m_vertex[1]].x() < 0 || _listVertex[face.m_vertex[2]].x() < 0) { if (y0 < 0) { if (y1 < 0) { if (y2 >= 0) { face.m_uv[2] = addUV(_listUV, face.m_vertex[2], -1.0f); } } else { if (y2 < 0) { face.m_uv[1] = addUV(_listUV, face.m_vertex[1], -1.0f);; } else { face.m_uv[0] = addUV(_listUV, face.m_vertex[0], 1.0f);; } } } else { if (y1 < 0) { if (y2 < 0) { face.m_uv[0] = addUV(_listUV, face.m_vertex[0], -1.0f); } else { face.m_uv[1] = addUV(_listUV, face.m_vertex[1], 1.0f); } } else { if (y2 < 0) { face.m_uv[2] = addUV(_listUV, face.m_vertex[2], 1.0f); } } } } } for (auto &vert : _listVertex) { vert *=_size; } } }
void IcoSphere::create(int recursionLevel) { vertices.clear(); lineIndices.clear(); triangleIndices.clear(); faces.clear(); middlePointIndexCache.clear(); index = 0; float t = (1.0f + Ogre::Math::Sqrt(5.0f)) / 2.0f; addVertex(Ogre::Vector3(-1.0f, t, 0.0f)); addVertex(Ogre::Vector3( 1.0f, t, 0.0f)); addVertex(Ogre::Vector3(-1.0f, -t, 0.0f)); addVertex(Ogre::Vector3( 1.0f, -t, 0.0f)); addVertex(Ogre::Vector3( 0.0f, -1.0f, t)); addVertex(Ogre::Vector3( 0.0f, 1.0f, t)); addVertex(Ogre::Vector3( 0.0f, -1.0f, -t)); addVertex(Ogre::Vector3( 0.0f, 1.0f, -t)); addVertex(Ogre::Vector3( t, 0.0f, -1.0f)); addVertex(Ogre::Vector3( t, 0.0f, 1.0f)); addVertex(Ogre::Vector3(-t, 0.0f, -1.0f)); addVertex(Ogre::Vector3(-t, 0.0f, 1.0f)); addFace(0, 11, 5); addFace(0, 5, 1); addFace(0, 1, 7); addFace(0, 7, 10); addFace(0, 10, 11); addFace(1, 5, 9); addFace(5, 11, 4); addFace(11, 10, 2); addFace(10, 7, 6); addFace(7, 1, 8); addFace(3, 9, 4); addFace(3, 4, 2); addFace(3, 2, 6); addFace(3, 6, 8); addFace(3, 8, 9); addFace(4, 9, 5); addFace(2, 4, 11); addFace(6, 2, 10); addFace(8, 6, 7); addFace(9, 8, 1); addLineIndices(1, 0); addLineIndices(1, 5); addLineIndices(1, 7); addLineIndices(1, 8); addLineIndices(1, 9); addLineIndices(2, 3); addLineIndices(2, 4); addLineIndices(2, 6); addLineIndices(2, 10); addLineIndices(2, 11); addLineIndices(0, 5); addLineIndices(5, 9); addLineIndices(9, 8); addLineIndices(8, 7); addLineIndices(7, 0); addLineIndices(10, 11); addLineIndices(11, 4); addLineIndices(4, 3); addLineIndices(3, 6); addLineIndices(6, 10); addLineIndices(0, 11); addLineIndices(11, 5); addLineIndices(5, 4); addLineIndices(4, 9); addLineIndices(9, 3); addLineIndices(3, 8); addLineIndices(8, 6); addLineIndices(6, 7); addLineIndices(7, 10); addLineIndices(10, 0); for (int i = 0; i < recursionLevel; i++) { std::list<TriangleIndices> faces2; for (std::list<TriangleIndices>::iterator j = faces.begin(); j != faces.end(); j++) { TriangleIndices f = *j; int a = getMiddlePoint(f.v1, f.v2); int b = getMiddlePoint(f.v2, f.v3); int c = getMiddlePoint(f.v3, f.v1); removeLineIndices(f.v1, f.v2); removeLineIndices(f.v2, f.v3); removeLineIndices(f.v3, f.v1); faces2.push_back(TriangleIndices(f.v1, a, c)); faces2.push_back(TriangleIndices(f.v2, b, a)); faces2.push_back(TriangleIndices(f.v3, c, b)); faces2.push_back(TriangleIndices(a, b, c)); addTriangleLines(f.v1, a, c); addTriangleLines(f.v2, b, a); addTriangleLines(f.v3, c, b); } faces = faces2; } }
void generate() { // create 12 vertices of a icosahedron double t = (1 + std::sqrt(5)) / 2; vertexList_.push_back(utymap::meshing::Vector3(-1, t, 0).normalized()); vertexList_.push_back(utymap::meshing::Vector3(1, t, 0).normalized()); vertexList_.push_back(utymap::meshing::Vector3(-1, -t, 0).normalized()); vertexList_.push_back(utymap::meshing::Vector3(1, -t, 0).normalized()); vertexList_.push_back(utymap::meshing::Vector3(0, -1, t).normalized()); vertexList_.push_back(utymap::meshing::Vector3(0, 1, t).normalized()); vertexList_.push_back(utymap::meshing::Vector3(0., -1, -t).normalized()); vertexList_.push_back(utymap::meshing::Vector3(0, 1, -t).normalized()); vertexList_.push_back(utymap::meshing::Vector3(t, 0, -1).normalized()); vertexList_.push_back(utymap::meshing::Vector3(t, 0, 1).normalized()); vertexList_.push_back(utymap::meshing::Vector3(-t, 0, -1).normalized()); vertexList_.push_back(utymap::meshing::Vector3(-t, 0, 1).normalized()); // create 20 triangles of the icosahedron std::vector<TriangleIndices> faces; // 5 faces around point 0 faces.push_back(TriangleIndices(0, 11, 5)); faces.push_back(TriangleIndices(0, 5, 1)); faces.push_back(TriangleIndices(0, 1, 7)); faces.push_back(TriangleIndices(0, 7, 10)); faces.push_back(TriangleIndices(0, 10, 11)); // 5 adjacent faces faces.push_back(TriangleIndices(1, 5, 9)); faces.push_back(TriangleIndices(5, 11, 4)); if (!isSemiSphere_) faces.push_back(TriangleIndices(11, 10, 2)); faces.push_back(TriangleIndices(10, 7, 6)); faces.push_back(TriangleIndices(7, 1, 8)); // 5 faces around point 3 if (!isSemiSphere_) { faces.push_back(TriangleIndices(3, 9, 4)); faces.push_back(TriangleIndices(3, 4, 2)); faces.push_back(TriangleIndices(3, 2, 6)); faces.push_back(TriangleIndices(3, 6, 8)); faces.push_back(TriangleIndices(3, 8, 9)); } // 5 adjacent faces faces.push_back(TriangleIndices(4, 9, 5)); if (!isSemiSphere_) { faces.push_back(TriangleIndices(2, 4, 11)); faces.push_back(TriangleIndices(6, 2, 10)); } faces.push_back(TriangleIndices(8, 6, 7)); faces.push_back(TriangleIndices(9, 8, 1)); // refine triangles for (int i = 0; i < recursionLevel_; i++) { std::vector<TriangleIndices> faces2; for (const auto& tri : faces) { // replace triangle by 4 triangles auto a = getMiddlePoint(tri.V1, tri.V2); auto b = getMiddlePoint(tri.V2, tri.V3); auto c = getMiddlePoint(tri.V3, tri.V1); faces2.push_back(TriangleIndices(tri.V1, a, c)); faces2.push_back(TriangleIndices(tri.V2, b, a)); faces2.push_back(TriangleIndices(tri.V3, c, b)); faces2.push_back(TriangleIndices(a, b, c)); } faces = faces2; } generateMesh(faces); // clear state to allow reusage middlePointIndexCache_.clear(); vertexList_.clear(); }
void generateIcoSphere(std::size_t recursion, std::vector<glm::vec3> &vertex, std::vector<unsigned int> &indices) { idxHash_t middlePoints; std::size_t currentIdx = 0; // create 12 vertices of a icosahedron const float t = (1.0f + (float)std::sqrt(5.0f)) / 2.0f; vertex = { glm::normalize(glm::vec3(-1, t, 0)), glm::normalize(glm::vec3(1, t, 0)), glm::normalize(glm::vec3(-1, -t, 0)), glm::normalize(glm::vec3(1, -t, 0)), glm::normalize(glm::vec3(0, -1, t)), glm::normalize(glm::vec3(0, 1, t)), glm::normalize(glm::vec3(0, -1, -t)), glm::normalize(glm::vec3(0, 1, -t)), glm::normalize(glm::vec3(t, 0, -1)), glm::normalize(glm::vec3(t, 0, 1)), glm::normalize(glm::vec3(-t, 0, -1)), glm::normalize(glm::vec3(-t, 0, 1)) }; indices = { 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 }; // refine triangles for (int i = 0; i < recursion; i++) { std::vector<glm::uvec3> idTab2; for (int i = 0; i < indices.size(); i += 3) { // replace triangle by 4 triangles uint32_t a = static_cast<uint32_t>(getMiddlePoint(vertex, middlePoints, indices[i + 0], indices[i + 1])); uint32_t b = static_cast<uint32_t>(getMiddlePoint(vertex, middlePoints, indices[i + 1], indices[i + 2])); uint32_t c = static_cast<uint32_t>(getMiddlePoint(vertex, middlePoints, indices[i + 2], indices[i + 0])); idTab2.push_back(glm::u32vec3(indices[i + 0], a, c)); idTab2.push_back(glm::u32vec3(indices[i + 1], b, a)); idTab2.push_back(glm::u32vec3(indices[i + 2], c, b)); idTab2.push_back(glm::u32vec3(a, b, c)); } indices.resize(idTab2.size() * 3); memcpy(indices.data(), idTab2.data(), idTab2.size() * 3 * sizeof(unsigned int)); } }
Model* Primative::getSphere(glm::vec3 color, float recursionLevel){ std::vector<glm::vec3> vertices; std::vector<unsigned int> indices; // create 12 vertices of a icosahedron float t = (1.0 + sqrtf(5.0)) / 2.0; addVertex(vertices, glm::vec3(-1, t, 0)); addVertex(vertices, glm::vec3( 1, t, 0)); addVertex(vertices, glm::vec3(-1, -t, 0)); addVertex(vertices, glm::vec3( 1, -t, 0)); addVertex(vertices, glm::vec3( 0, -1, t)); addVertex(vertices, glm::vec3( 0, 1, t)); addVertex(vertices, glm::vec3( 0, -1, -t)); addVertex(vertices, glm::vec3( 0, 1, -t)); addVertex(vertices, glm::vec3( t, 0, -1)); addVertex(vertices, glm::vec3( t, 0, 1)); addVertex(vertices, glm::vec3(-t, 0, -1)); addVertex(vertices, glm::vec3(-t, 0, 1)); // 5 faces around point 0 indices.push_back(0); indices.push_back(11); indices.push_back(5); indices.push_back(0); indices.push_back(5); indices.push_back(1); indices.push_back(0); indices.push_back(1); indices.push_back(7); indices.push_back(0); indices.push_back(7); indices.push_back(10); indices.push_back(0); indices.push_back(10); indices.push_back(11); // 5 adjacent faces indices.push_back(1); indices.push_back(5); indices.push_back(9); indices.push_back(5); indices.push_back(11); indices.push_back(4); indices.push_back(11); indices.push_back(10); indices.push_back(2); indices.push_back(10); indices.push_back(7); indices.push_back(6); indices.push_back(7); indices.push_back(1); indices.push_back(8); // 5 faces around point 3 indices.push_back(3); indices.push_back(9); indices.push_back(4); indices.push_back(3); indices.push_back(4); indices.push_back(2); indices.push_back(3); indices.push_back(2); indices.push_back(6); indices.push_back(3); indices.push_back(6); indices.push_back(8); indices.push_back(3); indices.push_back(8); indices.push_back(9); // 5 adjacent faces indices.push_back(4); indices.push_back(9); indices.push_back(5); indices.push_back(2); indices.push_back(4); indices.push_back(11); indices.push_back(6); indices.push_back(2); indices.push_back(10); indices.push_back(8); indices.push_back(6); indices.push_back(7); indices.push_back(9); indices.push_back(8); indices.push_back(1); // refine triangles for (int j = 0; j < recursionLevel; j++) { std::vector<unsigned int> newIndices; for(int i=0; (i+2)<indices.size();i+=3) { // replace triangle by 4 triangles unsigned int a = getMiddlePoint(vertices, indices[i], indices[i+1]); unsigned int b = getMiddlePoint(vertices,indices[i+1], indices[i+2]); unsigned int c = getMiddlePoint(vertices,indices[i+2], indices[i]); newIndices.push_back(indices[i]); newIndices.push_back(a); newIndices.push_back(c); newIndices.push_back(indices[i+1]); newIndices.push_back(b); newIndices.push_back(a); newIndices.push_back(indices[i+2]); newIndices.push_back(c); newIndices.push_back(b); newIndices.push_back(a); newIndices.push_back(b); newIndices.push_back(c); } indices = newIndices; } std::vector<glm::vec3> colors(vertices.size(),color); Model *m = new Model(vertices, vertices, colors, indices); middlePointIndexCache.clear(); return m; };
// Initialization code void init() { // Initializes the glew library glewInit(); // Enables the depth test, which you will want in most cases. You can disable this in the render loop if you need to. glEnable(GL_DEPTH_TEST); // An element array, which determines which of the vertices to display in what order. This is sometimes known as an index array. GLuint elements[] = { 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 }; // These are the indices for an icosahedron. for (int i = 0; i < 60; i++) { theElements.push_back(elements[i]); } // Formula for creating the 12 vertices of an icosahedron. double t = (1.0 + sqrt(5.0)) / 2.0; // Create an std::vector and put our vertices into it. These are just hardcoded values here defined once. // These are the vertices for an icosahedron. vertices.push_back(VertexFormat(glm::vec3(-1.0, t, 0.0), glm::vec4(1.0, 0.0, 0.0, 1.0))); //red vertices.push_back(VertexFormat(glm::vec3(1.0, t, 0.0), glm::vec4(1.0, 0.0, 0.0, 1.0))); //red vertices.push_back(VertexFormat(glm::vec3(-1.0, -t, 0.0), glm::vec4(1.0, 0.0, 1.0, 1.0))); //yellow vertices.push_back(VertexFormat(glm::vec3(1.0, -t, 0.0), glm::vec4(1.0, 0.0, 1.0, 1.0))); //yellow vertices.push_back(VertexFormat(glm::vec3(0.0, -1.0, t), glm::vec4(0.0, 1.0, 1.0, 1.0))); //cyan vertices.push_back(VertexFormat(glm::vec3(0.0, 1.0, t), glm::vec4(0.0, 1.0, 1.0, 1.0))); //cyan vertices.push_back(VertexFormat(glm::vec3(-0.0, -1.0, -t), glm::vec4(0.0, 1.0, 0.0, 1.0))); //blue vertices.push_back(VertexFormat(glm::vec3(-0.0, 1.0, -t), glm::vec4(0.0, 1.0, 0.0, 1.0))); //blue vertices.push_back(VertexFormat(glm::vec3(t, 0.0, -1.0), glm::vec4(0.0, 1.0, 1.0, 1.0))); //cyan vertices.push_back(VertexFormat(glm::vec3(t, 0.0, 1.0), glm::vec4(0.0, 1.0, 1.0, 1.0))); //cyan vertices.push_back(VertexFormat(glm::vec3(-t, 0.0, -1.0), glm::vec4(0.0, 1.0, 0.0, 1.0))); //blue vertices.push_back(VertexFormat(glm::vec3(-t, 0.0, 1.0), glm::vec4(0.0, 1.0, 0.0, 1.0))); //blue for (int i = 0; i < vertices.size(); i++) { double length = sqrt(vertices[i].position.x * vertices[i].position.x + vertices[i].position.y * vertices[i].position.y + vertices[i].position.z * vertices[i].position.z); vertices[i] = VertexFormat(glm::vec3(vertices[i].position.x / length, vertices[i].position.y / length, vertices[i].position.z / length), glm::vec4(((float)(rand() % 100)) / 99.0f, ((float)(rand() % 100)) / 99.0f, ((float)(rand() % 100)) / 99.0f, 1.0f)); // Normalize the vertices so they all lie on the outer sphere surrounding the icosahedron. } const int NUM_REVISIONS = 5; for (int i = 0; i < NUM_REVISIONS; i++) { std::vector<VertexFormat> vertices2; std::vector<GLuint> theElements2; for (int j = 0; j < theElements.size(); j += 3) { unsigned int a = getMiddlePoint(theElements[j], theElements[j + 1]); unsigned int b = getMiddlePoint(theElements[j + 1], theElements[j + 2]); unsigned int c = getMiddlePoint(theElements[j + 2], theElements[j]); vertices2.push_back(vertices[theElements[j]]); theElements2.push_back(j * 2); vertices2.push_back(vertices[a]); theElements2.push_back((j * 2) + 1); vertices2.push_back(vertices[c]); theElements2.push_back((j * 2) + 2); vertices2.push_back(vertices[theElements[j + 1]]); theElements2.push_back((j * 2) + 3); vertices2.push_back(vertices[b]); theElements2.push_back((j * 2) + 4); //vertices2.push_back(vertices[a]); theElements2.push_back((j * 2) + 1); vertices2.push_back(vertices[theElements[j + 2]]); theElements2.push_back((j * 2) + 5); //vertices2.push_back(vertices[c]); theElements2.push_back((j * 2) + 2); //vertices2.push_back(vertices[b]); theElements2.push_back((j * 2) + 4); //vertices2.push_back(vertices[a]); theElements2.push_back((j * 2) + 1); //vertices2.push_back(vertices[b]); theElements2.push_back((j * 2) + 4); //vertices2.push_back(vertices[c]); theElements2.push_back((j * 2) + 2); } vertices = vertices2; theElements = theElements2; } // Create our icosphere model from the calculated data. icosphere = new Model(vertices.size(), vertices.data(), theElements.size(), theElements.data()); // Create two GameObjects based off of the icosphere model (note that they are both holding pointers to the icosphere, not actual copies of the icosphere vertex data). obj1 = new GameObject(icosphere); // Set beginning properties of GameObjects. obj1->SetVelocity(glm::vec3(0, 0.0f, 0.0f)); // The first object doesn't move. obj1->SetPosition(glm::vec3(0.0f, 0.0f, 0.0f)); obj1->SetScale(glm::vec3(0.90f, 0.90f, 0.90f)); // Read in the shader code from a file. std::string vertShader = readShader("VertexShader.glsl"); std::string fragShader = readShader("FragmentShader.glsl"); // createShader consolidates all of the shader compilation code vertex_shader = createShader(vertShader, GL_VERTEX_SHADER); fragment_shader = createShader(fragShader, GL_FRAGMENT_SHADER); // A shader is a program that runs on your GPU instead of your CPU. In this sense, OpenGL refers to your groups of shaders as "programs". // Using glCreateProgram creates a shader program and returns a GLuint reference to it. program = glCreateProgram(); glAttachShader(program, vertex_shader); // This attaches our vertex shader to our program. glAttachShader(program, fragment_shader); // This attaches our fragment shader to our program. // This links the program, using the vertex and fragment shaders to create executables to run on the GPU. glLinkProgram(program); // End of shader and program creation // This gets us a reference to the uniform variable in the vertex shader, which is called "MVP". // We're using this variable as a 4x4 transformation matrix // Only 2 parameters required: A reference to the shader program and the name of the uniform variable within the shader code. uniMVP = glGetUniformLocation(program, "MVP"); // Creates the view matrix using glm::lookAt. // First parameter is camera position, second parameter is point to be centered on-screen, and the third paramter is the up axis. view = glm::lookAt( glm::vec3(0.0f, 0.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); // Creates a projection matrix using glm::perspective. // First parameter is the vertical FoV (Field of View), second paramter is the aspect ratio, 3rd parameter is the near clipping plane, 4th parameter is the far clipping plane. proj = glm::perspective(45.0f, 800.0f / 600.0f, 0.1f, 100.0f); // Allows us to make one less calculation per frame, as long as we don't update the projection and view matrices every frame. PV = proj * view; // Create your MVP matrices based on the objects' transforms. MVP = PV * *obj1->GetTransform(); // Calculate the Axis-Aligned Bounding Box for your object. obj1->CalculateAABB(); // This is not necessary, but I prefer to handle my vertices in the clockwise order. glFrontFace defines which face of the triangles you're drawing is the front. // Essentially, if you draw your vertices in counter-clockwise order, by default (in OpenGL) the front face will be facing you/the screen. If you draw them clockwise, the front face // will face away from you. By passing in GL_CW to this function, we are saying the opposite, and now the front face will face you if you draw in the clockwise order. // If you don't use this, just reverse the order of the vertices in your array when you define them so that you draw the points in a counter-clockwise order. glFrontFace(GL_CW); // This is also not necessary, but more efficient and is generally good practice. By default, OpenGL will render both sides of a triangle that you draw. By enabling GL_CULL_FACE, // we are telling OpenGL to only render the front face. This means that if you rotated the triangle over the X-axis, you wouldn't see the other side of the triangle as it rotated. glEnable(GL_CULL_FACE); // Determines the interpretation of polygons for rasterization. The first parameter, face, determines which polygons the mode applies to. // The face can be either GL_FRONT, GL_BACK, or GL_FRONT_AND_BACK // The mode determines how the polygons will be rasterized. GL_POINT will draw points at each vertex, GL_LINE will draw lines between the vertices, and // GL_FILL will fill the area inside those lines. glPolygonMode(GL_FRONT, GL_FILL); }