// Add an edge from node1 to node2, and from node2 to node1, with // the given cost. If the cost is < 0, throw a string exception. void Graph::addEdge(int node1, int node2, double cost) { if (cost < 0) { throw std::string("error: cost is < 0"); } if (getCost(node1, node2) == -1.0) { // no edge exists yet, add them Edge edge1(cost, node2); Edge edge2(cost, node1); adjList[node1].edgeList.push_back(edge1); adjList[node2].edgeList.push_back(edge2); } else { // this edge already exists, just update its value auto iterator = std::find_if(std::begin(adjList[node1].edgeList), std::end(adjList[node1].edgeList), [&] (const Edge &edge) { return edge.dest == node2; }); iterator->dest = node2; iterator = std::find_if(std::begin(adjList[node2].edgeList), std::end(adjList[node2].edgeList), [&] (const Edge &edge) { return edge.dest == node1; }); iterator->dest = node1; } }
bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ) { const btVector3* p1 = &vertices[0]; const btVector3* p2 = &vertices[1]; const btVector3* p3 = &vertices[2]; btVector3 edge1( *p2 - *p1 ); btVector3 edge2( *p3 - *p2 ); btVector3 edge3( *p1 - *p3 ); btVector3 p1_to_p( *p - *p1 ); btVector3 p2_to_p( *p - *p2 ); btVector3 p3_to_p( *p - *p3 ); btVector3 edge1_normal( edge1.cross(normal)); btVector3 edge2_normal( edge2.cross(normal)); btVector3 edge3_normal( edge3.cross(normal)); btScalar r1, r2, r3; r1 = edge1_normal.dot( p1_to_p ); r2 = edge2_normal.dot( p2_to_p ); r3 = edge3_normal.dot( p3_to_p ); if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) || ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) ) return true; return false; }
float Ray::HitDistance(const Vector3& v0, const Vector3& v1, const Vector3& v2, Vector3* outNormal) const { // Based on Fast, Minimum Storage Ray/Triangle Intersection by Möller & Trumbore // http://www.graphics.cornell.edu/pubs/1997/MT97.pdf // Calculate edge vectors Vector3 edge1(v1 - v0); Vector3 edge2(v2 - v0); // Calculate determinant & check backfacing Vector3 p(direction_.CrossProduct(edge2)); float det = edge1.DotProduct(p); if (det >= M_EPSILON) { // Calculate u & v parameters and test Vector3 t(origin_ - v0); float u = t.DotProduct(p); if (u >= 0.0f && u <= det) { Vector3 q(t.CrossProduct(edge1)); float v = direction_.DotProduct(q); if (v >= 0.0f && u + v <= det) { // There is an intersection, so calculate distance & optional normal if (outNormal) *outNormal = edge1.CrossProduct(edge2); return edge2.DotProduct(q) / det; } } } return M_INFINITY; }
void HFaceFormula::calcFaceNormal(HVertex v1, HVertex v2, HVertex v3, HNormal &n) { HNormal edge1(v1 - v2), edge2(v2 - v3); n = edge1 ^ edge2; // cross product }
//三角形v0,v1,v2 //判断点v是不是在三角形上只需要知道 O+ Dt = (1 - u - v)V0 + uV1 + vV2 //详细讲解参照:http://www.cnblogs.com/graphics/archive/2010/08/09/1795348.html float ORay::HitDistance(const OVector3& v0, const OVector3& v1, const OVector3& v2, OVector3* outNormal) const { // Based on Fast, Minimum Storage ORay/Triangle Intersection by M鰈ler & Trumbore // http://www.graphics.cornell.edu/pubs/1997/MT97.pdf // Calculate edge vectors OVector3 edge1(v1 - v0); OVector3 edge2(v2 - v0); // Calculate determinant & check backfacing OVector3 p( Vec3_CrossProduct( m_direction, edge2)); float det = Vec3_Dotf( edge1, p ); if (det >= EPSILON) { // Calculate u & v parameters and test OVector3 t(m_origin - v0); float u = Vec3_Dotf(t, p); if (u >= 0.0f && u <= det) { OVector3 q(Vec3_CrossProduct(t, edge1)); float v = Vec3_Dotf( m_direction, q ); if (v >= 0.0f && u + v <= det) { // There is an intersection, so calculate distance & optional normal if (outNormal) *outNormal = Vec3_CrossProduct(edge1, edge2); return Vec3_Dotf(edge2, q) / det; } } } return INFINITY; }
Graph::Graph(ifstream& file,float prime_weight) { vector<pair<float, float>> vertexs; int i = 0; //id string name; //city name float lat, lon; //latitude & longitude float weight; //weight = GDP * population bool prime; //whether it is a prime city int flag = file.is_open(); string line; int hz, nj; while (getline(file,line)) { stringstream ss; ss << line; ss >> name >> lat >> lon >> weight; pair<float, float> v(lat, lon); vertexs.push_back(v); if (weight > prime_weight) prime = true; else prime = false; City c(i,name, v, weight,prime); city.push_back(c); //find hangzhou and nanjing if (name == "杭州市") hz = i; if (name == "南京市") nj = i; i++; } //construct distances set //dists[{i,j}] means distance between city with id i and city with id j for (unsigned i = 0; i < vertexs.size(); ++i) { for (unsigned j = 0; j < vertexs.size(); ++j) { pair<int, int> edge(i, j); dists[edge] = dist(vertexs[i], vertexs[j]); } } express[{hz, nj}] = 1; //the amount of express from hz to nj is one car for (unsigned i = 0; i < vertexs.size(); ++i) { for (unsigned j = 0; j < vertexs.size(); ++j) { if (i == j) continue; pair<int, int> edge1(i, j); pair<int, int> edge2(j, i); express[edge1] = city[i].weight * city[j].weight / (city[hz].weight * city[nj].weight); express[edge2] = city[i].weight * city[j].weight / (city[hz].weight * city[nj].weight); } } }
bool PolygonLine :: intersects(Element *element) { printf("Warning: entering PolygonLine :: intersects(Element *element).\n"); #ifdef __BOOST_MODULE if ( !boundingBoxIntersects(element) ) { return false; } double distTol = 1.0e-9; int numSeg = this->giveNrVertices() - 1; // Loop over the crack segments and test each segment for // overlap with the element for ( int segId = 1; segId <= numSeg; segId++ ) { if ( element->giveGeometryType() == EGT_triangle_1 ) { // Crack segment bPoint2 crackP1( this->giveVertex ( segId )->at(1), this->giveVertex ( segId )->at(2) ); bPoint2 crackP2( this->giveVertex ( segId + 1 )->at(1), this->giveVertex ( segId + 1 )->at(2) ); bSeg2 crackSeg(crackP1, crackP2); // Triangle vertices bPoint2 x1( element->giveNode ( 1 )->giveCoordinate(1), element->giveNode ( 1 )->giveCoordinate(2) ); bPoint2 x2( element->giveNode ( 2 )->giveCoordinate(1), element->giveNode ( 2 )->giveCoordinate(2) ); bPoint2 x3( element->giveNode ( 3 )->giveCoordinate(1), element->giveNode ( 3 )->giveCoordinate(2) ); bSeg2 edge1(x1, x2); bSeg2 edge2(x2, x3); bSeg2 edge3(x3, x1); double d1 = bDist(crackSeg, edge1); if ( d1 < distTol ) { return true; } double d2 = bDist(crackSeg, edge2); if ( d2 < distTol ) { return true; } double d3 = bDist(crackSeg, edge3); if ( d3 < distTol ) { return true; } } } #endif return false; }
float HFaceFormula::calcTriangleFaceArea(HVertex &_v1, HVertex &_v2, HVertex &_v3) { ChapillVec3<float> v1(_v1.x, _v1.y, _v1.z), v2(_v2.x, _v2.y, _v2.z), v3(_v3.x, _v3.y, _v3.z); ChapillVec3<float> edge1(v1 - v2), edge2(v2 - v3); ChapillVec3<float> normal = edge1 ^ edge2; // cross product return normal.Length() / 2; }
Cloth::Cloth(vec3Array& vertices, std::vector<unsigned int> &indices, const scalarType edgeKs, const scalarType edgeKd, const scalarType bendKs, const scalarType bendKd) : mVertices(vertices), mIndices(indices) { std::map<clothEdge, clothPair> mBendPairs; for (int i = 0; i < indices.size(); i += 3){ clothSpring s; s.kd = edgeKd; s.ks = edgeKs; s.type = EDGE; // Edge 1 s.p1 = indices[i]; s.p2 = indices[i + 1]; if (mBendPairs.find(clothEdge(s.p1, s.p2)) == mBendPairs.end()){ s.restLen = glm::length(vertices[s.p1] - vertices[s.p2]); mSprings.push_back(s); } // Edge 2 s.p1 = indices[i + 1]; s.p2 = indices[i + 2]; if (mBendPairs.find(clothEdge(s.p1, s.p2)) == mBendPairs.end()){ s.restLen = glm::length(vertices[s.p1] - vertices[s.p2]); mSprings.push_back(s); } // Edge 3 s.p1 = indices[i + 2]; s.p2 = indices[i]; if (mBendPairs.find(clothEdge(s.p1, s.p2)) == mBendPairs.end()){ s.restLen = glm::length(vertices[s.p1] - vertices[s.p2]); mSprings.push_back(s); } clothEdge edge1(indices[i], indices[i + 1]); mBendPairs[edge1].add(indices[i + 2]); clothEdge edge2(indices[i + 1], indices[i + 2]); mBendPairs[edge2].add(indices[i]); clothEdge edge3(indices[i + 2], indices[i]); mBendPairs[edge1].add(indices[i + 1]); } std::map<clothEdge, clothPair>::iterator iter; for (iter = mBendPairs.begin(); iter != mBendPairs.end(); iter++){ if (iter->second.isValid()){ clothSpring s; s.kd = bendKd; s.ks = bendKs; s.type = BEND; s.p1 = iter->second.p1; s.p2 = iter->second.p2; s.restLen = glm::length(vertices[s.p1] - vertices[s.p2]); mSprings.push_back(s); } } }
void HFaceFormula::calcTriangleFaceFormula(HVertex _v1, HVertex _v2, HVertex _v3) { HNormal edge1(_v1 - _v2), edge2(_v2 - _v3); HNormal normal = edge1 ^ edge2; // cross product normal.Normalize(); a = normal.x; b = normal.y; c = normal.z; d = - (a * _v1.x + b * _v1.y + c * _v1.z); }
/** * Break edge into several straight line * */ void Edge::breakEdge() { cv::Point p0; // = contours[0]; cv::Point pend; // = contours[contours.size() - 1]; if (listOfPoints.size() > 0) { p0 = listOfPoints.at(0); pend = listOfPoints.at(listOfPoints.size() - 1); if (listOfPoints.size() > 2) { Line line(p0, pend); double distance = 0; double maxDistance = 0; // ?????????????????? double imax = 0; for (size_t i = 1; i < listOfPoints.size()-1; i++) { cv::Point pointi = listOfPoints.at(i); distance = abs(line.perpendicularDistance(pointi)); if (distance > maxDistance) { maxDistance = distance; imax = i; } } if (maxDistance > 3) { vector<cv::Point> part1(this->listOfPoints.begin(), this->listOfPoints.begin() + imax + 1); vector<cv::Point> part2(this->listOfPoints.begin() + imax, this->listOfPoints.end()); Edge edge1(part1); Edge edge2(part2); edge1.breakEdge(); edge2.breakEdge(); } } if (!checkPointInList(p0)) breakPoints.push_back(p0); if (!checkPointInList(pend)) breakPoints.push_back(pend); } else { return; } }
/* Convert tets and pyramids next to close (identified) points into prisms */ void MakePrismsClosePoints (Mesh & mesh) { int i, j, k; for (i = 1; i <= mesh.GetNE(); i++) { Element & el = mesh.VolumeElement(i); if (el.GetType() == TET) { for (j = 1; j <= 3; j++) for (k = j+1; k <= 4; k++) { INDEX_2 edge(el.PNum(j), el.PNum(k)); edge.Sort(); if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k))) { int pi3 = 1, pi4 = 1; while (pi3 == j || pi3 == k) pi3++; pi4 = 10 - j - k - pi3; int p3 = el.PNum(pi3); int p4 = el.PNum(pi4); el.SetType(PRISM); el.PNum(1) = edge.I1(); el.PNum(2) = p3; el.PNum(3) = p4; el.PNum(4) = edge.I2(); el.PNum(5) = p3; el.PNum(6) = p4; } } } if (el.GetType() == PYRAMID) { // pyramid, base face = 1,2,3,4 for (j = 0; j <= 1; j++) { int pi1 = el.PNum( (j+0) % 4 + 1); int pi2 = el.PNum( (j+1) % 4 + 1); int pi3 = el.PNum( (j+2) % 4 + 1); int pi4 = el.PNum( (j+3) % 4 + 1); int pi5 = el.PNum(5); INDEX_2 edge1(pi1, pi4); INDEX_2 edge2(pi2, pi3); edge1.Sort(); edge2.Sort(); if (mesh.GetIdentifications().GetSymmetric (pi1, pi4) && mesh.GetIdentifications().GetSymmetric (pi2, pi3)) { //int p3 = el.PNum(pi3); //int p4 = el.PNum(pi4); el.SetType(PRISM); el.PNum(1) = pi1; el.PNum(2) = pi2; el.PNum(3) = pi5; el.PNum(4) = pi4; el.PNum(5) = pi3; el.PNum(6) = pi5; } } } } for (i = 1; i <= mesh.GetNSE(); i++) { Element2d & el = mesh.SurfaceElement(i); if (el.GetType() != TRIG) continue; for (j = 1; j <= 3; j++) { k = (j % 3) + 1; INDEX_2 edge(el.PNum(j), el.PNum(k)); edge.Sort(); if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k))) { int pi3 = 6-j-k; int p3 = el.PNum(pi3); int p1 = el.PNum(j); int p2 = el.PNum(k); el.SetType(QUAD); el.PNum(1) = p2; el.PNum(2) = p3; el.PNum(3) = p3; el.PNum(4) = p1; } } } }
void main() { glfwInit(); // Creates a window window = glfwCreateWindow(800, 800, "OBB - Plane Collision Detection", nullptr, nullptr); glfwMakeContextCurrent(window); glfwSwapInterval(0); // Initializes most things needed before the main loop init(); //Generate box mesh struct Vertex boxVerts[24]; boxVerts[0] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Left Corner boxVerts[1] = { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Left Corner boxVerts[2] = { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Left Corner boxVerts[3] = { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Right Corner boxVerts[4] = { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Right Corner boxVerts[5] = { 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Right Corner boxVerts[6] = { 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Right Corner boxVerts[7] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Left Corner boxVerts[8] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Left Corner boxVerts[9] = { -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Top Back Left Corner boxVerts[10] = { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Left Corner boxVerts[11] = { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Top Front Left Corner boxVerts[12] = { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Right Corner boxVerts[13] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Top Front Right Corner boxVerts[14] = { 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Right Corner boxVerts[15] = { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Top Back Right Corner boxVerts[16] = { -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Left Corner boxVerts[17] = { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Left Corner boxVerts[18] = { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Left Corner boxVerts[19] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Right Corner boxVerts[20] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Front Right Corner boxVerts[21] = { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Right Corner boxVerts[22] = { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Right Corner boxVerts[23] = { -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; //Bottom Back Left Corner box = new struct Mesh(24, boxVerts, GL_LINES); //Scale the box box->scale = box->scale * glm::scale(glm::mat4(1.0f), glm::vec3(0.1f, 0.1f, 0.1f)); //Translate the box box->translation = glm::translate(box->translation, glm::vec3(-0.1f, 0.0f, 0.0f)); //Generate the Plane mesh struct Vertex planeVerts[6]; planeVerts[0] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[1] = { 0.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[2] = { 0.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[3] = { 0.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[4] = { 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[5] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; plane = new struct Mesh(6, planeVerts, GL_TRIANGLES); //Scale the plane plane->scale = plane->scale * glm::scale(glm::mat4(1.0f), glm::vec3(5.0f, 5.0f, 5.0f)); //Translate the plane plane->translation = glm::translate(plane->translation, glm::vec3(0.1f, 0.0f, 0.0f)); //Set the selected shape selectedShape = plane; //Generate the colliders boxCollider = new struct OBB(boxVerts[3].x - boxVerts[2].x, boxVerts[9].y - boxVerts[8].y, boxVerts[1].z - boxVerts[0].z); //Get two edges of the plane and take the cross product for the normal (Or just hardcode it, for example we know the normal to this plane //Will be the Z axis, because the plane mesh lies in the XY Plane to start. glm::vec3 edge1(planeVerts[0].x - planeVerts[1].x, planeVerts[0].y - planeVerts[1].y, planeVerts[0].z - planeVerts[1].z); glm::vec3 edge2(planeVerts[1].x - planeVerts[2].x, planeVerts[1].y - planeVerts[2].y, planeVerts[1].z - planeVerts[2].z); glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2)); planeCollider = new struct Plane(normal); //Print controls std::cout << "Use WASD to move the selected shape in the XY plane.\nUse left CTRL & left shift to move the selected shape along Z axis.\n"; std::cout << "Left click and drag the mouse to rotate the selected shape.\nUse spacebar to swap the selected shape.\n"; // Enter the main loop. while (!glfwWindowShouldClose(window)) { // Call to update() which will update the gameobjects. update(); // Call the render function. renderScene(); // Swaps the back buffer to the front buffer glfwSwapBuffers(window); // Checks to see if any events are pending and then processes them. glfwPollEvents(); } // After the program is over, cleanup your data! glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(program); // Note: If at any point you stop using a "program" or shaders, you should free the data up then and there. delete box; delete plane; delete boxCollider; delete planeCollider; // Frees up GLFW memory glfwTerminate(); }
void main() { glfwInit(); // Creates a window window = glfwCreateWindow(800, 800, "Point - Plane Collision Detection", nullptr, nullptr); glfwMakeContextCurrent(window); glfwSwapInterval(0); // Initializes most things needed before the main loop init(); //Generate the Plane1 mesh struct Vertex planeVerts[6]; planeVerts[0] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[1] = { 0.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[2] = { 0.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[3] = { 0.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[4] = { 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; planeVerts[5] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; plane = new struct Mesh(6, planeVerts, GL_TRIANGLES); //Translate the plane plane->translation = glm::translate(plane->translation, glm::vec3(0.15f, 0.0f, 0.0f)); //Generate point mesh struct Vertex pointVert = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; point = new struct Mesh(1, &pointVert, GL_POINTS); //Translate the plane point->translation = glm::translate(point->translation, glm::vec3(-0.15f, 0.0f, 0.0f)); //Set the selected shape selectedShape = plane; //Generate plane collider //Get two edges of the plane and take the cross product for the normal (Or just hardcode it, for example we know the normal to this plane //Will be the Z axis, because the plane mesh lies in the XY Plane to start. glm::vec3 edge1(planeVerts[0].x - planeVerts[1].x, planeVerts[0].y - planeVerts[1].y, planeVerts[0].z - planeVerts[1].z); glm::vec3 edge2(planeVerts[1].x - planeVerts[2].x, planeVerts[1].y - planeVerts[2].y, planeVerts[1].z - planeVerts[2].z); glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2)); planeCollider = new struct Plane(normal); //Print controls std::cout << "Use WASD to move the selected shape in the XY plane.\nUse left CTRL & left shift to move the selected shape along Z axis.\n"; std::cout << "Left click and drag the mouse to rotate the selected shape.\nUse spacebar to swap the selected shape.\n"; // Enter the main loop. while (!glfwWindowShouldClose(window)) { // Call to update() which will update the gameobjects. update(); // Call the render function. renderScene(); // Swaps the back buffer to the front buffer glfwSwapBuffers(window); // Checks to see if any events are pending and then processes them. glfwPollEvents(); } // After the program is over, cleanup your data! glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(program); delete plane; delete point; delete planeCollider; // Frees up GLFW memory glfwTerminate(); }
Subdivide (int _vertexCount, glm::vec3* _vertices, int _triangleCount, glm::ivec3* _triangles, int _subCount) :vertexCount(_vertexCount), triangleCount(_triangleCount * _subCount * _subCount), subCount(_subCount) { vertices.resize(vertexCount); triangles.resize(triangleCount); for (int i = 0; i < vertexCount; ++i){ vertices[i] = _vertices[i]; } std::map<SubdivideEdge, std::vector<int> > edgeMap; int triIndex = 0; for (int i = 0; i < _triangleCount; ++i){ std::vector<int> triIndices; // Edge 1 SubdivideEdge edge1(_triangles[i].x, _triangles[i].y); if (edgeMap.find(edge1) == edgeMap.end()){ glm::vec3 vertexGap = (vertices[edge1.e2] - vertices[edge1.e1]) / (float)subCount; for (int i = 1; i < subCount; ++i){ vertices.push_back(vertices[edge1.e1] + vertexGap * (float)i); edgeMap[edge1].push_back(vertexCount++); } } if (edge1.isExchanged){ triIndices.push_back(edge1.e2); const std::vector<int>& tmpI = edgeMap[edge1]; for (int i = 0; i < tmpI.size(); ++i){ triIndices.push_back(tmpI[tmpI.size() - i - 1]); } }else{ triIndices.push_back(edge1.e1); const std::vector<int>& tmpI = edgeMap[edge1]; for (int i = 0; i < tmpI.size(); ++i){ triIndices.push_back(tmpI[i]); } } // Edge 2 SubdivideEdge edge2(_triangles[i].y, _triangles[i].z); if (edgeMap.find(edge2) == edgeMap.end()){ glm::vec3 vertexGap = (vertices[edge2.e2] - vertices[edge2.e1]) / (float)subCount; for (int i = 1; i < subCount; ++i){ vertices.push_back(vertices[edge2.e1] + vertexGap * (float)i); edgeMap[edge2].push_back(vertexCount++); } } if (edge2.isExchanged){ triIndices.push_back(edge2.e2); const std::vector<int>& tmpI = edgeMap[edge2]; for (int i = 0; i < tmpI.size(); ++i){ triIndices.push_back(tmpI[tmpI.size() - i - 1]); } }else{ triIndices.push_back(edge2.e1); const std::vector<int>& tmpI = edgeMap[edge2]; for (int i = 0; i < tmpI.size(); ++i){ triIndices.push_back(tmpI[i]); } } // Edge 3 SubdivideEdge edge3(_triangles[i].z, _triangles[i].x); if (edgeMap.find(edge3) == edgeMap.end()){ glm::vec3 vertexGap = (vertices[edge3.e2] - vertices[edge3.e1]) / (float)subCount; for (int i = 1; i < subCount; ++i){ vertices.push_back(vertices[edge3.e1] + vertexGap * (float)i); edgeMap[edge3].push_back(vertexCount++); } } if (edge3.isExchanged){ triIndices.push_back(edge3.e2); const std::vector<int>& tmpI = edgeMap[edge3]; for (int i = 0; i < tmpI.size(); ++i){ triIndices.push_back(tmpI[tmpI.size() - i - 1]); } }else{ triIndices.push_back(edge3.e1); const std::vector<int>& tmpI = edgeMap[edge3]; for (int i = 0; i < tmpI.size(); ++i){ triIndices.push_back(tmpI[i]); } } // Limit the subCount to [2, 5] subCount = subCount < 2 ? 2 : subCount; subCount = subCount > 5 ? 5 : subCount; // Create vertices inner triangle int currTriIndicesCnt = triIndices.size(); for (int step = 2; step < subCount; ++step){ glm::vec3 vertexGap = (vertices[triIndices[currTriIndicesCnt - step]] - vertices[triIndices[step]]) / (float)step; for (int i = 1; i < step; ++i){ vertices.push_back(vertices[triIndices[step]] + vertexGap * (float)i); triIndices.push_back(vertexCount++); } } // Create triangle index int size = subCount * subCount; for (int i = 0; i < size; i++){ triangles[triIndex++] = glm::ivec3(triIndices[subDivideMap[subCount][i * 3]], triIndices[subDivideMap[subCount][i * 3 + 1]], triIndices[subDivideMap[subCount][i * 3 + 2]]); } } }
void ellipseTransform(QPointF p1, QPointF p2, qreal rx, qreal ry, int largeFlag, int sweepFlag, int angel, qreal* startAngle, qreal *sweepLength, QRectF *rect){ qreal r1 = (p1.x() - p2.x()) / (2.f * rx); qreal r2 = (p2.y() - p1.y()) / (2.f * ry); qreal tmp = atan(r1 / r2); qreal a1s[2] = { tmp, -tmp }; tmp = asin(sqrt(r1*r1 + r2*r2)); qreal a2s[2] = { tmp, -tmp }; qreal x, y, t1, t2; qreal rrmin = rx*rx; qreal rrmax = ry*ry; if (rrmin > rrmax){ tmp = rrmin; rrmin = rrmax; rrmax = tmp; } for (int i = 0; i < 2;i++) { qreal a1 = a1s[i]; bool isBreak = false; for (int j = 0; j < 2; j++) { qreal a2 = a2s[j]; t1 = a1 + a2; t2 = a1 - a2; x = p1.x() - rx*cos(t1); y = p1.y() - ry*sin(t1); qreal check1 = (p1.x() - x)*(p1.x() - x) / (rx*rx) + (p1.y() - y)*(p1.y() - y) / (ry*ry); qreal check2 = (p2.x() - x)*(p2.x() - x) / (rx*rx) + (p2.y() - y)*(p2.y() - y) / (ry*ry); if ( fabs(check1-1) < 1.e-6 && fabs(check2-1) < 1.e-6) { isBreak = true; break; } } if (isBreak) break; } QVector3D edge1(x - p1.x(), y - p1.y(),0); QVector3D edge2(p2.x() - x, p2.y() - y,0); QVector3D cross = QVector3D::crossProduct(edge1,edge2); bool isCw = cross.z() > 0; if (isCw != (largeFlag == sweepFlag)) { QPointF centerOfp1p2 = (p1 + p2) / 2.f; x = centerOfp1p2.x() * 2 - x; y = centerOfp1p2.y() * 2 - y; /*x = x0 + a * cos(t) y = y0 + b * sin(t)*/ } *rect = QRect(x - rx, y - ry, rx * 2, ry * 2); t1 = atan2((p1.y() - y) / ry, (p1.x() - x) / rx); t2 = atan2((p2.y() - y) / ry, (p2.x() - x) / rx); *startAngle = t1 * 180 / PI; *startAngle = -*startAngle; *sweepLength = t2 * 180 / PI; *sweepLength = -*sweepLength; *sweepLength -= *startAngle; if ((largeFlag && fabs(*sweepLength) < 180) || (!largeFlag && fabs(*sweepLength) > 180)) { if (*sweepLength < 0) *sweepLength = -360 - *sweepLength; else *sweepLength = 360 - *sweepLength; } if ((!sweepFlag && *sweepLength <0) || (sweepFlag && *sweepLength >0)) { *sweepLength = -*sweepLength; } /*if (!isCw) { *sweepLength = fabs(*sweepLength); }*/ }
HE_Mesh::HE_Mesh(FVMesh& mesh) : Mesh(nullptr) { for (int vIdx = 0 ; vIdx < mesh.vertices.size() ; vIdx++) { vertices.push_back(HE_Vertex(mesh.vertices[vIdx].p, -1)); } for (int fIdx = 0 ; fIdx < mesh.faces.size() ; fIdx++) { FVMeshFace& fvFace = mesh.faces[fIdx]; HE_Face heFace; HE_Edge edge0(fvFace.vertex_index[0], fIdx); // vertices in face are ordered counter-clockwise HE_Edge edge1(fvFace.vertex_index[1], fIdx); HE_Edge edge2(fvFace.vertex_index[2], fIdx); int newEdgeIndex = edges.size(); vertices[ fvFace.vertex_index[0] ].someEdge_idx = newEdgeIndex+0; // overwrites existing data, if present vertices[ fvFace.vertex_index[1] ].someEdge_idx = newEdgeIndex+1; vertices[ fvFace.vertex_index[2] ].someEdge_idx = newEdgeIndex+2; edge0.next_edge_idx = newEdgeIndex+1; edge1.next_edge_idx = newEdgeIndex+2; edge2.next_edge_idx = newEdgeIndex+0; edges.push_back(edge0); edges.push_back(edge1); edges.push_back(edge2); heFace.edge_idx[0] = newEdgeIndex+0; heFace.edge_idx[1] = newEdgeIndex+1; heFace.edge_idx[2] = newEdgeIndex+2; faces.push_back(heFace); } // connect half-edges: bool faceEdgeIsConnected[mesh.faces.size()][3] = {}; // initialize all as false // for each edge of each face : if it doesn't have a converse then find the converse in the edges of the opposite face for (int fIdx = 0 ; fIdx < mesh.faces.size() ; fIdx++) { FVMeshFace& fvFace = mesh.faces[fIdx]; //FVMeshFaceHandle fh(mesh, fIdx); HE_FaceHandle fnew(*this, fIdx); // face index on FVMesh corresponds to index in HE_Mesh // HE_EdgeHandle edge = fnew.edge0(); // HE_EdgeHandle edgeStart = edge; // do // for (int eIdx = 0; eIdx < 3; eIdx++) { if (faceEdgeIsConnected[fIdx][eIdx]) { // edge.next(); continue; } int edge_idx = faces[fIdx].edge_idx[eIdx]; HE_Edge& edge = edges[ edge_idx ]; int face2 = fvFace.connected_face_index[eIdx]; // connected_face X is connected via vertex X and vertex X+1 if (face2 < 0) { atlas::logError("Incorrect model: disconnected faces. Support generation aborted.\n"); exit(1); // TODO: not exit, but continue without support! } for (int e2 = 0; e2 < 3; e2++) { if (mesh.faces[face2].vertex_index[e2] == edges[edge.next_edge_idx].from_vert_idx) { edges[ faces[face2].edge_idx[e2] ].converse_edge_idx = edge_idx; edge.converse_edge_idx = faces[face2].edge_idx[e2]; faceEdgeIsConnected[face2][e2] = true; // the other way around doesn't have to be set; we will not pass the same edge twice break; } if (e2 == 2) std::cerr << "Couldn't find converse of edge " << std::to_string(edge_idx) <<"!!!!!" << std::endl; } //edge = edge.next(); } //while (edge != edgeStart) } HE_MESH_DEBUG_DO( mesh.debugOutputWholeMesh(); ) }
bool Terrain::HeightMapLoad(char* filename, float sx, float sz, float maxy) { //FILE *filePtr; // Point to the current position in the file //BITMAPFILEHEADER bitmapFileHeader; // Structure which stores information about file //BITMAPINFOHEADER bitmapInfoHeader; // Structure which stores information about image int imageSize, index; unsigned char height; // Open the file //filePtr = fopen(filename,"rb"); //if (filePtr == NULL) // return 0; dx = sz; dz = sz; dy = maxy; // Get the width and height (width and length) of the image hminfo.terrainWidth = 145;// bitmapInfoHeader.biWidth; hminfo.terrainHeight = 145;// bitmapInfoHeader.biHeight; // Initialize the heightMap array (stores the vertices of our terrain) hminfo.heightMap = new IntV3[hminfo.terrainWidth * hminfo.terrainHeight]; // We use a greyscale image, so all 3 rgb values are the same, but we only need one for the height // So we use this counter to skip the next two components in the image data (we read R, then skip BG) int k=0; // Read the image data into our heightMap array for(int j=0; j< hminfo.terrainHeight; j++) { for(int i=0; i< hminfo.terrainWidth; i++) { height = rand()%50+1; index = ( hminfo.terrainWidth * (hminfo.terrainHeight - 1 - j)) + i; hminfo.heightMap[index].x = i - (hminfo.terrainWidth - 1)/2; hminfo.heightMap[index].y = height; hminfo.heightMap[index].z = j - (hminfo.terrainHeight - 1)/2; k+=3; } k++; } int cols = hminfo.terrainWidth; int rows = hminfo.terrainHeight; //Create the grid NumVertices = 2 * rows * cols; NumFaces = (rows-1)*(cols-1)*2; v = new struct HeightFieldVertex[NumVertices]; for(DWORD i = 0; i < rows; ++i) { for(DWORD j = 0; j < cols; ++j) { v[i*cols+j].pos.x = hminfo.heightMap[i*cols+j].x * dx; v[i*cols+j].pos.y = (float(hminfo.heightMap[i*cols+j].y)/255.0) * dy; v[i*cols+j].pos.z = hminfo.heightMap[i*cols+j].z * dz; v[i*cols+j].texCoord = D3DXVECTOR2(j, i); } } indices = new DWORD[NumFaces * 3]; k = 0; for(DWORD i = 0; i < rows-1; i++) { for(DWORD j = 0; j < cols-1; j++) { indices[k] = i*cols+j; // Bottom left of quad indices[k+1] = i*cols+j+1; // Bottom right of quad indices[k+2] = (i+1)*cols+j; // Top left of quad indices[k+3] = (i+1)*cols+j; // Top left of quad indices[k+4] = i*cols+j+1; // Bottom right of quad indices[k+5] = (i+1)*cols+j+1; // Top right of quad k += 6; // next quad } } //normals & tangents std::vector<D3DXVECTOR3> tempNormal; //normalized and unnormalized normals D3DXVECTOR3 unnormalized(0.0f, 0.0f, 0.0f); //tangent stuff std::vector<D3DXVECTOR3> tempTangent; D3DXVECTOR3 tangent(0.0f, 0.0f, 0.0f); float tcU1, tcV1, tcU2, tcV2; //Used to get vectors (sides) from the position of the verts float vecX, vecY, vecZ; //Two edges of our triangle D3DXVECTOR3 edge1(0.0f, 0.0f, 0.0f); D3DXVECTOR3 edge2(0.0f, 0.0f, 0.0f); //Compute face normals //And Tangents for(int i = 0; i < NumFaces; ++i) { //Get the vector describing one edge of our triangle (edge 0,2) vecX = v[indices[(i*3)+1]].pos.x - v[indices[(i*3)]].pos.x; vecY = v[indices[(i*3)+1]].pos.y - v[indices[(i*3)]].pos.y; vecZ = v[indices[(i*3)+1]].pos.z - v[indices[(i*3)]].pos.z; edge1 = D3DXVECTOR3(vecX, vecY, vecZ); //Create our first edge //Get the vector describing another edge of our triangle (edge 2,1) vecX = v[indices[(i*3)+2]].pos.x - v[indices[(i*3)]].pos.x; vecY = v[indices[(i*3)+2]].pos.y - v[indices[(i*3)]].pos.y; vecZ = v[indices[(i*3)+2]].pos.z - v[indices[(i*3)]].pos.z; edge2 = D3DXVECTOR3(vecX, vecY, vecZ); //Create our second edge //Cross multiply the two edge vectors to get the un-normalized face normal D3DXVec3Cross(&unnormalized, &edge1, &edge2); tempNormal.push_back(unnormalized); //Find first texture coordinate edge 2d vector tcU1 = v[indices[(i*3)+1]].texCoord.x - v[indices[(i*3)]].texCoord.x; tcV1 = v[indices[(i*3)+1]].texCoord.y - v[indices[(i*3)]].texCoord.y; //Find second texture coordinate edge 2d vector tcU2 = v[indices[(i*3)+2]].texCoord.x - v[indices[(i*3)]].texCoord.x; tcV2 = v[indices[(i*3)+2]].texCoord.y - v[indices[(i*3)]].texCoord.y; //Find tangent using both tex coord edges and position edges tangent.x = (tcV2 * edge1.x - tcV1 * edge2.x) / (tcU1 * tcV2 - tcU2 * tcV1); tangent.y = (tcV2 * edge1.y - tcV1 * edge2.y) / (tcU1 * tcV2 - tcU2 * tcV1); tangent.z = (tcV2 * edge1.z - tcV1 * edge2.z) / (tcU1 * tcV2 - tcU2 * tcV1); tempTangent.push_back(tangent); } //Compute vertex normals (normal Averaging) D3DXVECTOR4 normalSum(0.0f, 0.0f, 0.0f, 0.0f); D3DXVECTOR4 tangentSum(0.0f, 0.0f, 0.0f, 0.0f); int facesUsing = 0; float tX, tY, tZ; //temp axis variables //Go through each vertex for(int i = 0; i < NumVertices; ++i) { //Check which triangles use this vertex for(int j = 0; j < NumFaces; ++j) { if(indices[j*3] == i || indices[(j*3)+1] == i || indices[(j*3)+2] == i) { tX = normalSum.x + tempNormal[j].x; tY = normalSum.y + tempNormal[j].y; tZ = normalSum.z + tempNormal[j].z; normalSum = D3DXVECTOR4(tX, tY, tZ, 0.0f); //If a face is using the vertex, add the unormalized face normal to the normalSum facesUsing++; } } //Get the actual normal by dividing the normalSum by the number of faces sharing the vertex normalSum = normalSum / facesUsing; facesUsing = 0; //Check which triangles use this vertex for(int j = 0; j < NumFaces; ++j) { if(indices[j*3] == i || indices[(j*3)+1] == i || indices[(j*3)+2] == i) { //We can reuse tX, tY, tZ to sum up tangents tX = tangentSum.x + tempTangent[j].x; tY = tangentSum.y + tempTangent[j].y; tZ = tangentSum.z + tempTangent[j].z; tangentSum = D3DXVECTOR4(tX, tY, tZ, 0.0f); //sum up face tangents using this vertex facesUsing++; } } //Get the actual normal by dividing the normalSum by the number of faces sharing the vertex tangentSum = tangentSum / facesUsing; //Normalize the normalSum vector and tangent D3DXVec4Normalize(&normalSum, &normalSum); D3DXVec4Normalize(&tangentSum, &tangentSum); //Store the normal and tangent in our current vertex v[i].normal.x = normalSum.x; v[i].normal.y = normalSum.y; v[i].normal.z = normalSum.z; v[i].tangent.x = tangentSum.x; v[i].tangent.y = tangentSum.y; v[i].tangent.z = tangentSum.z; D3DXVECTOR3 bit; D3DXVec3Cross(&bit, &v[i].normal, &v[i].tangent); v[i].bitangent = -1.0 * bit; //Clear normalSum, tangentSum and facesUsing for next vertex normalSum = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f); tangentSum = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f); facesUsing = 0; } ////terrain AABB //MinX = -1.0 * dx * (hminfo.terrainWidth - 1)/2; //MinY = 0.0; //MinZ = -1.0 * dz * (hminfo.terrainHeight - 1)/2; //MaxX = dx * (hminfo.terrainWidth - 1)/2; //MaxY = dy; //MaxZ = dz * (hminfo.terrainHeight - 1)/2; return true; }
bool CTriangulation::Triangulate(vector<CEdgeLoop> &tri_faces, CRegion& region) { vector<CEdge> regionEdges; for(EdgeArray::iterator ol_it = region.OuterLoops.Edges.begin();ol_it != region.OuterLoops.Edges.end();ol_it++) { regionEdges.push_back(*ol_it); } for(vector<CEdgeLoop>::iterator il_it1 = region.InnerLoops.begin();il_it1 != region.InnerLoops.end();il_it1++) { CEdgeLoop currentInnerLoop = *il_it1; for(EdgeArray::iterator il_it2 = currentInnerLoop.Edges.begin();il_it2 != currentInnerLoop.Edges.end();il_it2++) { regionEdges.push_back(*il_it2); } } while(regionEdges.size() > 3) { vector<vec2> candidatePoints; for(int i = 1;i<regionEdges.size();i++) { if (CMathUtility::ToLeftExcludeOnLine(regionEdges[i].End,regionEdges[0])) { int k = 0; for(k = 1;k<regionEdges.size();k++) { CEdge edge1(regionEdges[0].Start,regionEdges[i].End); edge1.Commit(); CEdge edge2(regionEdges[0].End,regionEdges[i].End); edge2.Commit(); //??????? if(edge1.IsIntersectWith2(regionEdges[k]) || edge2.IsIntersectWith2(regionEdges[k])) { break; } } if(k == regionEdges.size()) { candidatePoints.push_back(regionEdges[i].End); } } } double minR = MAXDWORD; vec2 LO2; for(int j = 0;j<candidatePoints.size();j++) { double r =CMathUtility::MinR(regionEdges[0].Start,regionEdges[0].End,candidatePoints[j]); if(r < minR) { minR = r; LO2 = candidatePoints[j]; } } CEdgeLoop tmpTriangel; tmpTriangel.Edges.push_back(regionEdges[0]); CEdge tmpEdge1(regionEdges[0].End,LO2); tmpEdge1.Commit(); tmpTriangel.Edges.push_back(tmpEdge1); CEdge tmpEdge2(LO2,regionEdges[0].Start); tmpEdge2.Commit(); tmpTriangel.Edges.push_back(tmpEdge2); tmpTriangel.Commit(); vector<vec2> newCandidatePoints; for(int m = 0;m<candidatePoints.size();m++) { if(CMathUtility::IsCanExistInCircle(candidatePoints[m],tmpTriangel)) { newCandidatePoints.push_back(candidatePoints[m]); } } while (!newCandidatePoints.size() ==0) { minR=MAXDWORD; for(int m = 0;m < newCandidatePoints.size();m++) { double r=CMathUtility::MinR(regionEdges[0].Start,regionEdges[0].End,newCandidatePoints[m]); if(r < minR) { minR = r; LO2 = newCandidatePoints[m]; } } tmpTriangel.Edges.clear(); tmpTriangel.Edges.push_back(regionEdges[0]); tmpEdge1.Start = regionEdges[0].End; tmpEdge1.End = LO2; tmpTriangel.Edges.push_back(tmpEdge1); tmpEdge2.Start = LO2; tmpEdge2.End = regionEdges[0].Start; tmpTriangel.Edges.push_back(tmpEdge2); tmpTriangel.Commit(); newCandidatePoints.clear(); for (int j = 0;j<candidatePoints.size();j++) { if (CMathUtility::IsCanExistInCircle(candidatePoints[j],tmpTriangel)) { newCandidatePoints.push_back(candidatePoints[j]); } } } tri_faces.push_back(tmpTriangel); CEdge L11_LO2(regionEdges[0].Start,LO2); L11_LO2.isBoundEdge = false; L11_LO2.Commit(); CEdge L12_LO2(LO2,regionEdges[0].End); L12_LO2.isBoundEdge =false; L12_LO2.Commit(); int pos_m = 0; int pos_n = 0; if(CMathUtility::IsBoundEdge(regionEdges,L11_LO2,pos_m)) { L11_LO2.isBoundEdge = true; } if(CMathUtility::IsBoundEdge(regionEdges,L12_LO2,pos_n)) { L12_LO2.isBoundEdge = true; } if(!L11_LO2.isBoundEdge && !L12_LO2.isBoundEdge) { CEdge tmpEdge(L12_LO2.Start,L12_LO2.End); tmpEdge.Commit(); regionEdges.push_back(tmpEdge); regionEdges[0].End = LO2; regionEdges[0].Commit(); } if(L11_LO2.isBoundEdge && !L12_LO2.isBoundEdge) { regionEdges[0].Start = LO2; regionEdges[0].Commit(); regionEdges[pos_m] = regionEdges[regionEdges.size()-1]; regionEdges.pop_back(); } if(!L11_LO2.isBoundEdge && L12_LO2.isBoundEdge) { regionEdges[0].End = LO2; regionEdges[0].Commit(); regionEdges[pos_n] = regionEdges[regionEdges.size()-1]; regionEdges.pop_back(); } if(L11_LO2.isBoundEdge && L12_LO2.isBoundEdge) { if (pos_n>pos_m) { regionEdges[pos_n] = regionEdges[regionEdges.size()-1]; regionEdges.pop_back(); regionEdges[pos_m] = regionEdges[regionEdges.size()-1]; regionEdges.pop_back(); regionEdges[0] = regionEdges[regionEdges.size()-1]; regionEdges.pop_back(); } else { regionEdges[pos_m] = regionEdges[regionEdges.size()-1]; regionEdges.pop_back(); regionEdges[pos_n] = regionEdges[regionEdges.size()-1]; regionEdges.pop_back(); regionEdges[0] = regionEdges[regionEdges.size()-1]; regionEdges.pop_back(); } } } // TODO if(regionEdges.size()==3) { CEdgeLoop tmpTriangle; tmpTriangle.Edges.push_back(regionEdges[0]); tmpTriangle.Edges.push_back(regionEdges[1]); tmpTriangle.Edges.push_back(regionEdges[2]); tmpTriangle.Commit(); tri_faces.push_back(tmpTriangle); } return true; }
bool DivideAndConquerFor3DCH::RayTriangleIntersection( Ray r, TRIANGLE triangle, const vector<VERTEX*>* pVertex ) { VERTEX* pointOne = (*pVertex)[ triangle.p1.pointOneIndex ]; VERTEX* pointTwo = (*pVertex)[ triangle.p2.pointTwoIndex ]; VERTEX* pointThree = (*pVertex)[ triangle.p3.pointThreeIndex ]; D3DXVECTOR3 edge1( pointTwo->x - pointOne->x, pointTwo->y - pointOne->y, pointTwo->z - pointOne->z ); D3DXVECTOR3 edge2( pointThree->x - pointOne->x, pointThree->y - pointOne->y, pointThree->z - pointOne->z ); D3DXVECTOR3 triNormal; D3DXVec3Cross( &triNormal, &edge1, &edge2 ); D3DXVec3Normalize( &triNormal, &triNormal ); double denominator = D3DXVec3Dot( &triNormal, &r.direction ); // Ray parallels to the plane if( fabs( denominator ) < 0.000001 ) { return false; } double d = triNormal.x * pointOne->x + triNormal.y * pointOne->y + triNormal.z * pointOne->z; double t = ( d - D3DXVec3Dot( &triNormal, &r.position ) ) / denominator; // Trianle behine the ray if( t <= 0 ) { return false; } D3DXVECTOR3 intersectPoint = r.position + t * r.direction; //D3DXVECTOR3 tmp; //D3DXVec3Cross( &tmp, &edge1, &edge2 ); //double totalAmount = D3DXVec3Dot( &tmp, &triNormal ); //double totalArea = D3DXVec3Length( &tmp ) * 0.5; //VERTEX tmpV = pointThree - pointTwo; //D3DXVec3Cross( &tmp, &D3DXVECTOR3( tmpV.x, tmpV.y, tmpV.z ), &D3DXVECTOR3( intersectPoint.x - pointTwo.x, intersectPoint.y - pointTwo.y, intersectPoint.z - pointTwo.z ) ); //double alpha = D3DXVec3Length( &tmp ) * 0.5 / totalArea; // //tmpV = pointOne - pointThree; //D3DXVec3Cross( &tmp, &D3DXVECTOR3( tmpV.x, tmpV.y, tmpV.z ), &D3DXVECTOR3( intersectPoint.x - pointThree.x, intersectPoint.y - pointThree.y, intersectPoint.z - pointThree.z ) ); //double beta = D3DXVec3Length( &tmp ) * 0.5 / totalArea; //tmpV = pointTwo - pointOne; //D3DXVec3Cross( &tmp, &D3DXVECTOR3( tmpV.x, tmpV.y, tmpV.z ), &D3DXVECTOR3( intersectPoint.x - pointOne.x, intersectPoint.y - pointOne.y, intersectPoint.z - pointOne.z ) ); //double gamma = D3DXVec3Length( &tmp ) * 0.5 / totalArea; // if( alpha + beta + gamma > 1.00001 ) // { // return false; // } D3DXVECTOR3 tmpEdge( intersectPoint.x - pointOne->x, intersectPoint.y - pointOne->y, intersectPoint.z - pointOne->z ); D3DXVECTOR3 tmpCrossRes; D3DXVec3Cross( &tmpCrossRes, &edge1, &tmpEdge ); double alpha = D3DXVec3Dot( &triNormal, &tmpCrossRes ); if( alpha < 0.0f ) { return false; } tmpEdge = D3DXVECTOR3( intersectPoint.x - pointTwo->x, intersectPoint.y - pointTwo->y, intersectPoint.z - pointTwo->z); D3DXVECTOR3 tmpEdge2( pointThree->x - pointTwo->x, pointThree->y - pointTwo->y, pointThree->z - pointTwo->z ); D3DXVec3Cross( &tmpCrossRes, &tmpEdge2, &tmpEdge ); double beta = D3DXVec3Dot( &triNormal, &tmpCrossRes ); if( beta < 0.0f ) { return false; } tmpEdge = D3DXVECTOR3( intersectPoint.x - pointThree->x, intersectPoint.y - pointThree->y, intersectPoint.z - pointThree->z ); tmpEdge2 = D3DXVECTOR3( pointOne->x - pointThree->x, pointOne->y - pointThree->y, pointOne->z - pointThree->z ); D3DXVec3Cross( &tmpCrossRes, &tmpEdge2, &tmpEdge ); double gamma = D3DXVec3Dot( &triNormal, &tmpCrossRes ); if( gamma < 0.0f ) { return false; } return true; }
DCEL DivideAndConquerFor3DCH::BruceForceCH( vector<VERTEX*>* pVertex, const unsigned int offset ) { vector<TRIANGLE> triangleSet, finalTriangleSet; // Generate all possible triangles int pointSetSize = pVertex->size(); for( int i = 0; i < pointSetSize; i++ ) { for( int j = i + 1; j < pointSetSize; j++ ) { for( int k = j + 1; k < pointSetSize; k++ ) { // Forming face TRIANGLE face; face.p1.pointOneIndex = i; face.p2.pointTwoIndex = j; face.p3.pointThreeIndex = k; triangleSet.push_back( face ); } } } // Find the CH for this point set by using RayAndTriangleIntersection method for( int i = 0; i < triangleSet.size(); i++ ) { // Create a ray from this surface TRIANGLE triangle = triangleSet[ i ]; // Point2 - point1 //D3DXVECTOR3 edge1( triangle.pointTwo.x - triangle.pointOne.x, triangle.pointTwo.y - triangle.pointOne.y, triangle.pointTwo.z - triangle.pointOne.z ); VERTEX* pointOne = (*pVertex)[ triangle.p1.pointOneIndex ]; VERTEX* pointTwo = (*pVertex)[ triangle.p2.pointTwoIndex ]; VERTEX* pointThree = (*pVertex)[ triangle.p3.pointThreeIndex ]; D3DXVECTOR3 edge1( pointTwo->x - pointOne->x, pointTwo->y - pointOne->y, pointTwo->z - pointOne->z ); D3DXVECTOR3 edge2( pointThree->x - pointOne->x, pointThree->y - pointOne->y, pointThree->z - pointOne->z ); // point3 - point1 //D3DXVECTOR3 edge2( triangle.pointThree.x - triangle.pointOne.x, triangle.pointThree.y - triangle.pointOne.y, triangle.pointThree.z - triangle.pointOne.z ); D3DXVECTOR3 triangleNormal; D3DXVec3Cross( &triangleNormal, &edge1, &edge2 ); D3DXVECTOR3 rayStartPoint( ( pointOne->x + pointTwo->x + pointThree->x ) / 3.0f, ( pointOne->y + pointTwo->y + pointThree->y ) / 3.0f, ( pointOne->z + pointTwo->z + pointThree->z ) / 3.0f ); Ray ray, invRay; D3DXVec3Normalize( &ray.direction, &triangleNormal ); ray.position = rayStartPoint; invRay = ray; invRay.direction *= -1.0; bool rayIntersect = !isNormal(ray, triangleSet[i], pVertex); bool invRayIntersect = !isNormal(invRay, triangleSet[i], pVertex); // This is the face that contribute to the convex hull and find its vertices order if( rayIntersect == false && invRayIntersect == true ) { finalTriangleSet.push_back( triangleSet[ i ] ); } else if( rayIntersect == true && invRayIntersect == false ) { TRIANGLE tmpTri = triangleSet[ i ]; int tmpVerIndex = tmpTri.p2.pointTwoIndex; tmpTri.p2.pointTwoIndex = tmpTri.p3.pointThreeIndex; tmpTri.p3.pointThreeIndex = tmpVerIndex; finalTriangleSet.push_back( tmpTri ); } } DCEL dcel; dcel.createDCEL( &finalTriangleSet, pVertex, offset ); return dcel; }
void Graph::seedNodesAndEdges() { /* Upon construction: seed graph with nodes and edges to connect them. * For now this happens manually. Ideally this happens by algorithm */ std::shared_ptr<Node> nodeA(new Node(0, "0", 100, 50)); std::shared_ptr<Node> nodeB(new Node(1, "1", 500, 40)); std::shared_ptr<Node> nodeC(new Node(2, "2", 200, 300)); std::shared_ptr<Node> nodeD(new Node(3, "3", 700, 100)); std::shared_ptr<Node> nodeE(new Node(4, "4", 600, 400)); std::shared_ptr<Node> nodeF(new Node(5, "5", 250, 450)); std::shared_ptr<Node> nodeG(new Node(6, "6", 750, 500)); std::shared_ptr<Node> nodeH(new Node(7, "7", 400, 150)); std::shared_ptr<Node> nodeI(new Node(8, "8", 550, 250)); std::shared_ptr<Node> nodeJ(new Node(9, "9", 100, 400)); std::list<std::shared_ptr<Edge>> edgeList; // Sequenced container of Edge pointers nodeVector.push_back(nodeA); std::shared_ptr<Edge> edge1(new Edge(nodeA, nodeB, calculateCost(nodeA, nodeB))); edgeList.push_back(edge1); std::shared_ptr<Edge> edge2(new Edge(nodeA, nodeC, calculateCost(nodeA, nodeC))); edgeList.push_back(edge2); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeB); std::shared_ptr<Edge> edge3(new Edge(nodeB, nodeA, calculateCost(nodeB, nodeA))); edgeList.push_back(edge3); std::shared_ptr<Edge> edge4(new Edge(nodeB, nodeH, calculateCost(nodeB, nodeH))); edgeList.push_back(edge4); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeC); std::shared_ptr<Edge> edge5(new Edge(nodeC, nodeA, calculateCost(nodeC, nodeA))); edgeList.push_back(edge5); std::shared_ptr<Edge> edge6(new Edge(nodeC, nodeH, calculateCost(nodeC, nodeH))); edgeList.push_back(edge6); std::shared_ptr<Edge> edge7(new Edge(nodeC, nodeE, calculateCost(nodeC, nodeE))); edgeList.push_back(edge7); std::shared_ptr<Edge> edge8(new Edge(nodeC, nodeF, calculateCost(nodeC, nodeF))); edgeList.push_back(edge8); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeD); std::shared_ptr<Edge> edge9(new Edge(nodeD, nodeH, calculateCost(nodeD, nodeH))); edgeList.push_back(edge9); std::shared_ptr<Edge> edge10(new Edge(nodeD, nodeE, calculateCost(nodeD, nodeE))); edgeList.push_back(edge10); std::shared_ptr<Edge> edge11(new Edge(nodeD, nodeG, calculateCost(nodeD, nodeG))); edgeList.push_back(edge11); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeE); std::shared_ptr<Edge> edge12(new Edge(nodeE, nodeC, calculateCost(nodeE, nodeC))); edgeList.push_back(edge12); std::shared_ptr<Edge> edge13(new Edge(nodeE, nodeD, calculateCost(nodeE, nodeD))); edgeList.push_back(edge13); std::shared_ptr<Edge> edge14(new Edge(nodeE, nodeG, calculateCost(nodeE, nodeG))); edgeList.push_back(edge14); std::shared_ptr<Edge> edge15(new Edge(nodeE, nodeI, calculateCost(nodeE, nodeI))); edgeList.push_back(edge15); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeF); std::shared_ptr<Edge> edge16(new Edge(nodeF, nodeG, calculateCost(nodeF, nodeG))); edgeList.push_back(edge16); std::shared_ptr<Edge> edge17(new Edge(nodeF, nodeC, calculateCost(nodeF, nodeC))); edgeList.push_back(edge17); std::shared_ptr<Edge> edge18(new Edge(nodeF, nodeJ, calculateCost(nodeF, nodeJ))); edgeList.push_back(edge18); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeG); std::shared_ptr<Edge> edge19(new Edge(nodeG, nodeF, calculateCost(nodeG, nodeF))); edgeList.push_back(edge19); std::shared_ptr<Edge> edge20(new Edge(nodeG, nodeD, calculateCost(nodeG, nodeD))); edgeList.push_back(edge20); std::shared_ptr<Edge> edge21(new Edge(nodeG, nodeE, calculateCost(nodeG, nodeE))); edgeList.push_back(edge21); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeH); std::shared_ptr<Edge> edge22(new Edge(nodeH, nodeD, calculateCost(nodeH, nodeD))); edgeList.push_back(edge22); std::shared_ptr<Edge> edge23(new Edge(nodeH, nodeC, calculateCost(nodeH, nodeC))); edgeList.push_back(edge23); std::shared_ptr<Edge> edge24(new Edge(nodeH, nodeB, calculateCost(nodeH, nodeB))); edgeList.push_back(edge24); std::shared_ptr<Edge> edge25(new Edge(nodeH, nodeI, calculateCost(nodeH, nodeI))); edgeList.push_back(edge25); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeI); std::shared_ptr<Edge> edge26(new Edge(nodeI, nodeH, calculateCost(nodeI, nodeH))); edgeList.push_back(edge26); std::shared_ptr<Edge> edge27(new Edge(nodeI, nodeE, calculateCost(nodeI, nodeE))); edgeList.push_back(edge27); edgeListVector.push_back(edgeList); edgeList.clear(); nodeVector.push_back(nodeJ); std::shared_ptr<Edge> edge28(new Edge(nodeJ, nodeF, calculateCost(nodeJ, nodeF))); edgeList.push_back(edge28); edgeListVector.push_back(edgeList); edgeList.clear(); }