UNPKG

angular-3d-viewer

Version:
234 lines (206 loc) 7.86 kB
import { Coord2D, CoordIsEqual2D } from '../geometry/coord2d.js'; import { CoordIsEqual3D } from '../geometry/coord3d.js'; import { RGBColor, RGBColorIsEqual } from './color.js'; export class MeshPrimitiveBuffer { constructor () { this.indices = []; this.vertices = []; this.colors = []; this.normals = []; this.uvs = []; this.material = null; } GetBounds () { let min = [Infinity, Infinity, Infinity]; let max = [-Infinity, -Infinity, -Infinity]; for (let i = 0; i < this.vertices.length / 3; i++) { for (let j = 0; j < 3; j++) { min[j] = Math.min (min[j], this.vertices[i * 3 + j]); max[j] = Math.max (max[j], this.vertices[i * 3 + j]); } } return { min : min, max : max }; } GetByteLength (indexTypeSize, numberTypeSize) { let indexCount = this.indices.length; let numberCount = this.vertices.length + this.colors.length + this.normals.length + this.uvs.length; return indexCount * indexTypeSize + numberCount * numberTypeSize; } } export class MeshBuffer { constructor () { this.primitives = []; } PrimitiveCount () { return this.primitives.length; } GetPrimitive (index) { return this.primitives[index]; } GetByteLength (indexTypeSize, numberTypeSize) { let byteLength = 0; for (let i = 0; i < this.primitives.length; i++) { let primitive = this.primitives[i]; byteLength += primitive.GetByteLength (indexTypeSize, numberTypeSize); } return byteLength; } } export function ConvertMeshToMeshBuffer (mesh) { function AddVertexToPrimitiveBuffer (mesh, indices, primitiveBuffer, meshVertexToPrimitiveVertices) { function GetColorOrDefault (mesh, colorIndex, forceColors) { if (colorIndex !== null) { return mesh.GetVertexColor (colorIndex); } else if (forceColors) { return new RGBColor (0, 0, 0); } else { return null; } } function GetUVOrDefault (mesh, uvIndex, forceUVs) { if (uvIndex !== null) { return mesh.GetTextureUV (uvIndex); } else if (forceUVs) { return new Coord2D (0.0, 0.0); } else { return null; } } function AddVertex (mesh, indices, primitiveBuffer) { let forceColors = mesh.VertexColorCount () > 0; let forceUVs = mesh.TextureUVCount () > 0; let vertex = mesh.GetVertex (indices.vertex); let normal = mesh.GetNormal (indices.normal); let primitiveVertexIndex = primitiveBuffer.vertices.length / 3; primitiveBuffer.indices.push (primitiveVertexIndex); primitiveBuffer.vertices.push (vertex.x, vertex.y, vertex.z); let color = GetColorOrDefault (mesh, indices.color, forceColors); if (color !== null) { primitiveBuffer.colors.push (color.r / 255.0, color.g / 255.0, color.b / 255.0); } primitiveBuffer.normals.push (normal.x, normal.y, normal.z); let uv = GetUVOrDefault (mesh, indices.uv, forceUVs); if (uv !== null) { primitiveBuffer.uvs.push (uv.x, uv.y); } return { index : primitiveVertexIndex, color : color, normal : normal, uv : uv }; } function FindMatchingPrimitiveVertex (mesh, primitiveVertices, indices) { function IsEqualColor (mesh, colorIndex, existingColor) { if (existingColor === null && colorIndex === null) { return true; } let color = GetColorOrDefault (mesh, colorIndex, true); return RGBColorIsEqual (existingColor, color); } function IsEqualNormal (mesh, normalIndex, existingNormal) { let normal = mesh.GetNormal (normalIndex); return CoordIsEqual3D (existingNormal, normal); } function IsEqualUV (mesh, uvIndex, existingUv) { if (existingUv === null && uvIndex === null) { return true; } let uv = GetUVOrDefault (mesh, uvIndex, true); return CoordIsEqual2D (existingUv, uv); } for (let i = 0; i < primitiveVertices.length; i++) { let primitiveVertex = primitiveVertices[i]; let equalColor = IsEqualColor (mesh, indices.color, primitiveVertex.color); let equalNormal = IsEqualNormal (mesh, indices.normal, primitiveVertex.normal); let equalUv = IsEqualUV (mesh, indices.uv, primitiveVertex.uv); if (equalColor && equalNormal && equalUv) { return primitiveVertex; } } return null; } if (meshVertexToPrimitiveVertices.has (indices.vertex)) { let primitiveVertices = meshVertexToPrimitiveVertices.get (indices.vertex); let existingPrimitiveVertex = FindMatchingPrimitiveVertex (mesh, primitiveVertices, indices); if (existingPrimitiveVertex !== null) { primitiveBuffer.indices.push (existingPrimitiveVertex.index); } else { let primitiveVertex = AddVertex (mesh, indices, primitiveBuffer); primitiveVertices.push (primitiveVertex); } } else { let primitiveVertex = AddVertex (mesh, indices, primitiveBuffer); meshVertexToPrimitiveVertices.set (indices.vertex, [primitiveVertex]); } } let meshBuffer = new MeshBuffer (); let triangleCount = mesh.TriangleCount (); if (triangleCount === 0) { return null; } let triangleIndices = []; for (let i = 0; i < triangleCount; i++) { triangleIndices.push (i); } triangleIndices.sort ((a, b) => { let aTriangle = mesh.GetTriangle (a); let bTriangle = mesh.GetTriangle (b); return aTriangle.mat - bTriangle.mat; }); let primitiveBuffer = null; let meshVertexToPrimitiveVertices = null; for (let i = 0; i < triangleIndices.length; i++) { let triangleIndex = triangleIndices[i]; let triangle = mesh.GetTriangle (triangleIndex); if (primitiveBuffer === null || primitiveBuffer.material !== triangle.mat) { primitiveBuffer = new MeshPrimitiveBuffer (); primitiveBuffer.material = triangle.mat; meshVertexToPrimitiveVertices = new Map (); meshBuffer.primitives.push (primitiveBuffer); } let v0Indices = { vertex : triangle.v0, color : triangle.c0, normal : triangle.n0, uv : triangle.u0 }; let v1Indices = { vertex : triangle.v1, color : triangle.c1, normal : triangle.n1, uv : triangle.u1 }; let v2Indices = { vertex : triangle.v2, color : triangle.c2, normal : triangle.n2, uv : triangle.u2 }; AddVertexToPrimitiveBuffer (mesh, v0Indices, primitiveBuffer, meshVertexToPrimitiveVertices); AddVertexToPrimitiveBuffer (mesh, v1Indices, primitiveBuffer, meshVertexToPrimitiveVertices); AddVertexToPrimitiveBuffer (mesh, v2Indices, primitiveBuffer, meshVertexToPrimitiveVertices); } return meshBuffer; }