bool readObjFile(SimpleMesh<Vector, Face3>& mesh, const std::string& fileName) { // Attempt to read file. std::ifstream file(fileName.c_str()); if(!file) { std::cerr << "Error reading file!" << std::endl; return false; } // Clear the mesh data structure. mesh = SimpleMesh<Vector, Face3>(); // Fill the mesh data structure. std::string line; while ( std::getline(file, line) ) { std::stringstream ss; ss << line; char type; ss >> type; if(type=='v') { double x, y, z; ss >> x >> y >> z; mesh.vertices().push_back(Vector(x, y, z)); } if(type=='f') { size_t a, b, c; ss >> a >> b >> c; mesh.faces().push_back(Face3(a-1, b-1, c-1)); }
inline void append_face(uint32_t a, uint32_t b, uint32_t c){ append_face(Face3(a, b, c)); }
static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z, PoolVector<Face3> &p_faces) { ERR_FAIL_INDEX(x, len_x); ERR_FAIL_INDEX(y, len_y); ERR_FAIL_INDEX(z, len_z); if (p_cell_status[x][y][z] & _CELL_EXTERIOR) return; /* static const Vector3 vertices[8]={ Vector3(0,0,0), Vector3(0,0,1), Vector3(0,1,0), Vector3(0,1,1), Vector3(1,0,0), Vector3(1,0,1), Vector3(1,1,0), Vector3(1,1,1), }; */ #define vert(m_idx) Vector3((m_idx & 4) >> 2, (m_idx & 2) >> 1, m_idx & 1) static const uint8_t indices[6][4] = { { 7, 6, 4, 5 }, { 7, 3, 2, 6 }, { 7, 5, 1, 3 }, { 0, 2, 3, 1 }, { 0, 1, 5, 4 }, { 0, 4, 6, 2 }, }; /* {0,1,2,3}, {0,1,4,5}, {0,2,4,6}, {4,5,6,7}, {2,3,7,6}, {1,3,5,7}, {0,2,3,1}, {0,1,5,4}, {0,4,6,2}, {7,6,4,5}, {7,3,2,6}, {7,5,1,3}, */ for (int i = 0; i < 6; i++) { Vector3 face_points[4]; int disp_x = x + ((i % 3) == 0 ? ((i < 3) ? 1 : -1) : 0); int disp_y = y + (((i - 1) % 3) == 0 ? ((i < 3) ? 1 : -1) : 0); int disp_z = z + (((i - 2) % 3) == 0 ? ((i < 3) ? 1 : -1) : 0); bool plot = false; if (disp_x < 0 || disp_x >= len_x) plot = true; if (disp_y < 0 || disp_y >= len_y) plot = true; if (disp_z < 0 || disp_z >= len_z) plot = true; if (!plot && (p_cell_status[disp_x][disp_y][disp_z] & _CELL_EXTERIOR)) plot = true; if (!plot) continue; for (int j = 0; j < 4; j++) face_points[j] = vert(indices[i][j]) + Vector3(x, y, z); p_faces.push_back( Face3( face_points[0], face_points[1], face_points[2])); p_faces.push_back( Face3( face_points[2], face_points[3], face_points[0])); } }
Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) { ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); ERR_EXPLAIN("Can't unwrap mesh with blend shapes"); ERR_FAIL_COND_V(blend_shapes.size() != 0, ERR_UNAVAILABLE); Vector<float> vertices; Vector<float> normals; Vector<int> indices; Vector<int> face_materials; Vector<float> uv; Vector<Pair<int, int> > uv_index; Vector<ArrayMeshLightmapSurface> surfaces; for (int i = 0; i < get_surface_count(); i++) { ArrayMeshLightmapSurface s; s.primitive = surface_get_primitive_type(i); if (s.primitive != Mesh::PRIMITIVE_TRIANGLES) { ERR_EXPLAIN("Only triangles are supported for lightmap unwrap"); ERR_FAIL_V(ERR_UNAVAILABLE); } s.format = surface_get_format(i); if (!(s.format & ARRAY_FORMAT_NORMAL)) { ERR_EXPLAIN("Normals are required for lightmap unwrap"); ERR_FAIL_V(ERR_UNAVAILABLE); } Array arrays = surface_get_arrays(i); s.material = surface_get_material(i); s.vertices = SurfaceTool::create_vertex_array_from_triangle_arrays(arrays); PoolVector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX]; int vc = rvertices.size(); PoolVector<Vector3>::Read r = rvertices.read(); PoolVector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL]; PoolVector<Vector3>::Read rn = rnormals.read(); int vertex_ofs = vertices.size() / 3; vertices.resize((vertex_ofs + vc) * 3); normals.resize((vertex_ofs + vc) * 3); uv_index.resize(vertex_ofs + vc); for (int j = 0; j < vc; j++) { Vector3 v = p_base_transform.xform(r[j]); Vector3 n = p_base_transform.basis.xform(rn[j]).normalized(); vertices[(j + vertex_ofs) * 3 + 0] = v.x; vertices[(j + vertex_ofs) * 3 + 1] = v.y; vertices[(j + vertex_ofs) * 3 + 2] = v.z; normals[(j + vertex_ofs) * 3 + 0] = n.x; normals[(j + vertex_ofs) * 3 + 1] = n.y; normals[(j + vertex_ofs) * 3 + 2] = n.z; uv_index[j + vertex_ofs] = Pair<int, int>(i, j); } PoolVector<int> rindices = arrays[Mesh::ARRAY_INDEX]; int ic = rindices.size(); if (ic == 0) { for (int j = 0; j < vc / 3; j++) { if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) continue; indices.push_back(vertex_ofs + j * 3 + 0); indices.push_back(vertex_ofs + j * 3 + 1); indices.push_back(vertex_ofs + j * 3 + 2); face_materials.push_back(i); } } else { PoolVector<int>::Read ri = rindices.read(); for (int j = 0; j < ic / 3; j++) { if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) continue; indices.push_back(vertex_ofs + ri[j * 3 + 0]); indices.push_back(vertex_ofs + ri[j * 3 + 1]); indices.push_back(vertex_ofs + ri[j * 3 + 2]); face_materials.push_back(i); } } surfaces.push_back(s); } //unwrap float *gen_uvs; int *gen_vertices; int *gen_indices; int gen_vertex_count; int gen_index_count; int size_x; int size_y; bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), face_materials.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y); if (!ok) { return ERR_CANT_CREATE; } //remove surfaces while (get_surface_count()) { surface_remove(0); } //create surfacetools for each surface.. Vector<Ref<SurfaceTool> > surfaces_tools; for (int i = 0; i < surfaces.size(); i++) { Ref<SurfaceTool> st; st.instance(); st->begin(Mesh::PRIMITIVE_TRIANGLES); st->set_material(surfaces[i].material); surfaces_tools.push_back(st); //stay there } print_line("gen indices: " + itos(gen_index_count)); //go through all indices for (int i = 0; i < gen_index_count; i += 3) { ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_index.size(), ERR_BUG); ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_index.size(), ERR_BUG); ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_index.size(), ERR_BUG); ERR_FAIL_COND_V(uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 1]]].first || uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); int surface = uv_index[gen_vertices[gen_indices[i + 0]]].first; for (int j = 0; j < 3; j++) { SurfaceTool::Vertex v = surfaces[surface].vertices[uv_index[gen_vertices[gen_indices[i + j]]].second]; if (surfaces[surface].format & ARRAY_FORMAT_COLOR) { surfaces_tools[surface]->add_color(v.color); } if (surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { surfaces_tools[surface]->add_uv(v.uv); } if (surfaces[surface].format & ARRAY_FORMAT_NORMAL) { surfaces_tools[surface]->add_normal(v.normal); } if (surfaces[surface].format & ARRAY_FORMAT_TANGENT) { Plane t; t.normal = v.tangent; t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; surfaces_tools[surface]->add_tangent(t); } if (surfaces[surface].format & ARRAY_FORMAT_BONES) { surfaces_tools[surface]->add_bones(v.bones); } if (surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { surfaces_tools[surface]->add_weights(v.weights); } Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); surfaces_tools[surface]->add_uv2(uv2); surfaces_tools[surface]->add_vertex(v.vertex); } } //free stuff ::free(gen_vertices); ::free(gen_indices); ::free(gen_uvs); //generate surfaces for (int i = 0; i < surfaces_tools.size(); i++) { surfaces_tools[i]->index(); surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format); } set_lightmap_size_hint(Size2(size_x, size_y)); return OK; }
void TriangleMesh::create(const DVector<Vector3>& p_faces) { valid=false; int fc=p_faces.size(); ERR_FAIL_COND(!fc || ((fc%3) != 0)); fc/=3; triangles.resize(fc); bvh.resize(fc*3); //will never be larger than this (todo make better) DVector<BVH>::Write bw = bvh.write(); { //create faces and indices and base bvh //except for the Set for repeated triangles, everything //goes in-place. DVector<Vector3>::Read r = p_faces.read(); DVector<Triangle>::Write w = triangles.write(); Map<Vector3,int> db; for(int i=0;i<fc;i++) { Triangle&f=w[i]; const Vector3 *v=&r[i*3]; for(int j=0;j<3;j++) { int vidx=-1; Vector3 vs=v[j].snapped(0.0001); Map<Vector3,int>::Element *E=db.find(vs); if (E) { vidx=E->get(); } else { vidx=db.size(); db[vs]=vidx; } f.indices[j]=vidx; if (j==0) bw[i].aabb.pos=vs; else bw[i].aabb.expand_to(vs); } f.normal=Face3(r[i*3+0],r[i*3+1],r[i*3+2]).get_plane().get_normal(); bw[i].left=-1; bw[i].right=-1; bw[i].face_index=i; bw[i].center=bw[i].aabb.pos+bw[i].aabb.size*0.5; } vertices.resize(db.size()); DVector<Vector3>::Write vw = vertices.write(); for (Map<Vector3,int>::Element *E=db.front();E;E=E->next()) { vw[E->get()]=E->key(); } } DVector<BVH*> bwptrs; bwptrs.resize(fc); DVector<BVH*>::Write bwp = bwptrs.write(); for(int i=0;i<fc;i++) { bwp[i]=&bw[i]; } max_depth=0; int max_alloc=fc; int max=_create_bvh(bw.ptr(),bwp.ptr(),0,fc,1,max_depth,max_alloc); bw=DVector<BVH>::Write(); //clearup bvh.resize(max_alloc); //resize back valid=true; }
int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_over[3]) const { ERR_FAIL_COND_V(is_degenerate(), 0); Vector3 above[4]; int above_count = 0; Vector3 below[4]; int below_count = 0; for (int i = 0; i < 3; i++) { if (p_plane.has_point(vertex[i], CMP_EPSILON)) { // point is in plane ERR_FAIL_COND_V(above_count >= 4, 0); above[above_count++] = vertex[i]; ERR_FAIL_COND_V(below_count >= 4, 0); below[below_count++] = vertex[i]; } else { if (p_plane.is_point_over(vertex[i])) { //Point is over ERR_FAIL_COND_V(above_count >= 4, 0); above[above_count++] = vertex[i]; } else { //Point is under ERR_FAIL_COND_V(below_count >= 4, 0); below[below_count++] = vertex[i]; } /* Check for Intersection between this and the next vertex*/ Vector3 inters; if (!p_plane.intersects_segment(vertex[i], vertex[(i + 1) % 3], &inters)) continue; /* Intersection goes to both */ ERR_FAIL_COND_V(above_count >= 4, 0); above[above_count++] = inters; ERR_FAIL_COND_V(below_count >= 4, 0); below[below_count++] = inters; } } int polygons_created = 0; ERR_FAIL_COND_V(above_count >= 4 && below_count >= 4, 0); //bug in the algo if (above_count >= 3) { p_res[polygons_created] = Face3(above[0], above[1], above[2]); p_is_point_over[polygons_created] = true; polygons_created++; if (above_count == 4) { p_res[polygons_created] = Face3(above[2], above[3], above[0]); p_is_point_over[polygons_created] = true; polygons_created++; } } if (below_count >= 3) { p_res[polygons_created] = Face3(below[0], below[1], below[2]); p_is_point_over[polygons_created] = false; polygons_created++; if (below_count == 4) { p_res[polygons_created] = Face3(below[2], below[3], below[0]); p_is_point_over[polygons_created] = false; polygons_created++; } } return polygons_created; }
Face3 Face3::clone() const { return Face3(*this); }
void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth) { if (p_octant->leaf) { if (p_aabb.has_point(p_triangle->vertices[0]) && p_aabb.has_point(p_triangle->vertices[1]) &&p_aabb.has_point(p_triangle->vertices[2])) { //face is completely enclosed, add area p_octant->surface_area+=Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area(); } else { //not completely enclosed, will need to be clipped.. Vector<Vector3> poly; poly.push_back(p_triangle->vertices[0]); poly.push_back(p_triangle->vertices[1]); poly.push_back(p_triangle->vertices[2]); //clip for(int i=0;i<3;i++) { //top plane Plane p(0,0,0,0); p.normal[i]=1.0; p.d=p_aabb.pos[i]+p_aabb.size[i]; poly=Geometry::clip_polygon(poly,p); //bottom plane p.normal[i]=-1.0; p.d=-p_aabb.pos[i]; poly=Geometry::clip_polygon(poly,p); } //calculate area for(int i=2;i<poly.size();i++) { p_octant->surface_area+=Face3(poly[0],poly[i-1],poly[i]).get_area(); } } } else { for(int i=0;i<8;i++) { AABB aabb=p_aabb; aabb.size*=0.5; if (i&1) aabb.pos.x+=aabb.size.x; if (i&2) aabb.pos.y+=aabb.size.y; if (i&4) aabb.pos.z+=aabb.size.z; AABB fit_aabb=aabb; //fit_aabb=fit_aabb.grow(bvh->aabb.size.x*0.0001); if (!Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb(fit_aabb)) continue; if (!p_octant->children[i]) { p_octant->children[i]=memnew(Octant); if (p_depth==0) { p_octant->children[i]->leaf=true; p_octant->children[i]->light_accum[0]=0; p_octant->children[i]->light_accum[1]=0; p_octant->children[i]->light_accum[2]=0; p_octant->children[i]->offset[0]=aabb.pos.x+aabb.size.x*0.5; p_octant->children[i]->offset[1]=aabb.pos.y+aabb.size.y*0.5; p_octant->children[i]->offset[2]=aabb.pos.z+aabb.size.z*0.5; p_octant->children[i]->surface_area=0; p_octant->children[i]->next_leaf=leaf_list; leaf_list=p_octant->children[i]; cell_count++; } else { p_octant->children[i]->leaf=false; for(int j=0;j<8;j++) { p_octant->children[i]->children[j]=0; } } } _octree_insert(aabb,p_octant->children[i],p_triangle,p_depth-1); } } }
void initialize( float radius, float segmentsWidth, float segmentsHeight, float phiStart, float phiLength, float thetaStart, float thetaLength ) { const auto segmentsX = Math::max( 3, ( int )Math::floor( segmentsWidth ) ); const auto segmentsY = Math::max( 2, ( int )Math::floor( segmentsHeight ) ); std::vector<std::vector<int>> indices; std::vector<std::vector<UV>> uvs; for ( int y = 0; y <= segmentsY; y ++ ) { std::vector<int> indicesRow; std::vector<UV> uvsRow; for ( int x = 0; x <= segmentsX; x ++ ) { const auto u = ( float )x / segmentsX; const auto v = ( float )y / segmentsY; Vertex vertex; vertex.x = - radius * Math::cos( phiStart + u * phiLength ) * Math::sin( thetaStart + v * thetaLength ); vertex.y = radius * Math::cos( thetaStart + v * thetaLength ); vertex.z = radius * Math::sin( phiStart + u * phiLength ) * Math::sin( thetaStart + v * thetaLength ); vertices.push_back( vertex ); indicesRow.push_back( ( int )vertices.size() - 1 ); uvsRow.push_back( UV( u, 1 - v ) ); } indices.push_back( indicesRow ); uvs.push_back( uvsRow ); } for ( int y = 0; y < segmentsY; y ++ ) { for ( int x = 0; x < segmentsX; x ++ ) { const auto v1 = indices[ y ][ x + 1 ]; const auto v2 = indices[ y ][ x ]; const auto v3 = indices[ y + 1 ][ x ]; const auto v4 = indices[ y + 1 ][ x + 1 ]; const auto n1 = vertices[ v1 ].clone().normalize(); const auto n2 = vertices[ v2 ].clone().normalize(); const auto n3 = vertices[ v3 ].clone().normalize(); const auto n4 = vertices[ v4 ].clone().normalize(); const auto& uv1 = uvs[ y ][ x + 1 ]; const auto& uv2 = uvs[ y ][ x ]; const auto& uv3 = uvs[ y + 1 ][ x ]; const auto& uv4 = uvs[ y + 1 ][ x + 1 ]; if ( Math::abs( vertices[ v1 ].y ) == radius ) { faces.push_back( Face3( v1, v3, v4, n1, n3, n4 ) ); faceVertexUvs[ 0 ].push_back( toArray( uv1, uv3, uv4 ) ); } else if ( Math::abs( vertices[ v3 ].y ) == radius ) { faces.push_back( Face3( v1, v2, v3, n1, n2, n3 ) ); faceVertexUvs[ 0 ].push_back( toArray( uv1, uv2, uv3 ) ); } else { faces.push_back( Face4( v1, v2, v3, v4, n1, n2, n3, n4 ) ); faceVertexUvs[ 0 ].push_back( toArray( uv1, uv2, uv3, uv4 ) ); } } } computeCentroids(); computeFaceNormals(); boundingSphere.radius = radius; }
void TorusKnotGeometry::initialize( float radius, float tube, size_t radialSegments, size_t tubularSegments, float p, float q, float heightScale ) { std::vector<std::vector<int>> grid; grid.resize( radialSegments ); auto tang = Vector3(); auto n = Vector3(); auto bitan = Vector3(); for ( size_t i = 0; i < radialSegments; ++ i ) { auto u = (float)i / (float)radialSegments * 2.f * p * Math::PI(); Vector3 p1 = getPos( u, q, p, radius, heightScale ); Vector3 p2 = getPos( u + 0.01f, q, p, radius, heightScale ); tang.subVectors( p2, p1 ); n.addVectors( p2, p1 ); bitan.crossVectors( tang, n ); n.crossVectors( bitan, tang ); bitan.normalize(); n.normalize(); for ( size_t j = 0; j < tubularSegments; ++ j ) { auto v = (float)j / (float)tubularSegments * 2.f * Math::PI(); auto cx = - tube * Math::cos( v ); // TODO: Hack: Negating it so it faces outside. auto cy = tube * Math::sin( v ); auto pos = Vector3(); pos.x = p1.x + cx * n.x + cy * bitan.x; pos.y = p1.y + cx * n.y + cy * bitan.y; pos.z = p1.z + cx * n.z + cy * bitan.z; this->vertices.push_back( pos ); grid[ i ].push_back( this->vertices.size() - 1 ); } } for ( size_t i = 0; i < radialSegments; ++ i ) { for ( size_t j = 0; j < tubularSegments; ++ j ) { auto ip = ( i + 1 ) % radialSegments; auto jp = ( j + 1 ) % tubularSegments; auto a = grid[ i ][ j ]; auto b = grid[ ip ][ j ]; auto c = grid[ ip ][ jp ]; auto d = grid[ i ][ jp ]; auto uva = Vector2( (float)i / (float)radialSegments, (float)j / (float)tubularSegments ); auto uvb = Vector2( (float)( i + 1 ) / (float)radialSegments, (float)j / (float)tubularSegments ); auto uvc = Vector2( (float)( i + 1 ) / (float)radialSegments, (float)( j + 1 ) / (float)tubularSegments ); auto uvd = Vector2( (float)i / (float)radialSegments, (float)( j + 1 ) / (float)tubularSegments ); this->faces.push_back( Face3( a, b, d ) ); this->faceVertexUvs[ 0 ].push_back( toArray( uva, uvb, uvd ) ); this->faces.push_back( Face3( b, c, d ) ); this->faceVertexUvs[ 0 ].push_back( toArray( uvb.clone(), uvc, uvd.clone() ) ); } } this->computeCentroids(); this->computeFaceNormals(); this->computeVertexNormals(); }