google / draco

Draco is a library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics.
https://google.github.io/draco/
Apache License 2.0
6.45k stars 961 forks source link

How to load uv for a decoded draco obj model #103

Open jungleowl opened 7 years ago

jungleowl commented 7 years ago

Hi, I am doing a project to use draco to compress my obj model. Compression is successful but I don't have any idea about how to load uv for the model when decoding the drc file while using the draco_mesh_decoder.js since the .mtl and corresponding jpg file are not covered by the draco compression process.
Could you please share me some example code or some links to introduce the solutions, thanks a lot! PS: I am using three.js as the basic frame.

ondys commented 7 years ago

UVs can be decoded as shown in the example in javascript/example/DRACOLoader.js .

As for loading materials and textures, you still need to send them separately as they are not included in the .drc file. If you are using three.js you can still parse the material directly using for example their MTLLoader that is going to create THREE.js material for you (with texture).

jungleowl commented 7 years ago

We have tried the above mentioned solution by following codes(partial). It turns out the model can be loaded correctly but the uv still remains missing. On the otherhand, when we use non-converted obj model with mtlloader, it works fine. We don't know where the problem sits and there is really very few reference can be found. Sincerely look forward to have your response to help us get out of this. Thanks a lot! @ondys


function loadOneModel() { if (loadedModel < numModels) { var mtlLoader = new THREE.MTLLoader(); mtlLoader.setPath( 'drc/' ); mtlLoader.load( 'atmo_fighter2.mtl', function( materials ) {

                materials.preload();

                var draco_file = new XMLHttpRequest();
                  draco_file.open("GET", "drc/atmo_fighter2.drc", true);
                  draco_file.responseType = "arraybuffer";
                  draco_file.send();
                  draco_file.onload = function(e) {
                  loadGeometry(draco_file.response);
                  loadOneModel();
                }
              })
          }
        }
ondys commented 7 years ago

Sorry for the late response. Can you send me the .drc model with the source .obj (+ the material and texture)? I should be able to help more when I have the input data.

jungleowl commented 7 years ago

Hi, Ondrej, I shall show my gratitude first for your response although you define it as a late response which is in fact nothing to a hungery guy seeking for answer. The attached document is the material you requested. Hope it does not bring you any inconvenience in term of your time. Look forward to have your late response again. :)

2017-04-21 13:49 GMT+08:00 Ondrej Stava notifications@github.com:

Sorry for the late response. Can you send me the .drc model with the source .obj (+ the material and texture)? I should be able to help more when I have the input data.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/google/draco/issues/103#issuecomment-296079732, or mute the thread https://github.com/notifications/unsubscribe-auth/AacGfNHxPTnVpzUyymWYaQcgAPknXRuOks5ryEN6gaJpZM4NABsf .

ondys commented 7 years ago

@jungleowl It seems that the attached document didn't make it all the way here. Or at least I can't see it. Github isn't really good with file attachments so you may need to upload it to some file sharing website and provide a link to the file.

jungleowl commented 7 years ago

Hi, Ondrej, Pls try to use this link which direct to the google cloud where I uploaded the required document. Thanks a lot! https://storage.googleapis.com/jungleowl-try/drcToGoogleDraco.zip

2017-04-22 5:36 GMT+08:00 Ondrej Stava notifications@github.com:

@jungleowl https://github.com/jungleowl It seems that the attached document didn't make it all the way here. Or at least I can't see it. Github isn't really good with file attachments so you may need to upload it to some file sharing website and provide a link to the file.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/draco/issues/103#issuecomment-296311033, or mute the thread https://github.com/notifications/unsubscribe-auth/AacGfH6Z5TMG7L9LY05uSWWymA9bK1SGks5rySFHgaJpZM4NABsf .

ondys commented 7 years ago

Thanks! I was able to download and test the files and all seemed to work ok for me. The code I used to load material is here:

 var mtlLoader = new THREE.MTLLoader();
 let material;
 mtlLoader.load( 'Tile_+000_+003.mtl', function( materials ) {
   materials.preload();
   material = materials.materials['Tile_+000_+003_0'];
   // bufferGeometry is a geometry decoded by DRACOLoader.js
   const geometry = new THREE.Mesh(bufferGeometry, material);
   // Add geometry to scene
 }

If it still doesn't work for you, please share your code where you assign the material to the decoded geometry.

jungleowl commented 7 years ago

Hi, Ondrej, We have tried the solution as above mentioned, but unfortunately it looks like we failed to hold the magic wand. Sincerely, seek your kind help again to drag us out from the situation. You can find our code as below which gives us a raw mesh. Looking forward to have your response, thanks a lot! @ondys


var onProgress = function(xhr){ if(xhr.lengthComputable){ var percentComplete = xhr.loader / xhr.total * 100; console.log(Math.round(percentComplete,2) + '%downloaded'); } };

        var onError = function(xhr){}

        var mtlLoader = new THREE.MTLLoader();
        mtlLoader.setPath('models/drc/');
        mtlLoader.load('Tile_+000_+003.mtl',function(materials){
            materials.preload();
            let material;
            materials = materials.materials['atmo_fighter_texture'];
            var draloader = new THREE.DRACOLoader();
            draloader.setPath('models/drc/');
            draloader.load('Tile_+000_+003.drc',function(obj){
                geometry = new THREE.Mesh(obj ,material)
                scene.add(geometry);
            },onProgress,onError);
        })
ondys commented 7 years ago

@jungleowl I see one problem in the snipped you posted:

materials = materials.materials['atmo_fighter_texture'];

it should be

material = materials.materials['atmo_fighter_texture'];
jungleowl commented 7 years ago

@ondys Hi, Ondrej, thanks for your reply. The caught problem has been corrected. But ,eventually, We discovered the true problem might not come from the uv applying step, instead, it came from the model loading part. The code below is that we used to load the draco compressed obj model, in fact, the model never been decompressed and rendered correctly since we could not see it in the screen. Tried to solve the problem but due to limitation on the programming, we failed once again. So we have to bother you again to have your help on the following codes, thanks a lot! *DRACO MODEL LOADING PART***** const fileDisplayArea = document.getElementById('fileDisplayArea');

    const dracoLoader = new THREE.DRACOLoader();
    const bufferGeometry = dracoLoader.decodeDracoFile(raw_data);

****UV APPLYING PART** var mtlLoader = new THREE.MTLLoader(); mtlLoader.setPath('models/drc/'); mtlLoader.load('atmo_fighter2.mtl',function(materials){ materials.preload(); let material; material = materials.materials['atmo_fighter_texture']; var draloader = new THREE.DRACOLoader(); draloader.setPath('models/drc/'); draloader.load('atmo_fighter2.drc',function(obj){ geometry = new THREE.Mesh(obj ,material) scene.add(geometry); },onProgress,onError); })

jungleowl commented 7 years ago

Hi, Ondrej, We have done many try with draco but still can't reach a success. I understand this is something of very basic application which could be kind of bothering to you, however, it is a serious crash on our ongoing research. Hereby, I have to make the comment again to gain a little attention of yours to help us on the above posted codes so that we can still have chance to save our current works. Honestly, we have to admit we are not professional 3D application developers but we want to be eventually. So sincerely request your kind help and very sorry for the occupation of your time.

ondys commented 7 years ago

Can you send me data for this atmo_fighter example? I really wish I could help more but I still don't see any problem loading a material file using the example you send me via email (except the line material = materials.materials['atmo_fighter_texture.jpg']; should most likely be material = materials.materials['atmo_fighter_texture'];

but other than that, I was able to load the texture with the data you sent me earlier (i.e. after I replaced atmofighter with Tile+000_+003 model)

jungleowl commented 7 years ago

Hi, Ondrej, It is finally working now. But we are encountering another problem. We are loading a scene including multiple models which are enormous in terms of the number of models, original size of each model is around 2MB and 100KB after compression of draco, the total is around 126M which most contents are jpg files . Problem is the texture of each model is quite big upto 1MB, even more. So when we load the scene with Chrome, the consumption of memory becomes very high causing the crash of Chrome, not mention to load it through safari on iphone. Kindly ask if there is any solution or good suggestion to manage this issue so that we can load the data in small device such as mobile phones since the purpose of draco compression solution is to reduce the system consumption and loading time.

ondys commented 7 years ago

since the purpose of draco compression solution is to reduce the system consumption and loading time

I would just like to clarify that main purpose of Draco is to speed-up streaming and to decrease storage requirements for meshes and point clouds. In the current version, we don't provide any tools that would allow you to reduce system resource consumption after the models are decompressed. We may add some features in future that may reduce memory consumption even for decompressed models, but it would most likely not really solve your problems anyway.

For your case, I would suggest looking at compressed texture formats (e.g. DXT1) + alternatively using lower resolution textures and meshes (LOD scheme). Also, in case you don't need to display all models at the same time, you should consider adding caching where not all models are loaded into the system memory all the time.

jungleowl commented 7 years ago

Ondrej, Yes, you are ABSOLUTELY right, I was misunderstanding the purpose of Draco. Now, with Draco, our project is going much better than before. I'd like to show my appreciation to you and all other engineers who work on Draco and hope more and more good utilities emerge in the coming future. Here I have another issue in the pipe. The following link includes a model which I couldn't use Draco_encoder.exe to compress. Windows stops the program and then Draco failed to compress the model and output nothing. It happens on all models in the same batch as the shared one as below. The model can be read correctly by other 3D tools such as 3dmax and so on. Could you please take a look on the file to see if the problem can be reproduced on your side? Thanks a lot! PS: if you think this should be opened as a new issue, pls indicate and I will follow. Link: http://pan.baidu.com/s/1dFf7Bgt

ghost commented 7 years ago

I also encountered the above problem and did not load the mtl material file.

ondys commented 7 years ago

@jungleowl

PS: if you think this should be opened as a new issue, pls indicate and I will follow. Link: http://pan.baidu.com/s/1dFf7Bgt

In future it would be better to open a new issue for this, but for now keep it here. I'll investigate and let you know when I have an update. Thanks for the report!

ondys commented 7 years ago

@1idontknow can you please post your code for loading materials + draco file?

ondys commented 7 years ago

@jungleowl I tried the attached model on both Win64 build and Linux build and in both cases it was compressed without issues (and decoded model looked same as the input). Can you give us more details about your configuration? (e.g. encoding options, OS, etc..). Thanks

jungleowl commented 7 years ago

Hi, Ondys, FYI, the OS I used is windows 7, 64bit, with service pack 1. I encoded the model with all default options. It works just fine on the other models except the batch having the attached one.

ondys commented 7 years ago

thanks. Did the model come with a .mtl file? If so, can you post it as well? The model loading pipeline works slightly differently when a .mtl file is present and I would like to check whether that could be the problem.

jungleowl commented 7 years ago

Hi, Ondys, For the compression failure problem, You can find the .mtl file in the following link. http://pan.baidu.com/s/1eR2WxFW

To not interfere with ongoing topic, I'd like make a new question herebelow. During the implementation of the draco solution, I noticed when we parse the .mtl file with mtlloader of three.js to get the filename of the texture, and after the preload() to download the texture file, we will have to assign the material with the name of the texture which is written in the corresponding .mtl file. Thus the texture can be correctly loaded. a very simple example is like below: newmtl FILENAME Ka 1 1 1 1 Kd 1 1 1 1 Ks 0 0 0 1 map_Kd FILENAME.jpg, But some .mtl files compose like this: newmtl XX //(this is a certain name in order, such as "material_MM" (followed as serial numbers) // in the related .obj file, it uses "newmtl XX" to make statement. Ka 1 1 1 1 Kd 1 1 1 1 Ks 0 0 0 1 map_Kd FILENAME.jpg So in this case, when we load texture by the previous way, it will fail until we change the XX to the same FILENAME as assigned in "map_Kd" statament. Since draco does not perserve the usemtl information of the original .obj file, we start to think if it is really necessary to use mtlloader and instead we can directly assign the texture by name to the decompressed draco geometry. To clarify, I come with this just want to know if my understanding is correct or not. If you will have different idea or explanation on this, I will be your best listener. :) PS: you can find the metioned example through the link as well, this one I haven't changed its mtl content.

ondys commented 7 years ago

Since draco does not perserve the usemtl information of the original .obj file, we start to think if it is really necessary to use mtlloader and instead we can directly assign the texture by name to the decompressed draco geometry.

It is certainly possible (and in fact easier) to load the texture and assign it to Draco model without loading the .mtl file. This is not really related to Draco, but more to THREE.js where you can simply add the loaded texture to your Material.. for example like this:


var loader = new THREE.TextureLoader();
loader.load('yourTexture.jpg', function (texture) {  
  var material = new THREE.MeshStandardMaterial({map: texture});
  var mesh = new THREE.Mesh(dracoGeometry, material);
  // ...
}

The only drawback is that the material will not contain any other non-texture properties that may have been stored in the .mtl file.
jungleowl commented 7 years ago

Hi, Ondys, yes, it works. In our scenario, the non-texture properties are all omitted. Thanks a lot! Kindly ask if there is anything new about the draco compression issue on your side? We are also trying to find a linux machine to do the same to see if it works correctly for the problematic models.

ondys commented 7 years ago

@jungleowl I still wasn't able to reproduce the issue. So far I have tried it on a linux machine only. I'll try it again on a Windows machine later today

ondys commented 7 years ago

@jungleowl I was still unable to reproduce the issue even on a Windows machine. Since you mentioned that it happens to all models in a given batch, maybe it's a problem with a path to the batch? If you try to add a model that you know that works to the problematic batch, does it fail there as well?

jungleowl commented 7 years ago

@ondys Sorry for the late reply. The compression procedure worked with new draco version after we compiled the source code of new version. Moreover, we discovered the draco couldn't compress the model with some unusal information such as extra "/" in the face statement like "1/2/", this requires some manual operation to remove the unuseful information. So we are trying to add some flexbility on the source code so that we can handle such cases. Unfortunately, during the process, we found that it was very difficult to transit the c++ to js in windows platform with current resource and we still can't make it work subsequently. Kindly ask is there any chance to have the workflow for windows platforms in order to help those who work only on windows platform? If so, it would be great help. Thanks a lot for your followup.

ondys commented 7 years ago

@jungleowl What were the issues that you encountered when generating .js on Windows? Our instructions should be mostly platform independent.

jungleowl commented 7 years ago

@ondys The issues gone while we deployed the virtual Linux machine and moved all compiling works on it. Thanks a lot for your concerns, and we hope we can keep reporting the issues occurred later on if any.

jungleowl commented 7 years ago

@ondys I come again to have your support. We are currently using draco compressed file on one of our project which loads the models with three.js. In the case, the number of models are enormous. The issue is that more models we load, more memory are consumed. We tried to release memory with some efficiency but failed to manage the JSArrayBufferData which keep growing until the google chrome crashed. Kindly ask if there is possibility that draco itself eats the memory? If no, kindly ask if you can share some solution on this kind of problem, it will be great helpful not only for us but also for everyone who are interested in applying draco, thanks a lot!

jungleowl commented 7 years ago

A little more comments I think I should add. When we were loading less models during the operation, in theory, the JSArrayBufferData should release memory since data get less but it eats more.

ondys commented 7 years ago

@jungleowl If you do that without Draco, do you still have the same memory problems? As far as I know, Draco doesn't leak memory in our THREE.js loader (assuming you are using the one we provided, if you use your custom one, make sure you call destroy(...) on every object that you created in Draco module).

jungleowl commented 7 years ago

@ondys , yes, you are right, draco just manages to control the memory very well, the leak was not caused due to draco. We have found our bug and cleared it already. Thank you for your response.

jungleowl commented 7 years ago

@ondys , Hi, buddy, again I come for support. A quite big model has a size up to 170M with 8M JPG texture. for PC and andriod, this is not a problem at all to load the compressed model. But for IOS, crash often happens during loading of it even we resize the texture to about 200K. Due to lack of debugging means on IOS mobile phone, we can't find exact problem to cause this. So kindly ask if you know there is any method to get stable loading of this kind of big models in IOS? The only solution we can figure out is to slice the original models to small pieces, but it costs time and computation.

ondys commented 7 years ago

@jungleowl Does it work when the texture is excluded completely? I'm just trying to figure out whether this is a problem with Draco or not. Unfortunately I'm not that familiar with iOS development so I cannot give any specific examples in that regard.

jungleowl commented 7 years ago

We haven't try load the model without texture since we already encounter the same problem when resizing the texture. We went to the other way to slice the models to pieces, in the case, the total size of the models increased but with less chances of crashing when loading smaller pieces. But there is a very interesting issue happened when we did this. The memory consumption(checked with chrome) was around 170M which equals to the original size of OBJ model. The memory consumption for sliced pieces were only taking around 48M. However, the size of sliced pieces is greater than the original one due to we have to make some extra vertices and faces to keep the model complete. This is quite strange to me, but it is good for my project. :)

ondys commented 7 years ago

@jungleowl One thing that may cause this weird memory consumption is that Draco decoder is going to require much more internal memory to decode a single large mesh vs multiple small meshes. On the other hand, when the decoder is destroyed the memory consumption should be about the same (or larger for the sliced meshes).

FarhadG commented 6 years ago

I'm running into the very same issue (https://github.com/google/draco/issues/364). It would be much appreciated if we have some working example of loading a .drc file with materials using the MTLLoader.