Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion on sub-objects and materials #89

Open
NumaNumaNuma opened this issue Apr 1, 2017 · 29 comments
Open

Discussion on sub-objects and materials #89

NumaNumaNuma opened this issue Apr 1, 2017 · 29 comments
Assignees

Comments

@NumaNumaNuma
Copy link

NumaNumaNuma commented Apr 1, 2017

Hi,

I'm bringing in an obj model with sub-objects. the suObjectAttribute works fine to assign points back to the correct sub-objects, but uv's don't come out properly. here's what I'm doing:

        for (var i = 0, k = 0, l = 0; i < numVertexCoordinates; i += 3, k++, l +=2) {            
       
        // Get sub object id
        subObjectId = subObjAttributeData.GetValue(k);

        // Positions
       // globalToLocalMap[] is a map to match each global point index to its corresponding index on a sub-object

        subObjectBuffers[subObjectId].vertices[globalToLocalMap[k]*3]   = -posAttributeData.GetValue(i);
        subObjectBuffers[subObjectId].vertices[globalToLocalMap[k]*3+1] = posAttributeData.GetValue(i + 1);
        subObjectBuffers[subObjectId].vertices[globalToLocalMap[k]*3+2] = posAttributeData.GetValue(i + 2);

        // Normals
        if (normalAttId != -1) {
            subObjectBuffers[subObjectId].normals[globalToLocalMap[k]*3]   = norAttributeData.GetValue(i);
            subObjectBuffers[subObjectId].normals[globalToLocalMap[k]*3+1] = norAttributeData.GetValue(i + 1);
            subObjectBuffers[subObjectId].normals[globalToLocalMap[k]*3+2] = norAttributeData.GetValue(i + 2);
        }
        // Uv's
        if (texCoordAttId != -1) {
            subObjectBuffers[subObjectId].uvs[globalToLocalMap[k]*2] = textCoordAttributeData.GetValue(l);
            subObjectBuffers[subObjectId].uvs[globalToLocalMap[k]*2+1] = textCoordAttributeData.GetValue(l + 1);
        }
    }

result:
https://puu.sh/v58lD/bf2c2363d9.png

thanks

@NumaNumaNuma NumaNumaNuma changed the title UV and sub-objects UV coming out incorrectly on sub-objects Apr 1, 2017
@ondys
Copy link
Collaborator

ondys commented Apr 3, 2017

@NumaNumaNuma Thanks for the report. Is this happening with the latest version of the javascript decoder? Just checking, because last week we have fixed some issues with UV decoding that may be related to the problem that you are experiencing.

@NumaNumaNuma
Copy link
Author

I'm 2 commits behind I think, is this the one you're talking about:
"6763aa32 - Our javascript decoders are now built with flag for precise floating
point operations. This should resolve some issues with texture
coordinate compression."

@ondys
Copy link
Collaborator

ondys commented Apr 3, 2017

Yes, that's the one that fixed the issue for other users

@NumaNumaNuma
Copy link
Author

I'll pull and check

@NumaNumaNuma
Copy link
Author

NumaNumaNuma commented Apr 3, 2017

It looks different but still not right (assuming my code is correct?)
http://puu.sh/v7C0M/454a8f779b.png

@ondys
Copy link
Collaborator

ondys commented Apr 3, 2017

Can you post your code for generating globalToLocalMap ? Also if you send me the model with the texture + material I can try it on our end. From the last image, it looks like the texture coordinates are decoded correctly (no weird deformations), but the mapping between uvs and subobjects (or textures and subobjects) is somehow wrong.

@NumaNumaNuma
Copy link
Author

NumaNumaNuma commented Apr 3, 2017

I think 'k' is ok, it's incremented once while 'i' is incremented 3 times it's basically i/3. points/normals/faces all map correctly.

Here is the code:

    // Count
    for (var i = 0, k = 0; i < numVertexCoordinates; i += 3, k ++) {

        subObjectId = subObjAttributeData.GetValue(k);

        // If subObjectId isn't in the list yet, create it and give it a count of 1
        if (!(subObjectId in subObjectInfo)) {
            subObjectInfo[subObjectId] = 1;
        }
        // Otherwise increment count
        else {
            subObjectInfo[subObjectId]++;
        }
        // Map global index with local index, (count -1)
        globalToLocalMap[k] = subObjectInfo[subObjectId] - 1;
    }

    // Create buffers for each subobject
    for (var key in subObjectInfo){

        geometryBuffer = {
            indices: [],
            vertices: new Float32Array(subObjectInfo[key] * 3),
            normals: new Float32Array(subObjectInfo[key] * 3),
            uvs: new Float32Array(subObjectInfo[key] * 2)                
        };
        subObjectBuffers[key] = geometryBuffer;
    }

    for (var i = 0, k = 0, l = 0; i < numVertexCoordinates; i += 3, k++, l +=2) {

        subObjectId = subObjAttributeData.GetValue(Math.floor(k));

        // Positions
        subObjectBuffers[subObjectId].vertices[globalToLocalMap[k]*3]   = -posAttributeData.GetValue(i);
        subObjectBuffers[subObjectId].vertices[globalToLocalMap[k]*3+1] = posAttributeData.GetValue(i + 1);
        subObjectBuffers[subObjectId].vertices[globalToLocalMap[k]*3+2] = posAttributeData.GetValue(i + 2);

        // Normals
        if (normalAttId != -1) {
            subObjectBuffers[subObjectId].normals[globalToLocalMap[k]*3]   = norAttributeData.GetValue(i);
            subObjectBuffers[subObjectId].normals[globalToLocalMap[k]*3+1] = norAttributeData.GetValue(i + 1);
            subObjectBuffers[subObjectId].normals[globalToLocalMap[k]*3+2] = norAttributeData.GetValue(i + 2);
        }
        // Uv's
        if (texCoordAttId != -1) {
            subObjectBuffers[subObjectId].uvs[globalToLocalMap[k]*2] = textCoordAttributeData.GetValue(l);
            subObjectBuffers[subObjectId].uvs[globalToLocalMap[k]*2+1] = textCoordAttributeData.GetValue(l + 1);
        }
    }

@NumaNumaNuma
Copy link
Author

I have emailed you the files. thanks!

@NumaNumaNuma
Copy link
Author

Ok I found the problem, your latest patch DID fix it. The engine I'm using has inverted Y coordinates, so I had to flip the second UV value and it's all good now. thanks very much!

@ondys
Copy link
Collaborator

ondys commented Apr 3, 2017

@NumaNumaNuma Thanks for the update. Good to know!

@openforus
Copy link

@NumaNumaNuma
I want to know how you get the subObjAttributeData and the subObjectId? Also the subObject model is mesh or point ? use wrapper.GetAttributeId(dracoGeometry, dracoDecoder.GENERIC)?

@ondys
Copy link
Collaborator

ondys commented Apr 5, 2017

@openforus Sub object attribute are automatically created when encoding .obj files that define object groups using o property. More details how to get the attribute can be found for example here: #67 (comment)

@openforus
Copy link

openforus commented Apr 6, 2017 via email

@openforus
Copy link

Hi ondys NumaNumaNuma,
Is it only supported point cloud for sub-objects?So for TRIANGULAR_MESH I want to know how to get the MeshFace to set the sub-object's geometryBuffer.indices

@ondys
Copy link
Collaborator

ondys commented Apr 11, 2017

@openforus I believe it's actually supported only for triangular meshes (not point clouds). To add indices for sub-objects above you can for example add one extra loop before the Create buffers for each subobjects comment:

numSubObjectIndices = new Int32Array(subObjectInfo.length);
for (let i = 0; i < subObjectInfo.length; ++i) numSubObjectIndices[i] = 0;
for (let i = 0; i < 3 * numFaces; ++i) {
  const pointId = indices.GetValue(i);
  subObjectId = subObjAttributeData.GetValue(pointId);
  numSubObjectIndices[subObjectId]++;
}

then you allocate indices for each subobject: replace indices: [], in the Numa's code above with:

 indices: new Uint32Array(numSubObjectIndices[key]),

lastly you add one more loop at the end where you fill the indices as:

for (let i = 0; i < subObjectInfo.length; ++i) numSubObjectIndices[i] = 0;
for (let i = 0; i < 3 * numFaces; ++i) {
  const pointId = indices.GetValue(i);
  subObjectId = subObjAttributeData.GetValue(pointId);
  subObjectBuffers[subObjectId].indices[numSubObjectIndices[subObjectId]++] = globalToLocalMap[pointId];
}

@openforus
Copy link

@ondys thaks ondys ,I will try later ! Thanks again for your help!

@shubhamagarwal003
Copy link

shubhamagarwal003 commented Aug 28, 2017

@NumaNumaNuma @ondys
I used the approach suggested here to get subobjects and apply material on them which are stored in a separate .mtl file. The approach works fine.
But sometimes the subobject have multiple materials associated with them. For ex; the model at the link,
https://drive.google.com/open?id=0B5ZnEve9BlcVWldWUFU5cS1IQ3M.
For including such cases I separated subobjects with both different subobject id and material id. For ex

 for (var i = 0, k = 0; i < numVertexCoordinates; i += 3, k ++) {

        subObjectId = subObjAttributeData.GetValue(k);
        var matId = materialAttributeData.GetValue(k);
        var key = subObjectId.toString() + ":" + matId.toString();
        // If key isn't in the dict yet, create it and give it a count of 1
        if (!(key in subObjectInfo)) {
            subObjectInfo[key] = 1;
        }
        // Otherwise increment count
        else {
            subObjectInfo[key]++;
        }
        // Map global index with local index, (count -1)
        globalToLocalMap[k] = subObjectInfo[key] - 1;
    }

Changing the subsequent code accordingly. But the issue occurs when the same sub-object have same material repeated twice in .obj file (For ex; the one in the link). So can you suggest what can be done to include that case (Though these may not occur very frequently)?

@JackC09
Copy link

JackC09 commented Sep 6, 2017

Hi, I’m little bit confused when I try to decode models materialAttrId and subObjAttId return always -1. For shubhamagarwal003’s ex (you add extra 'a' at the end of your link) if I encode it with command

$ ./draco_encoder -i car.obj -o car.drc --metadata

I have:

Encoder options:
Compression level = 7
Positions: Quantization = 14 bits
Texture coordinates: Quantization = 12 bits
Normals: Quantization = 10 bits

Encoded mesh saved to car.drc (42 ms to encode)

Encoded size = 133520 bytes

And same size without --metadata tag

@shubhamagarwal003 can you share me your DracoLoader code please?

@ondys
Copy link
Collaborator

ondys commented Sep 6, 2017

@shubhamagarwal003 I believe there is a bug in Draco obj loader with repeated materials in one obj files that should be fixed in our next release

@JackC09 Thanks for the report, I'll investigate

@ondys ondys self-assigned this Sep 6, 2017
@shubhamagarwal003
Copy link

@JackC09 which commit are you using. I suppose this PR should fix your issue

@JackC09
Copy link

JackC09 commented Sep 7, 2017

@shubhamagarwal003 I use the latest commit.
I think I'm doing something wrong in DracoLoader. Can you send me yours?

@shubhamagarwal003
Copy link

@JackC09 I've done changes in DracoLoader.js in the repo. Mostly in function convertDracoGeometryTo3JS. Here is my modified function (Sorry for the code quality).

convertDracoGeometryTo3JS: function(dracoDecoder, decoder, geometryType, buffer) {
        if (this.getAttributeOptions('position').skipDequantization === true) {
          decoder.SkipAttributeTransform(dracoDecoder.POSITION);
        }
        var dracoGeometry;
        var decodingStatus;
        const start_time = performance.now();
        if (geometryType === dracoDecoder.TRIANGULAR_MESH) {
          dracoGeometry = new dracoDecoder.Mesh();
          decodingStatus = decoder.DecodeBufferToMesh(buffer, dracoGeometry);
        } else {
          dracoGeometry = new dracoDecoder.PointCloud();
          decodingStatus =
              decoder.DecodeBufferToPointCloud(buffer, dracoGeometry);
        }
        if (!decodingStatus.ok() || dracoGeometry.ptr == 0) {
          var errorMsg = 'THREE.DRACOLoader: Decoding failed: ';
          errorMsg += decodingStatus.error_msg();
          console.error(errorMsg);
          dracoDecoder.destroy(decoder);
          dracoDecoder.destroy(dracoGeometry);
          throw new Error(errorMsg);
        }

        var decode_end = performance.now();
        dracoDecoder.destroy(buffer);
        /*
         * Example on how to retrieve mesh and attributes.
         */
        var numFaces, numPoints;
        var numVertexCoordinates, numTextureCoordinates, numColorCoordinates;
        var numAttributes;
        var numColorCoordinateComponents = 3;
        // For output basic geometry information.
        var geometryInfoStr;
        if (geometryType == dracoDecoder.TRIANGULAR_MESH) {
          numFaces = dracoGeometry.num_faces();
          if (this.verbosity > 0) {
            console.log('Number of faces loaded: ' + numFaces.toString());
          }
        } else {
          numFaces = 0;
        }
        numPoints = dracoGeometry.num_points();
        numVertexCoordinates = numPoints * 3;
        numTextureCoordinates = numPoints * 2;
        numColorCoordinates = numPoints * 3;
        numAttributes = dracoGeometry.num_attributes();
        console.log("dracoGeometry", dracoGeometry);
        if (this.verbosity > 0) {
          console.log('Number of points loaded: ' + numPoints.toString());
          console.log('Number of attributes loaded: ' +
              numAttributes.toString());
        }


        // Get position attribute. Must exists.
        var posAttId = decoder.GetAttributeId(dracoGeometry,
                                                dracoDecoder.POSITION);
        if (posAttId == -1) {
          var errorMsg = 'THREE.DRACOLoader: No position attribute found.';
          console.error(errorMsg);
          dracoDecoder.destroy(decoder);
          dracoDecoder.destroy(dracoGeometry);
          throw new Error(errorMsg);
        }

        var posAttribute = decoder.GetAttribute(dracoGeometry, posAttId);
        var posAttributeData = new dracoDecoder.DracoFloat32Array();
        decoder.GetAttributeFloatForAllPoints(
            dracoGeometry, posAttribute, posAttributeData);
        console.log("posAttribute", posAttribute);

        // Get color attributes if exists.
        var colorAttId = decoder.GetAttributeId(dracoGeometry,
                                                  dracoDecoder.COLOR);
        var colAttributeData;
        if (colorAttId != -1) {
          if (this.verbosity > 0) {
            console.log('Loaded color attribute.');
          }
          var colAttribute = decoder.GetAttribute(dracoGeometry, colorAttId);
          if (colAttribute.num_components() === 4) {
            numColorCoordinates = numPoints * 4;
            numColorCoordinateComponents = 4;
          }
          colAttributeData = new dracoDecoder.DracoFloat32Array();
          decoder.GetAttributeFloatForAllPoints(dracoGeometry, colAttribute,
                                                colAttributeData);
        }

        // Get normal attributes if exists.
        var normalAttId =
            decoder.GetAttributeId(dracoGeometry, dracoDecoder.NORMAL);
        var norAttributeData;
        if (normalAttId != -1) {
          if (this.verbosity > 0) {
            console.log('Loaded normal attribute.');
          }
          var norAttribute = decoder.GetAttribute(dracoGeometry, normalAttId);
          norAttributeData = new dracoDecoder.DracoFloat32Array();
          decoder.GetAttributeFloatForAllPoints(dracoGeometry, norAttribute,
                                                norAttributeData);
        }

        // Get texture coord attributes if exists.
        var texCoordAttId =
            decoder.GetAttributeId(dracoGeometry, dracoDecoder.TEX_COORD);
        var textCoordAttributeData;
        if (texCoordAttId != -1) {
          if (this.verbosity > 0) {
            console.log('Loaded texture coordinate attribute.');
          }
          var texCoordAttribute = decoder.GetAttribute(dracoGeometry,
                                                         texCoordAttId);
          textCoordAttributeData = new dracoDecoder.DracoFloat32Array();
          decoder.GetAttributeFloatForAllPoints(dracoGeometry,
                                                texCoordAttribute,
                                                textCoordAttributeData);
        }

        var materialAttrId = decoder.GetAttributeIdByName(dracoGeometry, "material");
        
        var materialAttributeData;
        if (materialAttrId != -1) {
          if (this.verbosity > 0) {
            console.log('Loaded material attribute.');
          }
        }

   
        var materialAttribute = decoder.GetAttribute(dracoGeometry,
                                                       materialAttrId);
        materialAttributeData = new dracoDecoder.DracoFloat32Array();
        decoder.GetAttributeFloatForAllPoints(dracoGeometry,
                                              materialAttribute,
                                              materialAttributeData);


        var subObjAttId = decoder.GetAttributeIdByName(dracoGeometry, "sub_obj");
        var subObjAttributeData;
        if (subObjAttId != -1) {
          if (this.verbosity > 0) {
            console.log('Loaded Sub Obj attribute.');
          }
        }

   
        var subObjAttribute = decoder.GetAttribute(dracoGeometry,
                                                       subObjAttId);
        subObjAttributeData = new dracoDecoder.DracoFloat32Array();
        decoder.GetAttributeFloatForAllPoints(dracoGeometry,
                                              subObjAttribute,
                                              subObjAttributeData);

        var subObjectInfo = {};
        var subObjectBuffers = [];
        var globalToLocalMap = {};
        for (var i = 0, k = 0; i < numVertexCoordinates; i += 3, k ++) {
            var subObjectId = subObjAttributeData.GetValue(k);
            var matId = materialAttributeData.GetValue(k);
            var key = subObjectId.toString() + ":" + matId.toString();
            // If subObjectId isn't in the list yet, create it and give it a count of 1
            if (!(key in subObjectInfo)) {
                subObjectInfo[key] = 1;
            }
            // Otherwise increment count
            else {
                subObjectInfo[key]++;
            }
            // Map global index with local index, (count -1)
            globalToLocalMap[k] = subObjectInfo[key] - 1;
        }
        var indices;

        if (geometryType == dracoDecoder.TRIANGULAR_MESH) {
          if (this.drawMode === THREE.TriangleStripDrawMode) {
            var stripsArray = new dracoDecoder.DracoInt32Array();
            var numStrips = decoder.GetTriangleStripsFromMesh(
                dracoGeometry, stripsArray);
            indices = new Uint32Array(stripsArray.size());
            for (var i = 0; i < stripsArray.size(); ++i) {
              indices[i] = stripsArray.GetValue(i);
            }
            dracoDecoder.destroy(stripsArray);
          } else {
            var numIndices = numFaces * 3;
            indices = new Uint32Array(numIndices);
            var ia = new dracoDecoder.DracoInt32Array();
            for (var i = 0; i < numFaces; ++i) {
              decoder.GetFaceFromMesh(dracoGeometry, i, ia);
              var index = i * 3;
              indices[index] = ia.GetValue(0);
              indices[index + 1] = ia.GetValue(1);
              indices[index + 2] = ia.GetValue(2);
            }
            dracoDecoder.destroy(ia);
         }
        }

        var subObjectInfoKeys = Object.keys(subObjectInfo);

        var numSubObjectIndices = {}; //new Int32Array(subObjectInfoKeys.length);
        for (var i in subObjectInfo) numSubObjectIndices[i] = 0;
        for (var i = 0; i < 3 * numFaces; ++i) {
          const pointId = indices[i];
          var subObjectId = subObjAttributeData.GetValue(pointId);
          var matId = materialAttributeData.GetValue(pointId);
          var key = subObjectId.toString() + ":" + matId.toString();
          numSubObjectIndices[key]++;
        }

        for (var key in subObjectInfo){
            var geometryBuffer = {
                indices: new Uint32Array(numSubObjectIndices[key]),
                vertices: new Float32Array(subObjectInfo[key] * 3),
                normals: new Float32Array(subObjectInfo[key] * 3),
                uvs: new Float32Array(subObjectInfo[key] * 2),
                colors: new Float32Array(subObjectInfo[key] * 3)
            };
            subObjectBuffers[key] = {"geometryBuffer": geometryBuffer, "materialId": -1};
        }



        for (var i = 0, k = 0, l = 0; i < numVertexCoordinates; i += 3, k++, l +=2) {
            var subObjectId = subObjAttributeData.GetValue(k);
            var matId = materialAttributeData.GetValue(k);
            var key = subObjectId.toString() + ":" + matId.toString();

            // Positions
            subObjectBuffers[key].geometryBuffer.vertices[globalToLocalMap[k]*3]   = posAttributeData.GetValue(i);
            subObjectBuffers[key].geometryBuffer.vertices[globalToLocalMap[k]*3+1] = posAttributeData.GetValue(i + 1);
            subObjectBuffers[key].geometryBuffer.vertices[globalToLocalMap[k]*3+2] = posAttributeData.GetValue(i + 2);

            // Normals
            if (normalAttId != -1) {
                subObjectBuffers[key].geometryBuffer.normals[globalToLocalMap[k]*3]   = norAttributeData.GetValue(i);
                subObjectBuffers[key].geometryBuffer.normals[globalToLocalMap[k]*3+1] = norAttributeData.GetValue(i + 1);
                subObjectBuffers[key].geometryBuffer.normals[globalToLocalMap[k]*3+2] = norAttributeData.GetValue(i + 2);
            }
            if (colorAttId != -1) {
              // Draco colors are already normalized.
              subObjectBuffers[key].geometryBuffer.colors[globalToLocalMap[k]*3] = colAttributeData.GetValue(i);
              subObjectBuffers[key].geometryBuffer.colors[globalToLocalMap[k]*3+1] = colAttributeData.GetValue(i + 1);
              subObjectBuffers[key].geometryBuffer.colors[globalToLocalMap[k]*3+2] = colAttributeData.GetValue(i + 2);
            } else {
              // Default is white. This is faster than TypedArray.fill().
              subObjectBuffers[key].geometryBuffer.colors[globalToLocalMap[k]*3] = 1.0;
              subObjectBuffers[key].geometryBuffer.colors[globalToLocalMap[k]*3+1] = 1.0;
              subObjectBuffers[key].geometryBuffer.colors[globalToLocalMap[k]*3+2] = 1.0;
            }
            // Uv's
            if (texCoordAttId != -1) {
                subObjectBuffers[key].geometryBuffer.uvs[globalToLocalMap[k]*2] = textCoordAttributeData.GetValue(l);
                subObjectBuffers[key].geometryBuffer.uvs[globalToLocalMap[k]*2+1] = textCoordAttributeData.GetValue(l + 1);
            }
            if(materialAttrId != -1){
              subObjectBuffers[key].materialId = materialAttributeData.GetValue(k);
              /*if(subObjectBuffers[key].materialId.indexOf(matId) == -1){
                   subObjectBuffers[key].materialId.push(matId);
              }*/
            }
        }


        for (var i in subObjectInfo) numSubObjectIndices[i] = 0;
        for (var i = 0; i < 3 * numFaces; ++i) {
          const pointId = indices[i];
          var subObjectId = subObjAttributeData.GetValue(pointId);
          var matId = materialAttributeData.GetValue(pointId);
          var key = subObjectId.toString() + ":" + matId.toString();
          subObjectBuffers[key].geometryBuffer.indices[numSubObjectIndices[key]++] = globalToLocalMap[pointId];
        }


        var container = new THREE.Group();
        var scales = [];
        var materialKeys = Object.keys(this.materials.materials);


        for(var key in subObjectBuffers){
            var geometryBuffer = subObjectBuffers[key].geometryBuffer;
            var geometry = new THREE.BufferGeometry();
            geometry.drawMode = this.drawMode;
            if (geometryType == dracoDecoder.TRIANGULAR_MESH) {
              geometry.setIndex(new(geometryBuffer.indices.length > 65535 ?
                    THREE.Uint32BufferAttribute : THREE.Uint16BufferAttribute)
                  (geometryBuffer.indices, 1));
            }
            geometry.addAttribute('position',
                new THREE.Float32BufferAttribute(geometryBuffer.vertices, 3));
            var posTransform = new dracoDecoder.AttributeQuantizationTransform();
            if (posTransform.InitFromAttribute(posAttribute)) {
              // Quantized attribute. Store the quantization parameters into the
              // THREE.js attribute.
              geometry.attributes['position'].isQuantized = false;
              geometry.attributes['position'].maxRange = posTransform.range();
              geometry.attributes['position'].numQuantizationBits =
                  posTransform.quantization_bits();
              geometry.attributes['position'].minValues = new Float32Array(3);
              for (var i = 0; i < 3; ++i) {
                geometry.attributes['position'].minValues[i] =
                    posTransform.min_value(i);
              }
            }
            dracoDecoder.destroy(posTransform);
            geometry.addAttribute('color',
                new THREE.Float32BufferAttribute(geometryBuffer.colors,
                                                 numColorCoordinateComponents));
            if (normalAttId != -1) {
              geometry.addAttribute('normal',
                  new THREE.Float32BufferAttribute(geometryBuffer.normals, 3));
            }
            if (texCoordAttId != -1) {
              geometry.addAttribute('uv',
                  new THREE.Float32BufferAttribute(geometryBuffer.uvs, 2));
            }

            var material = this.materials.materials[materialKeys[subObjectBuffers[key].materialId]];
            material.shading = THREE.SmoothShading;
            var mesh = new THREE.Mesh( geometry, material );

            mesh.drawMode = this.drawMode;
            geometry.computeBoundingBox();

            mesh.name = key;
            container.add( mesh );
        }
        return container;
}

I've another function setMaterials in which I set the materials loaded from Mtl-Loader.

mtlLoader.setPath('<path-to-your-mtl-file>');
    mtlLoader.load('<mtl-filename>', function(materials) {
    materials.preload();
    dracoLoader.setMaterials(materials);
    dracoLoader.decodeDracoFile(reader.result, function(contain) {
        scene.add(contain);
    });
});

@JackC09
Copy link

JackC09 commented Sep 7, 2017

@shubhamagarwal003 thanks it's really useful for me.

@ondys by placing --metadata flag before like this

$ ./draco_encoder --metadata -i car.obj -o car.drc

result is better with shubhamagarwal003's model:

Encoded size = 133614 bytes

Now I have subObjAttId but materialAttrId still return -1

@ondys
Copy link
Collaborator

ondys commented Sep 7, 2017

@JackC09 Yes there was a bug in Draco when --metadata was the last argument passed in (in which case it was ignored). It's fixed now in our private repo and we will push the fix to public in the coming days.

I'll look into the issue with materialAttrId == -1

@JackC09
Copy link

JackC09 commented Sep 13, 2017

@ondys Hi, I tried the latest commit 1.1.0 and for some models materialAttrId was ok but subObjAttId == -1
https://drive.google.com/drive/folders/0B7BhishE3I-cc1VkMS0xekd4Wjg?usp=sharing

In the description it is written 'Draco can preserve material or sub-object names' how can I get the subObjName?

@ondys
Copy link
Collaborator

ondys commented Sep 29, 2017

Which of the shared model had the problem with subObjAttId ? Note that subobject ids are currently generated only when the obj uses "o " keyword. When the .obj is encoded with --metadata flag, the metadata for sub object id attribute will then contain mapping between sub-object ids and the corresponding sub object names.

@yuerdev
Copy link

yuerdev commented Jan 10, 2018

@ondys where map between sub-object ids and the corresponding sub object names?
or how get sub object name?

@ondys
Copy link
Collaborator

ondys commented Jan 10, 2018

@PumpkinDev In c++ you can see an example in ObjEncoder::GetSubObjects() method (in obj_encoder.cc).
For javascript, it seems we miss some API that is needed to accomplish this. I'll make the necessary changes and try to push into into our next update.

@FarhadG
Copy link

FarhadG commented Apr 4, 2018

Do we have any programmatic way of loading a .drc file that has several textures? I have a large model (.obj) that was generated using a photogrammetry service. When I compress the file to .drc, I cannot get the multiple textures that the photogrammetry services generates for the single .obj to map properly. If you have any suggestions, it would be extremely helpful, as it's becoming a huge blocker for us.

I am thinking of writing a parser to separate the OBJ into several sub OBJs to reference each materials file individually, but perhaps we already have a working version of something similar (or better) than this approach?

@FrankGalligan FrankGalligan changed the title UV coming out incorrectly on sub-objects Discussion on sub-objects and materials Aug 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants