hjoykim / THREE

c# port of Three.js
MIT License
131 stars 24 forks source link

Load Objects and matrix #37

Closed merco closed 1 month ago

merco commented 1 month ago

Hi I'm working in a 3D model like this, where I have OBJ mesh and a model.dat file with worldmatrix.

1M.OBJ.zip

I'm going to read entities in this way

immagine

but some translation / rotation is wrong

How can I get right positioning of each instance ?

X3dModel.zip

merco commented 1 month ago

the only way is this... can be is it correct?

immagine

hjoykim commented 1 month ago

I would like to know why the x3d file was separated into obj file.

if you want that an object's transform, rotation to be inherited from parent object, please refer to below comments image

merco commented 1 month ago

X3D are too big. My new idea is to store entities in single obj/mtl files , and another file to list all bom tree dependencies.

I've fixed my code

merco commented 1 month ago

It could be faster than obj loader if I serialize this

immagine

and then reload it for creating the first new mesh ?

... but I can't get "List of material" serialized... why?

immagine

and in deserialization I didn't have "attributes"....

immagine

hjoykim commented 1 month ago

OK, I see

Can I get your entire source including serialization and deserialization

merco commented 1 month ago

it's not simple because is a part of another project (that export from proprietary legacy 3D file to obj).

This is the way I serialize (I'm sorry I have not cleaned my code yet from MTLLoader....)

_omissis_

[Serializable]
public class ThreeEnt
{
    public THREE.Geometry G { get; set; } = new THREE.Geometry();
    public List<Material> M = new List<Material>();
}

_omissis_

 private void Make3JsObjects (string outputpath)
 {
     var objFiles = System.IO.Directory.GetFiles(outputpath, "*.obj");
     foreach (string thisfileobj in  objFiles)
     {
         string thisFilemat = System.IO.Path.ChangeExtension(thisfileobj, ".mtl");
         string thisFile3js = System.IO.Path.ChangeExtension(thisfileobj, ".3js");
         var M = new THREE.MTLLoader();
         var mc=M.Parse(thisFilemat);
         var L = new THREE.OBJLoader ();
         L.SetMaterials(mc);
         var O1 = L.Load(thisfileobj);
         THREE.Mesh meshOriginale = (THREE.Mesh)  O1.Children[0];
         meshOriginale.Geometry.ComputeBoundingBox();
         ThreeEnt outEnt = new ThreeEnt();
         outEnt.M.AddRange(meshOriginale.Materials);
         outEnt.G = meshOriginale.Geometry;
         var so = JsonConvert.SerializeObject(outEnt);
         if (System.IO.File.Exists(thisFile3js)) System.IO.File.Delete(thisFile3js);
         System.IO.File.WriteAllText(thisFile3js,so);

     }
 }

and this is how I deserialize it


 If System.IO.File.Exists(File3JS) Then
     Dim meshjs = Newtonsoft.Json.JsonConvert.DeserializeObject(Of ThreeEnt)(System.IO.File.ReadAllText(File3JS)) JsonSerializer.Deserialize(Of ThreeEnt)(System.IO.File.ReadAllText(File3JS))
    O1 = New Group
    meshOriginale = New THREE.Mesh(meshjs.G, meshjs.M)

    O1.Add(meshOriginale)
merco commented 1 month ago

@hjoykim you had time to check how to serialize the data correctly?

hjoykim commented 1 month ago

hello Since it's been a very busy season these days, I haven't been able to take a look at your serialization code.

and execution result of your code, It seems that JsonConvert in the Newtonsoft.json package fails to serialize some classes to json.

The material class cannot be serialized at all.

I think that it need more time to find out the problem.

If you're in a hurry, you should probably write your own serialization class and use it.

Is there anything you have done so far to resolve this issue? Let us know if you see any notable results

merco commented 1 month ago

thanks. Just wanted to know the progress.

Do you think it's worth thinking about the serialization/deserialization method instead of using obj files to generate the scene, in terms of loading speed?

hjoykim commented 1 month ago

I don't know what scene you want to create, Looking at your sources so far It seems that you are constructing the scene by converting .obj and .mtl into .3js json format.

In my opinion, if you convert obj and mtl files to json, all the characteristics of the object will not be converted to json. There will likely be some loss, and it will also be a problem with loading speed. As you will know by trying it, class to json or json to class takes a lot of time.

If you want to manage objects with one file, it would be better to use another 3d format such as x3d, stp, or gltf etc.

If I were to do something similar to yours, I would probably keep the obj and mtl files.

I hope you make a wise choice.

merco commented 1 month ago

@hjoykim I did a quick test using BufferGeometryLoader instead of OBJLoader , saving a reduced json. OBJloader is faster.

merco commented 1 month ago

another try and save the attributes to a binary file and then read it back. Now it's really fast. from 15 seconds to 1! mmh I have to manage materials and groups ...

this is how I save: immagine

and this is how I load

immagine

merco commented 1 month ago

I've exported material and Geometry groups (DrawRange) in binary files .

immagine

2000 Meshes loaded in 2 seconds!

hjoykim commented 1 month ago

You've defined your own file format for saving and loading that's good idea. saving and loading objects to binary file is one of the best