void BaseMesh::CopyMesh(BaseMesh &Copy) const { Copy._GD = _GD; Copy.Allocate(VertexCount(), FaceCount()); memcpy(Copy.Vertices(), Vertices(), sizeof(MeshVertex) * VertexCount()); memcpy(Copy.Indices(), Indices(), sizeof(DWORD) * IndexCount()); }
void BaseMesh::CleanVerticesAndTriangles(Vector<UINT> &OldToNewMapping) { UINT NumFaces = FaceCount(), NumVertices = VertexCount(); DWORD *I = Indices(); MeshVertex *V = Vertices(); Vector<DWORD> NewIndices; Vector<MeshVertex> NewVertices; OldToNewMapping.ReSize(NumVertices); OldToNewMapping.Clear(NumVertices); for(UINT FaceIndex = 0; FaceIndex < NumFaces; FaceIndex++) { if(I[FaceIndex * 3 + 0] != I[FaceIndex * 3 + 1] && I[FaceIndex * 3 + 1] != I[FaceIndex * 3 + 2] && I[FaceIndex * 3 + 2] != I[FaceIndex * 3 + 0]) { for(UINT i = 0; i < 3; i++) { UINT SourceIndex = I[FaceIndex * 3 + i]; if(OldToNewMapping[SourceIndex] == NumVertices) { OldToNewMapping[SourceIndex] = NewVertices.Length(); NewVertices.PushEnd(V[SourceIndex]); } NewIndices.PushEnd(OldToNewMapping[SourceIndex]); } } } Allocate(NewVertices.Length(), NewIndices.Length() / 3); NumFaces = FaceCount(); NumVertices = VertexCount(); I = Indices(); V = Vertices(); for(UINT VertexIndex = 0; VertexIndex < NumVertices; VertexIndex++) { V[VertexIndex] = NewVertices[VertexIndex]; } for(UINT FaceIndex = 0; FaceIndex < NumFaces; FaceIndex++) { for(UINT i = 0; i < 3; i++) { I[FaceIndex * 3 + i] = NewIndices[FaceIndex * 3 + i]; } } }
void BaseMesh::RotateFaces() { DWORD *_Indices = Indices(); UINT _FaceCount = FaceCount(); for(UINT FaceIndex = 0; FaceIndex < _FaceCount; FaceIndex++) { Utility::Swap(_Indices[FaceIndex * 3 + 0], _Indices[FaceIndex * 3 + 1]); } GenerateNormals(); }
float BaseMesh::SidedSurfaceArea(const Plane &P) { float Result = 0.0f; DWORD *MyIndices = Indices(); MeshVertex *MyVertices = Vertices(); UINT TriangleCount = FaceCount(); for(UINT TriangleIndex = 0; TriangleIndex < TriangleCount; TriangleIndex++) { Vec3f LocalTriangle[6]; UINT TSide[3]; for(UINT LocalVertexIndex = 0; LocalVertexIndex < 3; LocalVertexIndex++) { LocalTriangle[LocalVertexIndex] = MyVertices[MyIndices[TriangleIndex * 3 + LocalVertexIndex]].Pos; if(Plane::DotCoord(P, LocalTriangle[LocalVertexIndex]) < 0.0f) { TSide[LocalVertexIndex] = 0; } else { TSide[LocalVertexIndex] = 1; } } UINT TriangleType = TSide[0] * 4 + TSide[1] * 2 + TSide[2] * 1; for(UINT EdgeIndex = 0; EdgeIndex < 3; EdgeIndex++) { if(PerfectEdges[TriangleType][EdgeIndex]) { Vec3f Vtx1 = MyVertices[MyIndices[TriangleIndex * 3 + PerfectEdgeList[EdgeIndex][0]]].Pos; Vec3f Vtx2 = MyVertices[MyIndices[TriangleIndex * 3 + PerfectEdgeList[EdgeIndex][1]]].Pos; Vec3f VtxIntersect = P.IntersectLine(Vtx1, Vtx2); if(!Vec3f::WithinRect(VtxIntersect, Rectangle3f::ConstructFromTwoPoints(Vtx1, Vtx2))) { VtxIntersect = (Vtx1 + Vtx2) * 0.5f; } LocalTriangle[3 + EdgeIndex] = VtxIntersect; } } for(UINT LocalTriangleIndex = 0; LocalTriangleIndex < 6; LocalTriangleIndex += 3) { if(M1Indices[TriangleType][LocalTriangleIndex] != -1) { Vec3f V[3]; V[0] = LocalTriangle[M1Indices[TriangleType][LocalTriangleIndex + 0]]; V[1] = LocalTriangle[M1Indices[TriangleType][LocalTriangleIndex + 1]]; V[2] = LocalTriangle[M1Indices[TriangleType][LocalTriangleIndex + 2]]; Result += Math::TriangleArea(V[0], V[1], V[2]); } } } return Result; }
void BaseMesh::CullFaces(const BYTE FaceTest[]) { Vector<DWORD> NewIndices; Vector<MeshVertex> NewVertices; UINT NumFaces = FaceCount(), NumVertices = VertexCount(); DWORD *I = Indices(); MeshVertex *V = Vertices(); for(UINT VertexIndex = 0; VertexIndex < NumVertices; VertexIndex++) { NewVertices.PushEnd(V[VertexIndex]); } for(UINT FaceIndex = 0; FaceIndex < NumFaces; FaceIndex++) { if(FaceTest[FaceIndex]) { for(UINT i = 0; i < 3; i++) { NewIndices.PushEnd(I[FaceIndex * 3 + i]); } } } Allocate(NewVertices.Length(), NewIndices.Length() / 3); NumFaces = FaceCount(); NumVertices = VertexCount(); I = Indices(); V = Vertices(); for(UINT VertexIndex = 0; VertexIndex < NumVertices; VertexIndex++) { V[VertexIndex] = NewVertices[VertexIndex]; } for(UINT FaceIndex = 0; FaceIndex < NumFaces; FaceIndex++) { for(UINT i = 0; i < 3; i++) { I[FaceIndex * 3 + i] = NewIndices[FaceIndex * 3 + i]; } } }
inline storage load_dds(const std::vector<char>& content) { std::stringstream FileIn(std::string(content.data(), content.size())); assert(!FileIn.fail()); if(FileIn.fail()) return storage(); detail::ddsHeader HeaderDesc; detail::ddsHeader10 HeaderDesc10; char Magic[4]; //* Read magic number and check if valid .dds file FileIn.read((char*)&Magic, sizeof(Magic)); assert(strncmp(Magic, "DDS ", 4) == 0); // Get the surface descriptor FileIn.read((char*)&HeaderDesc, sizeof(HeaderDesc)); if(HeaderDesc.format.flags & detail::DDPF_FOURCC && HeaderDesc.format.fourCC == detail::D3DFMT_DX10) FileIn.read((char*)&HeaderDesc10, sizeof(HeaderDesc10)); gli::format Format(gli::FORMAT_NULL); if(HeaderDesc.format.fourCC == detail::D3DFMT_DX10) Format = detail::format_dds2gli_cast(HeaderDesc10.Format); else if(HeaderDesc.format.flags & detail::DDPF_FOURCC) Format = detail::format_fourcc2gli_cast(HeaderDesc.format.flags, HeaderDesc.format.fourCC); else if(HeaderDesc.format.flags & detail::DDPF_RGB) { switch(HeaderDesc.format.bpp) { case 8: Format = R8_UNORM; break; case 16: Format = RG8_UNORM; break; case 24: Format = RGB8_UNORM; break; case 32: Format = RGBA8_UNORM; break; } } else assert(0); std::streamoff Curr = FileIn.tellg(); FileIn.seekg(0, std::ios_base::end); std::streamoff End = FileIn.tellg(); FileIn.seekg(Curr, std::ios_base::beg); storage::size_type const MipMapCount = (HeaderDesc.flags & detail::DDSD_MIPMAPCOUNT) ? HeaderDesc.mipMapLevels : 1; storage::size_type FaceCount(1); if(HeaderDesc.cubemapFlags & detail::DDSCAPS2_CUBEMAP) FaceCount = int(glm::bitCount(HeaderDesc.cubemapFlags & detail::DDSCAPS2_CUBEMAP_ALLFACES)); storage::size_type DepthCount = 1; if(HeaderDesc.cubemapFlags & detail::DDSCAPS2_VOLUME) DepthCount = HeaderDesc.depth; storage Storage( HeaderDesc10.arraySize, FaceCount, MipMapCount, Format, storage::dimensions_type(HeaderDesc.width, HeaderDesc.height, DepthCount)); FileIn.read((char*)Storage.data(), std::size_t(End - Curr)); return Storage; }
void D3D9Mesh::SimplifyToPercentFaces(float NewPercent) { SimplifyToFaces(UINT(FaceCount() * NewPercent)); }
ON_SubD* ON_SubDSectorType::SectorRingSubD( double radius, double sector_angle_radians, ON_SubD* subd ) const { if (subd) *subd = ON_SubD::Empty; if (!IsValid()) return ON_SUBD_RETURN_ERROR(nullptr); const unsigned int R = PointRingCount(); if (R < 3) return ON_SUBD_RETURN_ERROR(nullptr); const unsigned int F = FaceCount(); if ( F < 1) return ON_SUBD_RETURN_ERROR(nullptr); const unsigned int N = EdgeCount(); if (N < 2) return ON_SUBD_RETURN_ERROR(nullptr); if (F != N && F + 1 != N) return ON_SUBD_RETURN_ERROR(nullptr); const ON_SubD::SubDType subdivision_type = SubDType(); const ON_SubD::VertexTag vertex_tag = VertexTag(); const unsigned f_edge_count = ON_SubD::FacetEdgeCount(subdivision_type); if (3 != f_edge_count && 4 != f_edge_count) return ON_SUBD_RETURN_ERROR(nullptr); const unsigned int ring_ei_delta = f_edge_count - 2; if (nullptr == subd) subd = new ON_SubD; ON_SubD::VertexTag vertex_tag0; ON_SubD::VertexTag vertex_tag1; ON_SubD::EdgeTag edge_tag0; ON_SubD::EdgeTag edge_tag1; switch (vertex_tag) { case ON_SubD::VertexTag::Smooth: sector_angle_radians = 2.0*ON_PI; vertex_tag0 = ON_SubD::VertexTag::Smooth; vertex_tag1 = ON_SubD::VertexTag::Smooth; edge_tag0 = ON_SubD::EdgeTag::Smooth; edge_tag1 = ON_SubD::EdgeTag::Smooth; break; case ON_SubD::VertexTag::Crease: if ( !(sector_angle_radians > 0.0 && sector_angle_radians < 2.0*ON_PI) ) sector_angle_radians = 0.5*ON_PI; vertex_tag0 = ON_SubD::VertexTag::Crease; vertex_tag1 = ON_SubD::VertexTag::Crease; edge_tag0 = ON_SubD::EdgeTag::Crease; edge_tag1 = ON_SubD::EdgeTag::Crease; break; case ON_SubD::VertexTag::Corner: sector_angle_radians = CornerSectorAngleRadians(); vertex_tag0 = ON_SubD::VertexTag::Crease; vertex_tag1 = ON_SubD::VertexTag::Crease; edge_tag0 = ON_SubD::EdgeTag::Crease; edge_tag1 = ON_SubD::EdgeTag::Crease; break; case ON_SubD::VertexTag::Dart: sector_angle_radians = 2.0*ON_PI; vertex_tag0 = ON_SubD::VertexTag::Crease; vertex_tag1 = ON_SubD::VertexTag::Smooth; edge_tag0 = ON_SubD::EdgeTag::Crease; edge_tag1 = ON_SubD::EdgeTag::Smooth; break; default: return ON_SUBD_RETURN_ERROR(nullptr); break; } unsigned int sector_angle_index = ON_SubDSectorType::AngleIndexFromAngleRadians(sector_angle_radians); if (sector_angle_index <= ON_SubDSectorType::MaximumAngleIndex && fabs(ON_SubDSectorType::AngleRadiansFromAngleIndex(sector_angle_index) - sector_angle_radians) <= 1.0e-6 ) { sector_angle_radians = ON_SubDSectorType::AngleRadiansFromAngleIndex(sector_angle_index); } else { sector_angle_radians = ON_UNSET_UINT_INDEX; } const double smooth_edge_w0 = this->SectorWeight(); ON_SimpleArray< ON_SubDVertex* > V(R); ON_SimpleArray< ON_SubDEdge* > E(N); ON_3dPoint vertexP = ON_3dPoint::Origin; for (unsigned int vi = 0; vi < R; vi++) { ON_SubD::VertexTag vertex_tag_vi; if ( 0 == vi ) vertex_tag_vi = vertex_tag; // center vertex else if ( 1 == vi ) vertex_tag_vi = vertex_tag0; // first edge else if ( R == vi+1 && N > F ) vertex_tag_vi = vertex_tag1; // last edge else vertex_tag_vi = ON_SubD::VertexTag::Smooth; // interior edge or an outer face vertex if (radius > 0.0) { double cos_a, sin_a; if (sector_angle_index == ON_UNSET_UINT_INDEX) { double a = (vi / ((double)(R-1)))*sector_angle_radians; cos_a = cos(a); sin_a = sin(a); } else { ON_SubDMatrix::EvaluateCosAndSin(2*sector_angle_index*vi, (R-1)*ON_SubDSectorType::MaximumAngleIndex,&cos_a,&sin_a); } const double r = (3 == f_edge_count) || (1 == (vi%2)) ? radius : (2.0*radius); vertexP.x = r*cos_a; vertexP.y = r*sin_a; } ON_SubDVertex* vertex = subd->AddVertex( vertex_tag_vi, vertexP); V.Append(vertex); } //V[0]->m_vertex_edge_order = ON_SubD::VertexEdgeOrder::radial; for (unsigned int vei = 0; vei < N; vei++) { ON_SubD::EdgeTag edge_tag_vei; if ( 0 == vei ) edge_tag_vei = edge_tag0; // first edge else if ( vei+1 == N ) edge_tag_vei = edge_tag1; // last edge else edge_tag_vei = ON_SubD::EdgeTag::Smooth; // interior edge double w0 = (ON_SubD::EdgeTag::Smooth == edge_tag_vei) ? smooth_edge_w0 : ON_SubDSectorType::IgnoredSectorWeight; unsigned int ev1i = 1 + vei*ring_ei_delta; E.Append( subd->AddEdgeWithSectorCoefficients( edge_tag_vei, V[0], w0, V[ev1i], ON_SubDSectorType::IgnoredSectorWeight) ); } ON_SubDVertex* f_vertex[4] = {}; ON_SubDEdge* f_edge[4] = {}; ON_SubDEdgePtr f_edgeptr[4] = {}; f_vertex[0] = V[0]; f_vertex[f_edge_count - 1] = const_cast<ON_SubDVertex*>(E[0]->m_vertex[1]); f_edge[f_edge_count - 1] = E[0]; for (unsigned int vfi = 0; vfi < F; vfi++) { f_edge[0] = f_edge[f_edge_count - 1]; f_edge[f_edge_count-1] = E[(vfi + 1) % N]; f_vertex[1] = const_cast<ON_SubDVertex*>(f_edge[0]->m_vertex[1]); f_vertex[f_edge_count - 1] = const_cast<ON_SubDVertex*>(f_edge[f_edge_count - 1]->m_vertex[1]); f_edgeptr[0] = ON_SubDEdgePtr::Create(f_edge[0], 0); f_edgeptr[f_edge_count - 1] = ON_SubDEdgePtr::Create(f_edge[f_edge_count - 1], 1); if (4 == f_edge_count) { f_vertex[2] = V[2 + 2 * vfi]; f_edge[1] = subd->AddEdgeWithSectorCoefficients(ON_SubD::EdgeTag::Smooth, f_vertex[1], ON_SubDSectorType::IgnoredSectorWeight, f_vertex[2], ON_SubDSectorType::IgnoredSectorWeight); f_edge[2] = subd->AddEdgeWithSectorCoefficients(ON_SubD::EdgeTag::Smooth, f_vertex[2], ON_SubDSectorType::IgnoredSectorWeight, f_vertex[3], ON_SubDSectorType::IgnoredSectorWeight); f_edgeptr[1] = ON_SubDEdgePtr::Create(f_edge[1], 0); f_edgeptr[2] = ON_SubDEdgePtr::Create(f_edge[2], 0); } else { f_edge[1] = subd->AddEdgeWithSectorCoefficients(ON_SubD::EdgeTag::Smooth, f_vertex[1], ON_SubDSectorType::IgnoredSectorWeight, f_vertex[2], ON_SubDSectorType::IgnoredSectorWeight); f_edgeptr[1] = ON_SubDEdgePtr::Create(f_edge[1], 0); } subd->AddFace(f_edge_count, f_edgeptr); } return subd; }
void BaseMesh::CreateClosedCylinder(float radius, float height, UINT slices, UINT stacks) { //this code is almost identical to CreateCylinder(radius, height slices, stacks) except it //adds on a cap (like CreateLantern.) Allocate(slices * (stacks + 1),2 * stacks * slices + 2*(slices-2)); float PI2_Slices = 2.0f * Math::PIf / float(slices); float Theta; int vc=0,ic=0; MeshVertex *V = Vertices(); DWORD *I = Indices(); MeshVertex MVtx(Vec3f::Origin, Vec3f::Origin, RGBColor::White, Vec2f::Origin); for(UINT i=0;i <= stacks;i++) { for(UINT i2=0;i2 < slices;i2++) { Theta = float(i2+0.5f*i) * PI2_Slices; MVtx.Pos = Vec3f(radius * cosf(Theta), radius * sinf(Theta), height * (float(i) / stacks - 0.5f)); V[vc++] = MVtx; } } for(UINT i=0;i < FaceCount();i++) { I[i*3+0] = 0; I[i*3+1] = 1; I[i*3+2] = 2; } for(UINT i=0;i < stacks-1;i++) for(UINT i2=0;i2 < slices;i2++) { UINT i2m1 = i2 - 1; if(i2m1 == -1) i2m1 = slices-1; I[ic++] = i * slices + i2; I[ic++] = (i+1) * slices + i2; I[ic++] = (i+1) * slices + i2m1; I[ic++] = (i+1) * slices + i2m1; I[ic++] = (i+1) * slices + i2; I[ic++] = (i+2) * slices + i2m1; } UINT i = 0; for(UINT i2=0;i2 < slices;i2++) { UINT i2m1 = i2 - 1; if(i2m1 == -1) { i2m1 = slices-1; } I[ic++] = i * slices + i2m1; I[ic++] = i * slices + i2; I[ic++] = (i+1) * slices + i2m1; } i = stacks - 1; for(UINT i2 = 0; i2 < slices; i2++) { UINT i2m1 = i2 - 1; if(i2m1 == -1) { i2m1 = slices-1; } I[ic++] = (i+1) * slices + i2m1; I[ic++] = i * slices + i2; I[ic++] = (i+1) * slices + i2; } i = 0; for(UINT i2 = 1; i2 < slices - 1; i2++) { I[ic++] = i * slices + 0; I[ic++] = i * slices + i2+1; I[ic++] = i * slices + i2; } i = stacks; for(UINT i2 = 1; i2 < slices - 1; i2++) { I[ic++] = i * slices + 0; I[ic++] = i * slices + i2; I[ic++] = i * slices + i2+1; } GenerateNormals(); }
void BaseMesh::CreateLantern(float radius, float height, UINT slices, UINT stacks) { //this code is almost identical to CreateCylinder(radius, height slices, stacks) except it flips all non-border //edges; this is a much worse triangulation of the surface and does not behave well numerically (which was the //goal for the project I was working on at the time.) //it also has a cap on the top/bottom. Allocate(slices * (stacks + 1),2 * stacks * slices + 2*(slices-2)); float PI2_Slices = 2.0f * Math::PIf / float(slices); float Theta; int vc=0, ic=0; MeshVertex *V = Vertices(); DWORD *I = Indices(); MeshVertex MVtx(Vec3f::Origin, Vec3f::Origin, RGBColor::White, Vec2f::Origin); for(UINT i = 0; i <= stacks; i++) { for(UINT i2 = 0; i2 < slices; i2++) { Theta = float(i2+0.5f*i) * PI2_Slices; MVtx.Pos = Vec3f(radius * cosf(Theta), radius * sinf(Theta), height * (float(i) / stacks - 0.5f)); V[vc++] = MVtx; } } for(UINT i = 0; i < FaceCount(); i++) { I[i*3+0] = 0; I[i*3+1] = 1; I[i*3+2] = 2; } int i2m1; for(UINT i = 0; i < stacks - 1; i++) for(UINT i2 = 0; i2 < slices; i2++) { i2m1 = int(i2) - 1; if(i2m1 == -1) i2m1 = slices-1; I[ic++] = i * slices + i2; I[ic++] = (i+1) * slices + i2; I[ic++] = (i+2) * slices + i2m1; I[ic++] = i * slices + i2; I[ic++] = (i+2) * slices + i2m1; I[ic++] = (i+1) * slices + i2m1; } UINT i = 0; for(UINT i2 = 0; i2 < slices; i2++) { i2m1 = i2 - 1; if(i2m1 == -1) i2m1 = slices-1; I[ic++] = i * slices + i2m1; I[ic++] = i * slices + i2; I[ic++] = (i+1) * slices + i2m1; } i = stacks - 1; for(UINT i2 = 0; i2 < slices; i2++) { i2m1 = i2 - 1; if(i2m1 == -1) { i2m1 = slices - 1; } I[ic++] = (i + 1) * slices + i2m1; I[ic++] = i * slices + i2; I[ic++] = (i + 1) * slices + i2; } i = 0; for(UINT i2 = 1; i2 < slices - 1; i2++) { I[ic++] = i * slices + 0; I[ic++] = i * slices + i2 + 1; I[ic++] = i * slices + i2; } i = stacks; for(UINT i2 = 1; i2 < slices - 1; i2++) { I[ic++] = i * slices + 0; I[ic++] = i * slices + i2; I[ic++] = i * slices + i2 + 1; } GenerateNormals(); }