From 026cde075d0139269e02d5195eb3d9446c732565 Mon Sep 17 00:00:00 2001 From: Andriy Sheredko Date: Wed, 20 Aug 2025 15:40:56 +0300 Subject: [PATCH 1/4] ENG-8627 | Fix .3ds files not rendering in MFR viewer --- mfr/extensions/jsc3d/static/js/jsc3d.3ds.js | 67 ++++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js b/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js index 117a33f69..4324f87b9 100644 --- a/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js +++ b/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js @@ -199,9 +199,12 @@ JSC3D.Autodesk3DSLoader.prototype.readAmount = function(reader,end) { len = reader.readUInt32(); switch (cid) { - case 0x0030: // Floats + case 0x0030: amount = reader.readUInt16(); break; + case 0x0031: + amount = reader.readFloat32() * 100.0; + break; default: break; } @@ -489,8 +492,8 @@ JSC3D.Autodesk3DSLoader.prototype.parseSmoothingGroups = function (reader) { JSC3D.Autodesk3DSLoader.prototype.finalizeCurrentMaterial = function () { var mat = new JSC3D.Material; - if (this._cur_mat.colorMap) { - mat.textureFileName = this._cur_mat.colorMap.texture; + if (this._cur_mat.colorMap && this._cur_mat.colorMap.url) { + mat.textureFileName = this._cur_mat.colorMap.url; } else { mat.diffuseColor = this._cur_mat.diffuseColor; @@ -572,25 +575,59 @@ JSC3D.Autodesk3DSLoader.prototype.parse3DS = function(scene, data) { // mesh.texCoordIndexBuffer = mesh.indexBuffer; mesh.material = new JSC3D.Material; - var materialFaces = this._cur_obj.materialFaces; - var currentMaterial = null; - for(var materialName in materialFaces){ - currentMaterial = this._materials[materialName]; - if (currentMaterial.colorMap) { + // Defaults: opaque & double-sided (helps open meshes) + mesh.material.transparency = 0; + mesh.isDoubleSided = true; + mesh.material.bothSides = true; + + var materialFaces = this._cur_obj.materialFaces || {}; + var sawMaterial = false; + for (var materialName in materialFaces) { + if (!Object.prototype.hasOwnProperty.call(materialFaces, materialName)) + continue; + sawMaterial = true; + + var currentMaterial = this._materials[materialName]; + if (!currentMaterial) { + if (JSC3D.console) JSC3D.console.logWarning('3DS: missing material "' + materialName + '", using defaults.'); + continue; + } + + if (currentMaterial.colorMap && currentMaterial.colorMap.url) { if(JSC3D.console) - JSC3D.console.logInfo('set texture: '+currentMaterial.colorMap.url); + JSC3D.console.logInfo('set texture: ' + currentMaterial.colorMap.url); this.setupTexture([mesh], currentMaterial.colorMap.url); } - else { + else if (currentMaterial.diffuseColor != null) { mesh.material.diffuseColor = currentMaterial.diffuseColor; } -// mesh.material.ambientColor = currentMaterial.ambientColor; -// mesh.material.simulateSpecular = (currentMaterial.specularColor>0); - mesh.isDoubleSided = true;//currentMaterial.twoSided; - mesh.material.transparency = currentMaterial.transparency>0?(currentMaterial.transparency)/100:0; + + // Transparency: normalize (0..1), snap tiny values to 0 to avoid z-sort artifacts + var t = currentMaterial.transparency; + if (typeof t === 'number') { + var alpha = (t > 1) ? (t / 100.0) : t; + alpha = Math.max(0, Math.min(1, alpha)); + if (alpha < 0.01) alpha = 0; + mesh.material.transparency = alpha; + } else { + mesh.material.transparency = 0; + } + + var two = (currentMaterial.twoSided !== undefined) ? !!currentMaterial.twoSided : true; + mesh.isDoubleSided = two; + mesh.material.bothSides = two; } + if (!sawMaterial) { + mesh.isDoubleSided = true; + mesh.material.bothSides = true; + mesh.material.transparency = 0; + } + if (!mesh.texCoordBuffer || !mesh.texCoordIndexBuffer) { + mesh.texCoordBuffer = null; + mesh.texCoordIndexBuffer = null; + } //mesh.faceNormalBuffer = []; // mesh.init(); @@ -672,7 +709,7 @@ JSC3D.Autodesk3DSLoader.prototype.parse3DS = function(scene, data) { this._cur_obj = {}; this._cur_obj.name = this.readNulTermString(reader); this._cur_obj.materials = []; - this._cur_obj.materialFaces = []; + this._cur_obj.materialFaces = {}; break; case 0x4100: // OBJ_TRIMESH From da41d850ac89fa0533bdd01c692f196f2c739f3e Mon Sep 17 00:00:00 2001 From: Andriy Sheredko Date: Wed, 20 Aug 2025 15:47:55 +0300 Subject: [PATCH 2/4] ENG-8627 | Fix CI flake8 error --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index d674820e5..5af81b897 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -182,5 +182,5 @@ # default anyway. This block will use the same theme when building locally # as on RTD. if not on_rtd: - import sphinx_rtd_theme + import sphinx_rtd_theme # noqa: F401 html_theme = 'sphinx_rtd_theme' From ccdfc5905f889fdad259cf96b76a26f4edf735d3 Mon Sep 17 00:00:00 2001 From: Andriy Sheredko Date: Wed, 20 Aug 2025 19:18:19 +0300 Subject: [PATCH 3/4] ENG-8627 | code style fixes --- mfr/extensions/jsc3d/static/js/jsc3d.3ds.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js b/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js index 4324f87b9..958f8f946 100644 --- a/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js +++ b/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js @@ -580,16 +580,18 @@ JSC3D.Autodesk3DSLoader.prototype.parse3DS = function(scene, data) { mesh.isDoubleSided = true; mesh.material.bothSides = true; - var materialFaces = this._cur_obj.materialFaces || {}; - var sawMaterial = false; - for (var materialName in materialFaces) { + let materialFaces = this._cur_obj.materialFaces || {}; + let sawMaterial = false; + for (let materialName in materialFaces) { if (!Object.prototype.hasOwnProperty.call(materialFaces, materialName)) continue; sawMaterial = true; var currentMaterial = this._materials[materialName]; if (!currentMaterial) { - if (JSC3D.console) JSC3D.console.logWarning('3DS: missing material "' + materialName + '", using defaults.'); + if (JSC3D.console) { + JSC3D.console.logWarning('3DS: missing material "' + materialName + '", using defaults.'); + } continue; } From c25c60a3f1cc4ea3e6b125d0288e964adcb12423 Mon Sep 17 00:00:00 2001 From: Andriy Sheredko Date: Thu, 21 Aug 2025 13:51:38 +0300 Subject: [PATCH 4/4] ENG-8627 | code style fixes --- mfr/extensions/jsc3d/static/js/jsc3d.3ds.js | 30 ++++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js b/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js index 958f8f946..539e05009 100644 --- a/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js +++ b/mfr/extensions/jsc3d/static/js/jsc3d.3ds.js @@ -77,11 +77,13 @@ JSC3D.Autodesk3DSLoader.prototype.loadFromUrl = function(urlName) { xhr.onreadystatechange = function() { if(this.readyState == 4) { if(this.status == 200 || this.status == 0) { - if(JSC3D.console) + if(JSC3D.console) { JSC3D.console.logInfo('Finished loading 3DS file "' + urlName + '".'); + } if(self.onload) { - if(self.onprogress) + if(self.onprogress) { self.onprogress('Loading 3DS file ...', 1); + } // if(JSC3D.PlatformInfo.browser == 'ie' && JSC3D.PlatformInfo.version >= '10') { // // asynchronously decode blob to binary string // var blobReader = new FileReader; @@ -107,10 +109,12 @@ JSC3D.Autodesk3DSLoader.prototype.loadFromUrl = function(urlName) { } } else { - if(JSC3D.console) + if(JSC3D.console) { JSC3D.console.logError('Failed to load 3DS file "' + urlName + '".'); - if(self.onerror) + } + if(self.onerror) { self.onerror('Failed to load 3DS file "' + urlName + '".'); + } } self.request = null; } @@ -464,14 +468,16 @@ JSC3D.Autodesk3DSLoader.prototype.parseObjectAnimation = function (reader,end) { if (name != '$$$DUMMY' && this._unfinalized_objects.hasOwnProperty(name)) { vo = this._unfinalized_objects[name]; // todo vasea - if(JSC3D.console) + if(JSC3D.console) { JSC3D.console.logInfo('Construct object '+vo.name); + } // this._cur_obj = null; obj = null;//this.constructObject(vo, pivot); if (obj) { - if(JSC3D.console) + if(JSC3D.console) { JSC3D.console.logInfo('finished loading the object '+vo.name); + } } delete this._unfinalized_objects[name]; @@ -520,8 +526,9 @@ JSC3D.Autodesk3DSLoader.prototype.setupTexture = function(meshList, textureUrlNa texture.onready = function() { for(var i=0; i