diff --git a/source/import/importerply.js b/source/import/importerply.js index aa6c097..32d3cd5 100644 --- a/source/import/importerply.js +++ b/source/import/importerply.js @@ -84,6 +84,66 @@ OV.PlyHeader = class } }; +OV.PlyMaterialHandler = class +{ + constructor (model) + { + this.model = model; + this.vertexColors = []; + this.colorToMaterial = {}; + } + + AddVertexColor (color) + { + this.vertexColors.push (color); + } + + GetTriangleColor (v0, v1, v2) + { + let vertexCount = this.vertexColors.length; + if (v0 >= vertexCount || v1 >= vertexCount || v2 >= vertexCount) { + return null; + } + return this.vertexColors[v0]; + } + + GetTriangleFaceMaterialIndex (color) + { + return this.GetMaterialIndexByColor (color); + } + + GetTriangleVertexMaterialIndex (v0, v1, v2) + { + let color = this.GetTriangleColor (v0, v1, v2); + if (color === null) { + return null; + } + return this.GetMaterialIndexByColor (color); + } + + GetMaterialIndexByColor (color) + { + let materialName = 'Color ' + + OV.IntegerToHexString (color[0]) + + OV.IntegerToHexString (color[1]) + + OV.IntegerToHexString (color[2]) + + OV.IntegerToHexString (color[3]); + + let materialIndex = this.colorToMaterial[materialName]; + if (materialIndex === undefined) { + let material = new OV.Material (OV.MaterialType.Phong); + material.name = materialName; + material.color = new OV.Color (color[0], color[1], color[2]); + material.opacity = color[3] / 255.0; + OV.UpdateMaterialTransparency (material); + materialIndex = this.model.AddMaterial (material); + this.colorToMaterial[materialName] = materialIndex; + } + + return materialIndex; + } +}; + OV.ImporterPly = class extends OV.ImporterBase { constructor () @@ -238,7 +298,50 @@ OV.ImporterPly = class extends OV.ImporterBase ReadBinaryContent (header, fileContent, headerLength) { - function SkipAndGetColor (obj, reader, format, startIndex) + function ReadByFormat (reader, format) + { + function ReadType (reader, type) + { + if (type === 'char' || type === 'int8') { + return reader.ReadCharacter8 (); + } else if (type === 'uchar' || type === 'uint8') { + return reader.ReadUnsignedCharacter8 (); + } else if (type === 'short' || type === 'int16') { + return reader.ReadInteger16 (); + } else if (type === 'ushort' || type === 'uint16') { + return reader.ReadUnsignedInteger16 (); + } else if (type === 'int' || type === 'int32') { + return reader.ReadInteger32 (); + } else if (type === 'uint' || type === 'uint32') { + return reader.ReadUnsignedInteger32 (); + } else if (type === 'float' || type === 'float32') { + return reader.ReadFloat32 (); + } else if (type === 'double' || type === 'double64') { + return reader.ReadDouble64 (); + } + return null; + } + + if (format.isSingle) { + return ReadType (reader, format.elemType); + } else { + let list = []; + let count = ReadType (reader, format.countType); + for (let i = 0; i < count; i++) { + list.push (ReadType (reader, format.elemType)); + } + return list; + } + } + + function SkipFormat (reader, format, startIndex) + { + for (let i = startIndex; i < format.length; i++) { + ReadByFormat (reader, format[i]); + } + } + + function SkipAndGetColor (reader, format, startIndex) { let r = null; let g = null; @@ -247,7 +350,7 @@ OV.ImporterPly = class extends OV.ImporterBase for (let i = startIndex; i < format.length; i++) { let currFormat = format[i]; - let val = obj.ReadByFormat (reader, currFormat); + let val = ReadByFormat (reader, currFormat); if (currFormat.name === 'red') { r = val; } else if (currFormat.name === 'green') { @@ -266,47 +369,6 @@ OV.ImporterPly = class extends OV.ImporterBase return null; } - function GetMaterialFromColor (obj, color, colorToMaterial) - { - if (color === null) { - return null; - } - - let materialName = 'Color ' + - OV.IntegerToHexString (color[0]) + - OV.IntegerToHexString (color[1]) + - OV.IntegerToHexString (color[2]) + - OV.IntegerToHexString (color[3]); - let materialIndex = colorToMaterial[materialName]; - if (materialIndex === undefined) { - let material = new OV.Material (OV.MaterialType.Phong); - material.name = materialName; - material.color = new OV.Color (color[0], color[1], color[2]); - material.opacity = color[3] / 255.0; - OV.UpdateMaterialTransparency (material); - materialIndex = obj.model.AddMaterial (material); - colorToMaterial[materialName] = materialIndex; - } - - return materialIndex; - } - - function GetFaceColorByVertexColors (obj, v0, v1, v2, vertexColors, colorToMaterial) - { - let c0 = vertexColors[v0]; - let c1 = vertexColors[v1]; - let c2 = vertexColors[v2]; - let d0 = Math.abs (c0[0] - c1[0]) + Math.abs (c0[1] - c1[1]) + Math.abs (c0[2] - c1[2]); - let d1 = Math.abs (c1[0] - c2[0]) + Math.abs (c1[1] - c2[1]) + Math.abs (c1[2] - c2[2]); - let d2 = Math.abs (c0[0] - c2[0]) + Math.abs (c0[1] - c2[1]) + Math.abs (c0[2] - c2[2]); - let min = Math.min (d0, d1, d2); - let color = c0; - if (min === d1) { - color = c1; - } - return GetMaterialFromColor (obj, color, colorToMaterial); - } - let reader = null; if (header.format === 'binary_little_endian') { reader = new OV.BinaryReader (fileContent, true); @@ -317,43 +379,42 @@ OV.ImporterPly = class extends OV.ImporterBase } reader.Skip (headerLength); - let vertexColors = []; - let colorToMaterial = {}; + let materialHandler = new OV.PlyMaterialHandler (this.model); let elements = header.GetElements (); for (let elementIndex = 0; elementIndex < elements.length; elementIndex++) { let element = elements[elementIndex]; if (element.name === 'vertex') { for (let vertexIndex = 0; vertexIndex < element.count; vertexIndex++) { - let x = this.ReadByFormat (reader, element.format[0]); - let y = this.ReadByFormat (reader, element.format[1]); - let z = this.ReadByFormat (reader, element.format[2]); - let color = SkipAndGetColor (this, reader, element.format, 3); + let x = ReadByFormat (reader, element.format[0]); + let y = ReadByFormat (reader, element.format[1]); + let z = ReadByFormat (reader, element.format[2]); + let color = SkipAndGetColor (reader, element.format, 3); if (color !== null) { - vertexColors.push (color); + materialHandler.AddVertexColor (color); } this.mesh.AddVertex (new OV.Coord3D (x, y, z)); } } else if (element.name === 'face') { for (let faceIndex = 0; faceIndex < element.count; faceIndex++) { - let vertices = this.ReadByFormat (reader, element.format[0]); - let faceColor = SkipAndGetColor (this, reader, element.format, 1); + let vertices = ReadByFormat (reader, element.format[0]); + let faceColor = SkipAndGetColor (reader, element.format, 1); for (let i = 0; i < vertices.length - 2; i++) { let v0 = vertices[0]; let v1 = vertices[i + 1]; let v2 = vertices[i + 2]; let triangle = new OV.Triangle (v0, v1, v2); if (faceColor !== null) { - triangle.mat = GetMaterialFromColor (this, faceColor, colorToMaterial); - } else if (vertexColors.length === this.model.VertexCount ()) { - triangle.mat = GetFaceColorByVertexColors (this, v0, v1, v2, vertexColors, colorToMaterial); + triangle.mat = materialHandler.GetTriangleFaceMaterialIndex (faceColor); + } else { + triangle.mat = materialHandler.GetTriangleVertexMaterialIndex (v0, v1, v2); } this.mesh.AddTriangle (triangle); } } } else if (element.name === 'tristrips') { for (let triStripIndex = 0; triStripIndex < element.count; triStripIndex++) { - let vertices = this.ReadByFormat (reader, element.format[0]); - this.SkipFormat (reader, element.format, 1); + let vertices = ReadByFormat (reader, element.format[0]); + SkipFormat (reader, element.format, 1); let ccw = true; for (let i = 0; i < vertices.length - 2; i++) { let v0 = vertices[i]; @@ -375,51 +436,8 @@ OV.ImporterPly = class extends OV.ImporterBase } } } else { - this.SkipFormat (reader, element.format, 0); + SkipFormat (reader, element.format, 0); } } } - - SkipFormat (reader, format, startIndex) - { - for (let i = startIndex; i < format.length; i++) { - this.ReadByFormat (reader, format[i]); - } - } - - ReadByFormat (reader, format) - { - function ReadType (reader, type) - { - if (type === 'char' || type === 'int8') { - return reader.ReadCharacter8 (); - } else if (type === 'uchar' || type === 'uint8') { - return reader.ReadUnsignedCharacter8 (); - } else if (type === 'short' || type === 'int16') { - return reader.ReadInteger16 (); - } else if (type === 'ushort' || type === 'uint16') { - return reader.ReadUnsignedInteger16 (); - } else if (type === 'int' || type === 'int32') { - return reader.ReadInteger32 (); - } else if (type === 'uint' || type === 'uint32') { - return reader.ReadUnsignedInteger32 (); - } else if (type === 'float' || type === 'float32') { - return reader.ReadFloat32 (); - } else if (type === 'double' || type === 'double64') { - return reader.ReadDouble64 (); - } - return null; - } - - if (format.isSingle) { - return ReadType (reader, format.elemType); - } else { - let list = []; - let count = ReadType (reader, format.countType); - for (let i = 0; i < count; i++) { - list.push (ReadType (reader, format.elemType)); - } - return list; - } - } };