void TessMeshApp::Update(){ App::Update(); mesh->Update(); meshShaderProgram->use(); GLuint m = meshShaderProgram->uniform("model"); glUniformMatrix4fv(m, 1, GL_FALSE, glm::value_ptr(mesh->modelMatrix)); GLuint v = meshShaderProgram->uniform("view"); glUniformMatrix4fv(v, 1, GL_FALSE, glm::value_ptr(camera.view)); GLuint p = meshShaderProgram->uniform("projection"); glUniformMatrix4fv(p, 1, GL_FALSE, glm::value_ptr(camera.projection)); meshShaderProgram->disable(); mouseShaderProgram->use(); m = mouseShaderProgram->uniform("model"); glUniformMatrix4fv(m, 1, GL_FALSE, glm::value_ptr(mesh->modelMatrix)); v = mouseShaderProgram->uniform("view"); glUniformMatrix4fv(v, 1, GL_FALSE, glm::value_ptr(camera.view)); p = mouseShaderProgram->uniform("projection"); glUniformMatrix4fv(p, 1, GL_FALSE, glm::value_ptr(camera.projection)); // cursor { vec2 mouse = mouse_cursor; vec3 view = normalize( camera.camera_look_at - camera.camera_position ); vec3 h = normalize(cross(view, camera.camera_up)); vec3 v = normalize(cross(h, view)); float rad = radians(camera.field_of_view); float vLength = tanf(rad /2.0f) * camera.near_clip; float hLength = vLength * camera.aspect; v *= vLength; h *= hLength; mouse.x -= window_width/2; mouse.y = window_height - mouse.y - window_height/2; mouse.x /= window_width/2; mouse.y /= window_height/2; vec3 pos = camera.camera_position + view * (float)camera.near_clip + h*mouse.x + v*mouse.y; GLuint mousePosition = mouseShaderProgram->uniform("mousePosition"); glUniform3fv(mousePosition, 1, value_ptr(pos)); } mouseShaderProgram->disable(); }
Distance3f distance_trianglef(const float3 p, const float3* poly) { const float3 normal = normalize(cross(poly[1]-poly[0], poly[2]-poly[0])); // Degenerate triangle if (normal.x != normal.x) { // Hack to safely fail if triangle is degenerate float max_d = length2(poly[1]-poly[0]); float3 a = poly[1]; float3 b = poly[0]; if (length2(poly[2]-poly[1]) > max_d) { max_d = length2(poly[2]-poly[1]); a = poly[2]; b = poly[1]; } if (length2(poly[2]-poly[0]) > max_d) { // No need to reset max_d a = poly[2]; b = poly[0]; } return distance_line3(p, a, b); } const float proj_dist = dot((p - poly[0]), normal); const float3 proj_pnt = p - (normal * proj_dist); float dist = fabs(proj_dist); int drop_dim = 0; float drop_dim_val = fabs(normal.x); if (fabs(normal.y) > drop_dim_val) { drop_dim = 1; drop_dim_val = fabs(normal.y); } if (fabs(normal.z) > drop_dim_val) { drop_dim = 2; drop_dim_val = fabs(normal.z); } float2 poly_proj[3]; float2 proj_proj_pnt; #ifdef OPEN_CL for (int i = 0; i < 3; ++i) { if (drop_dim == 0) { poly_proj[i] = poly[i].yz; } else if (drop_dim == 1) { poly_proj[i] = poly[i].xz; } else { poly_proj[i] = poly[i].xy; } } if (drop_dim == 0) { proj_proj_pnt = proj_pnt.yz; } else if (drop_dim == 1) { proj_proj_pnt = proj_pnt.xz; } else { proj_proj_pnt = proj_pnt.xy; } #else for (int i = 0; i < 3; ++i) { if (drop_dim == 0) { poly_proj[i] = make_float2(poly[i].y, poly[i].z); } else if (drop_dim == 1) { poly_proj[i] = make_float2(poly[i].x, poly[i].z); } else { poly_proj[i] = make_float2(poly[i].x, poly[i].y); } } if (drop_dim == 0) { proj_proj_pnt = make_float2(proj_pnt.y, proj_pnt.z); } else if (drop_dim == 1) { proj_proj_pnt = make_float2(proj_pnt.x, proj_pnt.z); } else { proj_proj_pnt = make_float2(proj_pnt.x, proj_pnt.y); } #endif float2 poly_shift[3]; for (int i = 0; i < 3; ++i) { poly_shift[i] = poly_proj[i] - proj_proj_pnt; } bool test_val; bool first_time = true; bool inside = true; for (int i = 0; i < 3; ++i) { float2 v = poly_shift[i]; float2 vn = poly_shift[(i+1) % 3]; float area = vn.x*v.y - v.x*vn.y; // actually is twice area if (first_time) { test_val = area > 0; first_time = false; } else { if (test_val != area > 0) { inside = false; break; } } } if (inside) { // nan! /* assert(dist == dist); */ // dist is set at start of function to be proj distance Distance3f d = { dist, proj_pnt }; return d; } else { bool unset = true; Distance3f best; for (int i = 0; i < 3; ++i) { if (unset) { best = distance_line3(p, poly[i], poly[(i+1)%3]); unset = false; } else { Distance3f dist = distance_line3(p, poly[i], poly[(i+1)%3]); best = min_pair3f(best, dist); } } // nan! /* assert(best.d == best.d) { */ return best; } }
double Vector2D::angleBetween(const Vector2D &a, const Vector2D &b) { return atan2(cross(a, b), scalar(a, b)); }
int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit) { if(verts_count <4) return 0; if(vlimit==0) vlimit=1000000000; int j; btVector3 bmin(*verts),bmax(*verts); btAlignedObjectArray<int> isextreme; isextreme.reserve(verts_count); btAlignedObjectArray<int> allow; allow.reserve(verts_count); for(j=0;j<verts_count;j++) { allow.push_back(1); isextreme.push_back(0); bmin.setMin (verts[j]); bmax.setMax (verts[j]); } btScalar epsilon = (bmax-bmin).length() * btScalar(0.001); btAssert (epsilon != 0.0); int4 p = FindSimplex(verts,verts_count,allow); if(p.x==-1) return 0; // simplex failed btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0); // a valid interior point btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1); btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0); btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3); btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2); isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1; checkit(t0);checkit(t1);checkit(t2);checkit(t3); for(j=0;j<m_tris.size();j++) { btHullTriangle *t=m_tris[j]; btAssert(t); btAssert(t->vmax<0); btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); t->vmax = maxdirsterid(verts,verts_count,n,allow); t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); } btHullTriangle *te; vlimit-=4; while(vlimit >0 && ((te=extrudable(epsilon)) != 0)) { int3 ti=*te; int v=te->vmax; btAssert(v != -1); btAssert(!isextreme[v]); // wtf we've already done this vertex isextreme[v]=1; //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already j=m_tris.size(); while(j--) { if(!m_tris[j]) continue; int3 t=*m_tris[j]; if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) { extrude(m_tris[j],v); } } // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle j=m_tris.size(); while(j--) { if(!m_tris[j]) continue; if(!hasvert(*m_tris[j],v)) break; int3 nt=*m_tris[j]; if(above(verts,nt,center,btScalar(0.01)*epsilon) || cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) ) { btHullTriangle *nb = m_tris[m_tris[j]->n[0]]; btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->id<j); extrude(nb,v); j=m_tris.size(); } } j=m_tris.size(); while(j--) { btHullTriangle *t=m_tris[j]; if(!t) continue; if(t->vmax>=0) break; btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); t->vmax = maxdirsterid(verts,verts_count,n,allow); if(isextreme[t->vmax]) { t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate. } else { t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); } } vlimit --; } return 1; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { #define facesInput prhs[0] #define verticesInput prhs[1] #define edgesOutput plhs[0] #define edgeLengthsOutput plhs[1] #define edgeUnitsOutput plhs[2] #define edgeCentersOutput plhs[3] #define edgeNormalsOutput plhs[4] #define faceNormalsOutput plhs[5] #define faceAreasOutput plhs[6] #define volumeOutput plhs[7] mxArray *faceCell, *edgesCell, *edgeCentersCell, *edgeLengthsCell, *edgeUnitsCell, *faceNormalCell, *edgeNormalsCell; double *face, *vertices, *edges, *edgeCenters, *edgeLengths, *edgeUnits, *faceNormal, *edgeNormals, *faceAreas, *volume; double tmp; mwIndex f, e, i; mwIndex currentVertexIdx, nextVertexIdx, edgeIdx; mwSize faceNumber, edgeNumber, vertexNumber; mwSize edgesOutputSize[EDGES_OUTPUT_DIM]; if (nrhs != 2) mexErrMsgTxt("There should be exactly two inputs, faces and vertices."); if (nlhs != 8) mexErrMsgTxt("There should be exactly 8 outputs. " "edges, edgeLengths, edgeCenters, edgeUnits, edgeCenters, " "edgeNormals, faceNormals."); if (!mxIsCell(facesInput)) mexErrMsgTxt("Input faces should be a cell array!"); if (!mxIsDouble(verticesInput)) mexErrMsgTxt("Input vertices should be a double matrix!"); faceNumber = mxGetNumberOfElements(facesInput); vertices = mxGetPr(verticesInput); vertexNumber = mxGetN(verticesInput); edgesOutputSize[0] = faceNumber; edgesOutputSize[1] = 1; edgesOutput = mxCreateCellArray(EDGES_OUTPUT_DIM, edgesOutputSize); edgeLengthsOutput = mxCreateCellArray(EDGES_OUTPUT_DIM, edgesOutputSize); edgeUnitsOutput = mxCreateCellArray(EDGES_OUTPUT_DIM, edgesOutputSize); edgeCentersOutput = mxCreateCellArray(EDGES_OUTPUT_DIM, edgesOutputSize); edgeNormalsOutput = mxCreateCellArray(EDGES_OUTPUT_DIM, edgesOutputSize); faceNormalsOutput = mxCreateCellArray(EDGES_OUTPUT_DIM, edgesOutputSize); faceAreasOutput = mxCreateDoubleMatrix(faceNumber, 1, mxREAL); faceAreas = mxGetPr(faceAreasOutput); volumeOutput = mxCreateDoubleMatrix(1, 1, mxREAL); volume = mxGetPr(volumeOutput); for (f = 0; f < faceNumber; f++) { faceCell = mxGetCell(facesInput, f); face = mxGetPr(faceCell); edgeNumber = (mwIndex)(mxGetN(faceCell)) - 1; // face is 1 by e + 1 array, the last entry is duplication of // the first one edgesCell = mxCreateDoubleMatrix(dim, edgeNumber, mxREAL); edges = mxGetPr(edgesCell); edgeCentersCell = mxCreateDoubleMatrix(dim, edgeNumber, mxREAL); edgeCenters = mxGetPr(edgeCentersCell); edgeLengthsCell = mxCreateDoubleMatrix(1, edgeNumber, mxREAL); edgeLengths = mxGetPr(edgeLengthsCell); edgeUnitsCell = mxCreateDoubleMatrix(dim, edgeNumber, mxREAL); edgeUnits = mxGetPr(edgeUnitsCell); edgeNormalsCell = mxCreateDoubleMatrix(dim, edgeNumber, mxREAL); edgeNormals = mxGetPr(edgeNormalsCell); faceNormalCell = mxCreateDoubleMatrix(dim, 1, mxREAL); faceNormal = mxGetPr(faceNormalCell); for (e = 0; e < edgeNumber; e++) { for (i = 0; i < dim; i++) { nextVertexIdx = (mwIndex)face[e+1] * dim + i; currentVertexIdx = (mwIndex)face[e] * dim + i; edgeIdx = dim * e + i; edgeCenters[edgeIdx] = (vertices[nextVertexIdx] + vertices[currentVertexIdx]) / 2; edges[edgeIdx] = vertices[nextVertexIdx] - vertices[currentVertexIdx]; } edgeLengths[e] = twoNorm(edges + e * dim, dim); for (i = 0; i < dim; i++) { edgeIdx = dim * e + i; edgeUnits[edgeIdx] = edges[edgeIdx] / edgeLengths[e]; } } cross(edgeUnits, edgeUnits + dim, faceNormal); mexPrint1dArray(faceNormal, dim); tmp = twoNorm(faceNormal, dim); divideScaler(faceNormal, dim, tmp); faceAreas[f] = calcFaceArea(vertices, vertexNumber, face, edgeNumber, faceNormal); for (e = 0; e < edgeNumber; e++){ cross(edgeUnits + e * dim, faceNormal, edgeNormals + e * dim); for (i = 0; i < dim; i++){ edgeNormals[e * dim + i] *= edgeLengths[e]; } } mxSetCell(edgesOutput, f, edgesCell); mxSetCell(edgeCentersOutput, f, edgeCentersCell); mxSetCell(edgeLengthsOutput, f, edgeLengthsCell); mxSetCell(edgeUnitsOutput, f, edgeUnitsCell); mxSetCell(faceNormalsOutput, f, faceNormalCell); mxSetCell(edgeNormalsOutput, f, edgeNormalsCell); } *volume = calcPolyVolumeCellFaces(faceAreas, vertices, facesInput, faceNormalsOutput); }
// Moller-Trumbore intersection float Model::intersect(const Point &r, const Vector &ray, IntersectionInfo &out) const { Vector o = {r.x, r.y, r.z}; Vector lb = bbtop; Vector rt = bbbottom; // based on https://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms/18459#18459 // r.dir is unit direction vector of ray Vector dirfrac; dirfrac.x = 1.0f / ray.x; dirfrac.y = 1.0f / ray.y; dirfrac.z = 1.0f / ray.z; // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner // r.org is origin of ray float t1 = (lb.x - o.x)*dirfrac.x; float t2 = (rt.x - o.x)*dirfrac.x; float t3 = (lb.y - o.y)*dirfrac.y; float t4 = (rt.y - o.y)*dirfrac.y; float t5 = (lb.z - o.z)*dirfrac.z; float t6 = (rt.z - o.z)*dirfrac.z; float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us if (tmax < 0) { return -1; } // if tmin > tmax, ray doesn't intersect AABB if (tmin > tmax) { return -1; } float closest = -1; bool notfound = true; int size = _faces.size(); for (int i = 0; i < size; ++i) { const Face &f = _faces[i]; Vector v3 = _vertices[f.x]; Vector v2 = _vertices[f.y]; Vector v1 = _vertices[f.z]; Vector e1 = v2-v1; Vector e2 = v3-v1; Vector p = cross(ray, e2); float det = dot(e1, p); if (fabs(det) < 0.000001f) { continue; } float inv_det = 1.f/det; Vector t = o - v1; float u = dot(t, p) * inv_det; if (u < 0.f || u > 1.f) { continue; } Vector q = cross(t, e1); float v = dot(ray, q) * inv_det; if (v < 0.f || v + u > 1.f) { continue; } float t2 = dot(e2, q) * inv_det; if (t2 > 0.0001f) { if (notfound || t2 < closest) { notfound = false; Vector sc = ray * t2; out.pos.x = o.x + sc.x; out.pos.y = o.y + sc.y; out.pos.z = o.z + sc.z; out.vertex = i; closest = t2; } } } return closest; }
void MiroWindow::keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; case 'i': case 'I': { char str[1024]; sprintf(str, "miro_%d.ppm", time(0)); if (g_camera->isOpenGL()) { unsigned char* buf = new unsigned char[g_image->width()*g_image->height()*3]; glReadPixels(0, 0, g_image->width(), g_image->height(), GL_RGB, GL_UNSIGNED_BYTE, buf); g_image->writePPM(str, buf, g_image->width(), g_image->height()); } else { g_image->writePPM(str); } break; } case 'r': case 'R': g_camera->setRenderer(Camera::RENDER_RAYTRACE); break; case 'g': case 'G': g_camera->setRenderer(Camera::RENDER_OPENGL); break; case '+': m_scaleFact *= 1.5; break; case '-': m_scaleFact /= 1.5; break; case 'w': case 'W': g_camera->setEye(g_camera->eye() + m_scaleFact*g_camera->viewDir()); break; case 's': case 'S': g_camera->setEye(g_camera->eye() - m_scaleFact*g_camera->viewDir()); break; case 'q': case 'Q': g_camera->setEye(g_camera->eye() + m_scaleFact*g_camera->up()); break; case 'z': case 'Z': g_camera->setEye(g_camera->eye() - m_scaleFact*g_camera->up()); break; case 'v': case 'V': g_scene->togglePDraw(); break; case 'b': case 'B': g_scene->toggleDraw(); break; case 'a': case 'A': { Vector3 vRight = cross(g_camera->viewDir(), g_camera->up()); g_camera->setEye(g_camera->eye() - m_scaleFact*vRight); break; } case 'd': case 'D': { Vector3 vRight = cross(g_camera->viewDir(), g_camera->up()); g_camera->setEye(g_camera->eye() + m_scaleFact*vRight); break; } break; default: break; } glutPostRedisplay(); }
void Boonas::doExtrude(QString num, QString filename) // extrudes and writes whilst extruding { float n = num.toFloat(); float x, y, z, w; int numSides; Point* pa; Point* pb; Point* pc; Point pd; Point firstPoint; Vector va; Vector vb; Vector vn; bool again = true; filename.append(".poly"); QFile* theDestination; theDestination = new QFile(filename); theDestination -> remove(); theDestination -> open(QIODevice::ReadWrite | QIODevice::Text); QTextStream outStream( theDestination ); do // do this loop while ther is more in orig { cursor = orig -> getCurrent(); // cursor is current cursor -> reset(); //change color respectively for each object x = cursor -> getX(); y = cursor -> getY(); z = cursor -> getZ(); if(colorValue != 0) { delete colorValue; colorValue = 0; } colorValue = new Point(x, y, z); cursor -> advance(); if(!(orig -> isNotLast())) { again = false; } // get initial points in order to get unit vectior x = cursor -> getX(); y = cursor -> getY(); z = cursor -> getZ(); pa = new Point(x, y, z); cursor -> advance(); x = cursor -> getX(); y = cursor -> getY(); z = cursor -> getZ(); pb = new Point(x, y, z); cursor -> advance(); x = cursor -> getX(); y = cursor -> getY(); z = cursor -> getZ(); pc = new Point(x, y, z); va = *pa - *pb; vb = *pb - *pc; vn = cross(va, vb); vn.normalize(); //vn = vn * -1.0; // flip it vn = vn * n; // vn is vector! cursor -> reset(); // reset cursor so 2nd iteration starts from begining // skip color vector cursor -> advance(); numSides = 0; outStream << "newObject" << endl; // put out color vector outStream << colorValue -> x() << " " << colorValue -> y() << " "<< colorValue -> z() << " 1" << endl; // first iteration, copy orig polygon, count number of sides do { numSides++; //qDebug() << "Test results"; x = cursor -> getX(); // get point y = cursor -> getY(); z = cursor -> getZ(); w = cursor -> getW(); outStream << x << " " << y << " " << z << " " << w << endl; cursor -> advance(); } while(cursor -> hasNext()); // run through the points and mult!k numSides++; x = cursor -> getX(); // get point y = cursor -> getY(); z = cursor -> getZ(); w = cursor -> getW(); outStream << x << " " << y << " " << z << " " << w << endl; //numsides is the number of points cursor -> reset(); // skip color vector cursor -> advance(); // second iteration, copy the top polygon outStream << "newObject" << endl; // put out color vector outStream << colorValue -> x() << " " << colorValue -> y() << " "<< colorValue -> z() << " 1" << endl; // second iteration, copy orig polygon to traversed points, count number of sides do { //qDebug() << "Test results"; x = cursor -> getX(); // get point y = cursor -> getY(); z = cursor -> getZ(); w = cursor -> getW(); delete pa; pa = new Point(x, y, z); pd = *pa + vn; outStream << pd.x() << " " << pd.y() << " " << pd.z() << " " << w << endl; cursor -> advance(); } while(cursor -> hasNext()); // run through the points and mult!k x = cursor -> getX(); // get point y = cursor -> getY(); z = cursor -> getZ(); w = cursor -> getW(); delete pa; pa = new Point(x, y, z); pd = *pa + vn; outStream << pd.x() << " " << pd.y() << " " << pd.z() << " " << w << endl; // start next run time for the sides yo cursor -> reset(); // skip color vector cursor -> advance(); for(int i = 0; i < (numSides - 1); i++) // run through this next bit for each side of the polygon except the last side { cursor -> reset(); // skip color vector cursor -> advance(); outStream << "newObject" << endl; // put out color vector outStream << colorValue -> x() << " " << colorValue -> y() << " "<< colorValue -> z() << " 1" << endl; for(int j = 0; j < i; j++) // advance cursor to get it to desired point { cursor -> advance(); } x = cursor -> getX(); y = cursor -> getY(); z = cursor -> getZ(); w = cursor -> getW(); outStream << x << " " << y << " " << z << " " << w << endl; // out put orig point delete pa; pa = new Point(x, y, z); pd = *pa + vn; outStream << pd.x() << " " << pd.y() << " " << pd.z() << " " << w << endl; // out put mod point a cursor -> advance(); //advance to next point; x = cursor -> getX(); y = cursor -> getY(); z = cursor -> getZ(); w = cursor -> getW(); delete pa; pa = new Point(x, y, z); pd = *pa + vn; outStream << pd.x() << " " << pd.y() << " " << pd.z() << " " << w << endl; // out put mod point b outStream << x << " " << y << " " << z << " " << w << endl; // out put last point } // now we only have to deal with the last side outStream << "newObject" << endl; // put out color vector outStream << colorValue -> x() << " " << colorValue -> y() << " "<< colorValue -> z() << " 1" << endl; cursor -> reset(); // skip color vector cursor -> advance(); for(int i = 0; i < numSides; i++) { cursor -> advance(); // advance cursor to last point; } x = cursor -> getX(); y = cursor -> getY(); z = cursor -> getZ(); w = cursor -> getW(); outStream << x << " " << y << " " << z << " " << w << endl; // out put first point delete pa; pa = new Point(x, y, z); pd = *pa + vn; outStream << pd.x() << " " << pd.y() << " " << pd.z() << " " << w << endl; // out put mod point a cursor -> reset(); // skip color vector cursor -> advance(); x = cursor -> getX(); y = cursor -> getY(); z = cursor -> getZ(); w = cursor -> getW(); delete pa; pa = new Point(x, y, z); pd = *pa + vn; outStream << pd.x() << " " << pd.y() << " " << pd.z() << " " << w << endl; // out put mod point b outStream << x << " " << y << " " << z << " " << w << endl; // out put last point orig -> advance(); // advance what were working with } while(again); theDestination -> close(); delete theDestination; delete pa; delete pb; delete pc; }
Model::Model(const std::string &filename, const Vector &off) : bbtop({0,0,0}), bbbottom({0,0,0}) { FILE *f = fopen(filename.c_str(), "r"); int verts, faces; fscanf(f, "# %d %d\n", &verts, &faces); for (int i = 0; i < verts; ++i) { float x,y,z; fscanf(f, "v %f %f %f\n", &x, &y, &z); x += off.x; y += off.y; z += off.z; if (i == 0 || x > bbtop.x) { bbtop.x = x; } if (i == 0 || y > bbtop.y) { bbtop.y = y; } if (i == 0 || z > bbtop.z) { bbtop.z = z; } if (i == 0 || x < bbbottom.x) { bbbottom.x = x; } if (i == 0 || y < bbbottom.y) { bbbottom.y = y; } if (i == 0 || z < bbbottom.z) { bbbottom.z = z; } _vertices.push_back({x,y,z}); } for (int i = 0; i < faces; ++i) { int x,y,z; fscanf(f, "f %d %d %d\n", &x, &y, &z); x--; y--; z--; //Based on https://www.opengl.org/wiki/Calculating_a_Surface_Normal Vector norm; Vector v1 = _vertices[x]; Vector v2 = _vertices[y]; Vector v3 = _vertices[z]; Vector u = v2 - v3; Vector v = v1 - v3; norm = normalize(cross(v,u)); _faces.push_back({x,y,z, norm}); } fclose(f); mat_ambient[0] = 0.7; mat_ambient[1] = 0.7; mat_ambient[2] = 0.7; mat_diffuse[0] = 0; mat_diffuse[1] = 0; mat_diffuse[2] = 1; mat_specular[0] = 1; mat_specular[1] = 1; mat_specular[2] = 1; mat_shineness = 30; reflectance = 0.5; transparency = 0.5; }
// it works in the sense that it produces a perpendicular-to-everyting vector, // but it has not been tested whether it points in the "right" direction. float4 gcross(float4 p, float4 q, float4 r) { return float4(dot(p.yzw, cross(q.yzw, r.yzw)), -dot(p.xzw, cross(q.xzw, r.xzw)), dot(p.xyw, cross(q.xyw, r.xyw)), -dot(p.xyz, cross(q.xyz, r.xyz))); }
float determinant(mat4 p) { return dot(p.v[0], float4(dot(p.v[1].yzw, cross(p.v[2].yzw, p.v[3].yzw)), -dot(p.v[1].xzw, cross(p.v[2].xzw, p.v[3].xzw)), dot(p.v[1].xyw, cross(p.v[2].xyw, p.v[3].xyw)), -dot(p.v[1].xyz, cross(p.v[2].xyz, p.v[3].xyz)))); }
float determinant(mat3 p) { return dot(p.v[0], cross(p.v[1], p.v[2])); }
void DebugHooks::drawFaceLoopWireframe(const std::vector<const carve::geom3d::Vector *> &face_loop, const carve::geom3d::Vector &normal, float r, float g, float b, float a, bool inset) { glDisable(GL_DEPTH_TEST); const size_t S = face_loop.size(); double INSET = 0.005; if (inset) { glColor4f(r, g, b, a / 2.0); glBegin(GL_LINE_LOOP); for (size_t i = 0; i < S; ++i) { size_t i_pre = (i + S - 1) % S; size_t i_post = (i + 1) % S; carve::geom3d::Vector v1 = (*face_loop[i] - *face_loop[i_pre]).normalized(); carve::geom3d::Vector v2 = (*face_loop[i] - *face_loop[i_post]).normalized(); carve::geom3d::Vector n1 = cross(normal, v1); carve::geom3d::Vector n2 = cross(v2, normal); carve::geom3d::Vector v = *face_loop[i]; carve::geom3d::Vector p1 = v + INSET * n1; carve::geom3d::Vector p2 = v + INSET * n2; carve::geom3d::Vector i1 , i2; double mu1, mu2; carve::geom3d::Vector p; if (carve::geom3d::rayRayIntersection(carve::geom3d::Ray(v1, p1), carve::geom3d::Ray(v2, p2), i1, i2, mu1, mu2)) { p = (i1 + i2) / 2; } else { p = (p1 + p2) / 2; } glVertex(&p); } glEnd(); } glColor4f(r, g, b, a); glBegin(GL_LINE_LOOP); for (unsigned i = 0; i < S; ++i) { glVertex(face_loop[i]); } glEnd(); glColor4f(r, g, b, a); glPointSize(3.0); glBegin(GL_POINTS); for (unsigned i = 0; i < S; ++i) { carve::geom3d::Vector p = *face_loop[i]; glVertex(face_loop[i]); } glEnd(); glEnable(GL_DEPTH_TEST); }
MLIB_INLINE mlib::Plane<PLANE,P,V,L>::Plane(const P &p, const V&v1, const V&v2) : _d(0) { *this = Plane<PLANE,P,V,L>(p, cross(v1, v2)); }