static void display(void) { #ifdef _WIN32 LARGE_INTEGER t1, t2, freq; QueryPerformanceCounter(&t1); #else struct timespec t1, t2; clock_gettime(CLOCK_MONOTONIC, &t1); #endif glClear(GL_COLOR_BUFFER_BIT); if (draw_normal) { triangle_normal(); } else { triangle_normal(); } glFinish(); #ifdef _WIN32 QueryPerformanceCounter(&t2); QueryPerformanceFrequency(&freq); printf("one frame: %lf.\n", (double)(t2.QuadPart - t1.QuadPart) / freq.QuadPart); #else clock_gettime(CLOCK_MONOTONIC, &t2); printf("one frame: %lf.\n", ((double)(t2.tv_sec - t1.tv_sec) + ((double)(t2.tv_nsec - t1.tv_nsec) / 1e9))); #endif checkError("display"); }
void shape_smooth_frames(Shape* shape) { if(is<TriangleMesh>(shape)) { auto mesh = cast<TriangleMesh>(shape); mesh->norm.resize(mesh->pos.size(),zero3f); for(auto f : mesh->triangle) for(auto vid : f) mesh->norm[vid] += triangle_normal(mesh->pos[f.x],mesh->pos[f.y],mesh->pos[f.z]); for(auto &n : mesh->norm) n = normalize(n); } else if(is<Mesh>(shape)) { auto mesh = cast<Mesh>(shape); mesh->norm.resize(mesh->pos.size(),zero3f); for(auto f : mesh->triangle) for(auto vid : f) mesh->norm[vid] += triangle_normal(mesh->pos[f.x],mesh->pos[f.y],mesh->pos[f.z]); for(auto f : mesh->quad) for(auto vid : f) mesh->norm[vid] += quad_normal(mesh->pos[f.x],mesh->pos[f.y],mesh->pos[f.z],mesh->pos[f.w]); for(auto &n : mesh->norm) n = normalize(n); } }
void MxPropSlim::discontinuity_constraint(MxVertexID i, MxVertexID j, MxFaceID f) { Vec3 org(m->vertex(i)), dest(m->vertex(j)); Vec3 e = dest - org; Vec3 v1(m->vertex(m->face(f)(0))); Vec3 v2(m->vertex(m->face(f)(1))); Vec3 v3(m->vertex(m->face(f)(2))); Vec3 n = triangle_normal(v1,v2,v3); Vec3 n2 = e ^ n; unitize(n2); MxQuadric3 Q3(n2, -(n2*org)); Q3 *= boundary_weight; if( weighting_policy == MX_WEIGHT_AREA || weighting_policy == MX_WEIGHT_AREA_AVG ) { Q3.set_area(norm2(e)); Q3 *= Q3.area(); } MxQuadric Q(Q3, dim()); quadric(i) += Q; quadric(j) += Q; }
void prepare_gravity(Real_t nv[], Real_t rij[], Real_t cm[], int numfaces, std::vector<unsigned int>& fi, std::vector<float>& ev) { for(int i = 0; i < numfaces; i++) { double a[3], b[3], c[3], d[3], nu[3]; int ain = fi[i*3+0]; int bin = fi[i*3+1]; int cin = fi[i*3+2]; a[0] = ev[ain*3+0]; a[1] = ev[ain*3+1]; a[2] = ev[ain*3+2]; b[0] = ev[bin*3+0]; b[1] = ev[bin*3+1]; b[2] = ev[bin*3+2]; c[0] = ev[cin*3+0]; c[1] = ev[cin*3+1]; c[2] = ev[cin*3+2]; d[0] = (a[0]+b[0]+c[0])/3.0; d[1] = (a[1]+b[1]+c[1])/3.0; d[2] = (a[2]+b[2]+c[2])/3.0; // face center cm[i*3+0] = d[0]; cm[i*3+1] = d[1]; cm[i*3+2] = d[2]; triangle_normal(a, b, c, nu); nv[i*3+0] = nu[0]; nv[i*3+1] = nu[1]; nv[i*3+2] = nu[2]; rij[(i*4+0)*3+0] = a[0]; rij[(i*4+0)*3+1] = a[1]; rij[(i*4+0)*3+2] = a[2]; rij[(i*4+1)*3+0] = b[0]; rij[(i*4+1)*3+1] = b[1]; rij[(i*4+1)*3+2] = b[2]; rij[(i*4+2)*3+0] = c[0]; rij[(i*4+2)*3+1] = c[1]; rij[(i*4+2)*3+2] = c[2]; rij[(i*4+3)*3+0] = a[0]; rij[(i*4+3)*3+1] = a[1]; rij[(i*4+3)*3+2] = a[2]; } }
frame3f trianglemesh_frame(TriangleMesh* mesh, int elementid, const vec2f& uv) { auto f = mesh->triangle[elementid]; frame3f ff; ff.x = normalize(mesh->pos[f.y]-mesh->pos[f.x]); ff.y = normalize(mesh->pos[f.z]-mesh->pos[f.x]); if(not mesh->norm.empty()) ff.z = normalize(interpolate_baricentric_triangle(mesh->norm, f, uv)); else ff.z = triangle_normal(mesh->pos[f.x], mesh->pos[f.y], mesh->pos[f.z]); ff.o = interpolate_baricentric_triangle(mesh->pos, f, uv); ff = orthonormalize(ff); return ff; }
frame3f mesh_frame(Mesh* mesh, int elementid, const vec2f& uv) { auto f = mesh_triangle_face(mesh,elementid); frame3f ff; ff.x = normalize(mesh->pos[f.y]-mesh->pos[f.x]); ff.y = normalize(mesh->pos[f.z]-mesh->pos[f.x]); if(not mesh->norm.empty()) ff.z = normalize(interpolate_baricentric_triangle(mesh->norm,f,uv)); else if(elementid < mesh->triangle.size()) ff.z = triangle_normal(mesh->pos[f.x], mesh->pos[f.y], mesh->pos[f.z]); else { auto f = mesh->quad[(elementid-mesh->triangle.size())/2]; ff.z = quad_normal(mesh->pos[f.x], mesh->pos[f.y], mesh->pos[f.z], mesh->pos[f.w]); } ff.o = interpolate_baricentric_triangle(mesh->pos,f,uv); ff = orthonormalize(ff); return ff; }
void glutils_draw_triangle_lines(const vec3f& v0, const vec3f& v1, const vec3f& v2) { glsCheckError(); glBegin(GL_LINE_LOOP); glsNormal(triangle_normal(v0, v1, v2)); glsTexCoord(zero2f); glsVertex(v0); glsTexCoord(x2f); glsVertex(v1); glsTexCoord(y2f); glsVertex(v2); glEnd(); glsCheckError(); }
int tri_tet_disjoint(ptriangle tri, ptetra tet) { arr3 normals[4]; /* * First check facet normals for separating axes. * This covers face-face and face-edge. */ triangle_normal(tri,normals[0]); if (tri_tet_separation_axis(tri,tet,normals[0]) == DISJOINT) return DISJOINT; tetra_normals(tet, normals); if (tri_tet_separation_axes(tri,tet,normals, 4) == DISJOINT) return DISJOINT; /* * Check all cross produts of edges between triangle and tetrahedron as separating axis. * This covers edge-edge. * * The six edges of a tet are given by edges. * Indication how edge 'x' is made up.. for example edge[0] = vertex[1] - vertex[0] */ int edges[6][2] = {{1,0},{2,0},{2,1}, //Base triangle (first three) {3,0},{3,1},{3,2}}; //Edges from base to apex //Test all the edges arr3 edge_a, edge_b; for (int i = 0; i < 3; i++) { subArr3(tri->vertices[edges[i][0]], tri->vertices[edges[i][1]], edge_a); for (int j = 0; j < 6; j++) { subArr3(tet->vertices[edges[j][0]], tet->vertices[edges[j][1]], edge_b); //Check crossproduct of edge_a and edge_b as seperating axis arr3 perp_axis; crossArr3(edge_a,edge_b, perp_axis); if (zeroArr3(perp_axis)) { /* * Edges are parallel thus lie in some plane. * Calculate another vector in this plane and try the cross product * between those vectors as separating axis */ subArr3(tri->vertices[edges[i][0]], tet->vertices[edges[j][0]], edge_b); crossArr3(edge_a,edge_b, perp_axis); if (zeroArr3(perp_axis)) //Still zero, all points lie on the same line, not a separation axis, IS TRUE? continue; } if (tri_tet_separation_axis(tri,tet, perp_axis) == DISJOINT) return DISJOINT; } } return INTERSECT; //No separation axis found, thus we are not disjoint }
int triangle_plane( Vec4 *out, const Vec3 *v1, const Vec3 *v2, const Vec3 *v3 ) { Vec3 n; if( !triangle_normal( &n, v1, v2, v3 ) ) return 0; out->elt[0] = n.elt[0]; out->elt[1] = n.elt[1]; out->elt[2] = n.elt[2]; out->elt[3] = -( mxv_dot(n.elt, v1->elt, 3) ); return 1; } /* end function triangle_plane */
int in_triangle(Point point, Triangle tri) { /* This implementation is based on "Graphics Gems" p390 */ int i1, i2; Normal norm; float u0, v0, u1, v1, u2, v2; float alpha, beta; int inter = 0; triangle_normal(tri, &norm); if(fabs(norm[0]) >= fabs(norm[1]) && fabs(norm[0]) >= fabs(norm[2])) { i1 = 1; i2 = 2; }else if(fabs(norm[1]) >= fabs(norm[0]) && fabs(norm[1]) >= fabs(norm[2])) { i1 = 0; i2 = 2; }else { i1 = 0; i2 = 1; } u0 = point[i1] - tri.vert[0][i1]; v0 = point[i2] - tri.vert[0][i2]; u1 = tri.vert[1][i1] - tri.vert[0][i1]; v1 = tri.vert[1][i2] - tri.vert[0][i2]; u2 = tri.vert[2][i1] - tri.vert[0][i1]; v2 = tri.vert[2][i2] - tri.vert[0][i2]; if(u1 == 0) { beta = u0/u2; if((beta >= 0.) && (beta <= 1.)) { alpha = (v0 - beta*v2)/v1; inter = ((alpha >= 0.) && ((alpha+beta) <= 1.))? 1:0; } } else { beta = (v0*u1 - u0*v1)/(v2*u1 - u2*v1); if ((beta >= 0.)&&(beta <= 1.)) { alpha = (u0 - beta*u2)/u1; inter = ((alpha >= 0) && ((alpha+beta) <= 1.))? 1:0; } } return inter; }
static void triangle(void) { GLint tmpFramebuffer; GLint tmpRenderbuffer; GLint viewport[4]; GLenum err; checkError("triangle enter"); glGetIntegerv(GL_VIEWPORT, viewport); glGenFramebuffers(1, (GLuint*)&tmpFramebuffer); glGenRenderbuffers(1, (GLuint*)&tmpRenderbuffer); glBindFramebuffer(GL_FRAMEBUFFER, tmpFramebuffer); glBindRenderbuffer(GL_RENDERBUFFER, tmpRenderbuffer); glRenderbufferStorageMultisample(GL_RENDERBUFFER, 16, GL_RGBA, viewport[2], viewport[3]); err = glGetError(); if (err != GL_NO_ERROR) { fprintf(stderr, "error occurs: %X.\n", err); exit(1); } glBindRenderbuffer(GL_RENDERBUFFER, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, tmpRenderbuffer); if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER)) { fprintf(stderr, "fbo is not completed.\n"); exit(1); } triangle_normal(); glBindFramebuffer(GL_FRAMEBUFFER, 0); // blit here glBindFramebuffer(GL_READ_FRAMEBUFFER, tmpFramebuffer); glBlitFramebuffer(0, 0, viewport[2], viewport[3], 0, 0, viewport[2], viewport[3], GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glDeleteFramebuffers(1, (GLuint*)&tmpFramebuffer); glDeleteRenderbuffers(1, (GLuint*)&tmpRenderbuffer); checkError("triangle"); }
static void append_triangles(struct groupdata *groupdata, buffer *buffer) { triangle *triangles = buffer_data(buffer); size_t trianglecount = buffer_count(buffer, sizeof(struct triangle)); for (size_t i = 0; i < trianglecount; ++i) { vec3 normal; triangle_normal(&normal, &triangles[i]); vec3_normalize(&normal, &normal); vertex vertices[3] = { {normal, triangles[i].a}, {normal, triangles[i].b}, {normal, triangles[i].c} }; append_buffer(groupdata->vertices, vertices, sizeof(vertices)); } }
float intersect_triangle(iRay ray, Triangle tri, Point point) { Normal norm; /* triangle normal */ float t, fz, fm; int i; triangle_normal(tri, &norm); fz = 0; fm = 0; for (i = 0; i < 3; i++) { fz += norm[i] * (tri.vert[0][i]-ray.orig[i]); fm += norm[i] * ray.dir[i]; } if(fm == 0.0) return -1; t = fz / fm; /* don't consider negative parameter any more */ if(t < 0.0) return t; for(i = 0; i < 3; i++) point[i] = ray.orig[i] + ray.dir[i] * t; #ifdef _DEBUG printf("intersection point: (%f, %f, %f)\n", point[0], point[1], point[2]); #endif if(in_triangle(point, tri)) return t; return -1; }
bool EdgeCollapser::collapse_edge_introduces_normal_inversion( size_t source_vertex, size_t destination_vertex, size_t edge_index, const Vec3d& vertex_new_position ) { // Get the set of triangles which are going to be deleted std::vector< size_t >& triangles_incident_to_edge = m_surf.m_mesh.m_edge_to_triangle_map[edge_index]; // Get the set of triangles which move because of this motion std::vector<size_t> moving_triangles; for ( size_t i = 0; i < m_surf.m_mesh.m_vertex_to_triangle_map[source_vertex].size(); ++i ) { moving_triangles.push_back( m_surf.m_mesh.m_vertex_to_triangle_map[source_vertex][i] ); } for ( size_t i = 0; i < m_surf.m_mesh.m_vertex_to_triangle_map[destination_vertex].size(); ++i ) { moving_triangles.push_back( m_surf.m_mesh.m_vertex_to_triangle_map[destination_vertex][i] ); } // // check for normal inversion // for ( size_t i = 0; i < moving_triangles.size(); ++i ) { // Disregard triangles which will end up being deleted - those triangles incident to the collapsing edge. bool triangle_will_be_deleted = false; for ( size_t j = 0; j < triangles_incident_to_edge.size(); ++j ) { if ( moving_triangles[i] == triangles_incident_to_edge[j] ) { triangle_will_be_deleted = true; break; } } if ( triangle_will_be_deleted ) { continue; } const Vec3st& current_triangle = m_surf.m_mesh.get_triangle( moving_triangles[i] ); Vec3d old_normal = m_surf.get_triangle_normal( current_triangle ); Vec3d new_normal; double new_area; if ( current_triangle[0] == source_vertex || current_triangle[0] == destination_vertex ) { new_normal = triangle_normal( vertex_new_position, m_surf.get_position(current_triangle[1]), m_surf.get_position(current_triangle[2]) ); new_area = triangle_area( vertex_new_position, m_surf.get_position(current_triangle[1]), m_surf.get_position(current_triangle[2]) ); } else if ( current_triangle[1] == source_vertex || current_triangle[1] == destination_vertex ) { new_normal = triangle_normal( m_surf.get_position(current_triangle[0]), vertex_new_position, m_surf.get_position(current_triangle[2]) ); new_area = triangle_area( m_surf.get_position(current_triangle[0]), vertex_new_position, m_surf.get_position(current_triangle[2]) ); } else { assert( current_triangle[2] == source_vertex || current_triangle[2] == destination_vertex ); new_normal = triangle_normal( m_surf.get_position(current_triangle[0]), m_surf.get_position(current_triangle[1]), vertex_new_position ); new_area = triangle_area( m_surf.get_position(current_triangle[0]), m_surf.get_position(current_triangle[1]), vertex_new_position ); } if ( dot( new_normal, old_normal ) < 1e-5 ) { if ( m_surf.m_verbose ) { std::cout << "collapse edge introduces normal inversion" << std::endl; } g_stats.add_to_int( "EdgeCollapser:collapse_normal_inversion", 1 ); return true; } if ( new_area < m_surf.m_min_triangle_area ) { if ( m_surf.m_verbose ) { std::cout << "collapse edge introduces tiny triangle area" << std::endl; } g_stats.add_to_int( "EdgeCollapser:collapse_degenerate_triangle", 1 ); return true; } } return false; }
/* create a smoothed version of the given Object by computing average normal vectors for the vertexes */ static ObjectSmooth *create_ObjectSmooth( Object *obj ) { int t, v, i; Vector *t_normal = (Vector *) malloc( obj->num_triangle*sizeof(Vector) ); ObjectSmooth *ret = (ObjectSmooth *) malloc( sizeof( ObjectSmooth ) ); /* fill in vertexes and triangles */ ret->num_vertex = obj->num_vertex; ret->num_triangle = obj->num_triangle; ret->vertex = (Vector *) malloc( obj->num_vertex * sizeof( Vector ) ); ret->normal = (Vector *) malloc( obj->num_vertex * sizeof( Vector ) ); ret->triangle = (Triangle *) malloc( obj->num_triangle * sizeof( Triangle ) ); for (v=0; v<obj->num_vertex; ++v) { ret->vertex[v] = obj->vertex[v]; } for (t=0; t<obj->num_triangle; ++t) { ret->triangle[t] = obj->triangle[t]; } /* create normals (triangles) */ for (t=0; t<ret->num_triangle; ++t) { triangle_normal( &ret->vertex[ret->triangle[t].i[0]], &ret->vertex[ret->triangle[t].i[1]], &ret->vertex[ret->triangle[t].i[2]], &t_normal[t] ); } /* create normals (vertex) by averaging triangle normals at vertex */ for (v=0; v<ret->num_vertex; ++v) { vector_clear( &ret->normal[v] ); for (t=0; t<ret->num_triangle; ++t) { for (i=0; i<3; ++i) { if (ret->triangle[t].i[i] == v) { vector_add( &ret->normal[v], &t_normal[t] ); } } } /* as we have only a half sphere we force the normals at the bortder to be perpendicular to z. the simple algorithm above makes an error here. */ if (fabs(ret->vertex[v].z) < 0.0001) { ret->normal[v].z = 0.0; } vector_normalize( &ret->normal[v] ); } free( t_normal ); return ret; }