0
\$\begingroup\$

I'm trying to make a importer for my mesh file exported from 3ds max sdk using triobj I already changed YZ vectors and extracted data is just like a obj file.

In unity I have no idea how to build it , it goes wrong: unityresult

Here's my code , I included mesh data : 

using UnityEngine;

public class autodesk_3dsmax_mesh_import : MonoBehaviour
{
    public Material DefaultMaterial;
    private float scalefactor = 10.0f;

    class MeshFace
    {
        public int _vid { get; set; }
        public int _uid { get; set; }
        public int _nid { get; set; }

        public MeshFace(int vid,int uid,int nid) {
            _vid = vid; _uid = uid; _nid = nid;
        }
    }

    //// Exported data from 3DsMax using Trimesh API [YZ flip is applied]
    //// It's in *.obj data-type format
    private Vector3[] _3dsmax_vertexdata = {
      new Vector3(-5.000000f,-5.000000f,5.000000f),
      new Vector3(5.000000f,-5.000000f,5.000000f),
      new Vector3(-5.000000f,-5.000000f,-5.000000f),
      new Vector3(5.000000f,-5.000000f,-5.000000f),
      new Vector3(-5.000000f,5.000000f,5.000000f),
      new Vector3(5.000000f,5.000000f,5.000000f),
      new Vector3(-5.000000f,5.000000f,-5.000000f),
      new Vector3(5.000000f,5.000000f,-5.000000f)
    };
    private Vector3[] _3dsmax_normaldata = {
      new Vector3(0.000000f,-1.000000f,0.000000f),
      new Vector3(0.000000f,-1.000000f,0.000000f),
      new Vector3(0.000000f,-1.000000f,0.000000f),
      new Vector3(0.000000f,-1.000000f,0.000000f),
      new Vector3(0.000000f,1.000000f,0.000000f),
      new Vector3(0.000000f,1.000000f,0.000000f),
      new Vector3(0.000000f,1.000000f,0.000000f),
      new Vector3(0.000000f,1.000000f,0.000000f),
      new Vector3(0.000000f,0.000000f,1.000000f),
      new Vector3(0.000000f,0.000000f,1.000000f),
      new Vector3(0.000000f,0.000000f,1.000000f),
      new Vector3(0.000000f,0.000000f,1.000000f),
      new Vector3(1.000000f,0.000000f,0.000000f),
      new Vector3(1.000000f,0.000000f,0.000000f),
      new Vector3(1.000000f,0.000000f,0.000000f),
      new Vector3(1.000000f,0.000000f,0.000000f),
      new Vector3(0.000000f,0.000000f,-1.000000f),
      new Vector3(0.000000f,0.000000f,-1.000000f),
      new Vector3(0.000000f,0.000000f,-1.000000f),
      new Vector3(0.000000f,0.000000f,-1.000000f),
      new Vector3(-1.000000f,0.000000f,0.000000f),
      new Vector3(-1.000000f,0.000000f,0.000000f),
      new Vector3(-1.000000f,0.000000f,0.000000f),
      new Vector3(-1.000000f,0.000000f,0.000000f)
    };
    private Vector2[] _3dsmax_uvdata = {
      new Vector2(0.000000f,0.000000f),
      new Vector2(1.000000f,0.000000f),
      new Vector2(0.000000f,1.000000f),
      new Vector2(1.000000f,1.000000f),
      new Vector2(0.000000f,0.000000f),
      new Vector2(1.000000f,0.000000f),
      new Vector2(0.000000f,1.000000f),
      new Vector2(1.000000f,1.000000f),
      new Vector2(0.000000f,0.000000f),
      new Vector2(1.000000f,0.000000f),
      new Vector2(0.000000f,1.000000f),
      new Vector2(1.000000f,1.000000f)
        };
    private MeshFace[] _3dsmax_facedata = {
      new MeshFace(4,11,1),
      new MeshFace(2,9,2),
      new MeshFace(1,10,3),
      new MeshFace(1,10,3),
      new MeshFace(3,12,4),
      new MeshFace(4,11,1),
      new MeshFace(8,12,5),
      new MeshFace(7,11,6),
      new MeshFace(5,9,7),
      new MeshFace(5,9,7),
      new MeshFace(6,10,8),
      new MeshFace(8,12,5),
      new MeshFace(6,8,9),
      new MeshFace(5,7,10),
      new MeshFace(1,5,11),
      new MeshFace(1,5,11),
      new MeshFace(2,6,12),
      new MeshFace(6,8,9),
      new MeshFace(8,4,13),
      new MeshFace(6,3,14),
      new MeshFace(2,1,15),
      new MeshFace(2,1,15),
      new MeshFace(4,2,16),
      new MeshFace(8,4,13),
      new MeshFace(7,8,17),
      new MeshFace(8,7,18),
      new MeshFace(4,5,19),
      new MeshFace(4,5,19),
      new MeshFace(3,6,20),
      new MeshFace(7,8,17),
      new MeshFace(5,4,21),
      new MeshFace(7,3,22),
      new MeshFace(3,1,23),
      new MeshFace(3,1,23),
      new MeshFace(1,2,24),
      new MeshFace(5,4,21),
    };


    void Start()
    {
        uint v_count = 8; uint n_count = 24;
        uint t_count = 12; uint f_count = 36;

        //// Extracted From 3DsMax
        string obj_name = "Box_001";
        Vector3 object_pos = new Vector3(0, 0.5f, 0);
        Quaternion object_rot = new Quaternion(0,0,0,0);
        Vector3 object_scale = new Vector3(1f,1f,1f);

        GameObject simple_mesh = new GameObject(obj_name);
        simple_mesh.transform.position = object_pos;
        simple_mesh.transform.rotation = object_rot;

        simple_mesh.AddComponent<MeshFilter>();
        simple_mesh.AddComponent<MeshRenderer>();

        Mesh mesh = simple_mesh.GetComponent<MeshFilter>().mesh;
        mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

        Vector3[] vertex_data   =   new Vector3[f_count];
        Vector3[] normal_data   =   new Vector3[f_count];
        Vector2[] texcoord_data =   new Vector2[f_count];
        int[] triangles         =   new int[f_count];

        for (int i = 0; i < f_count; i++)
        {
            int vertex_id = _3dsmax_facedata[i]._vid - 1;
            int texcoord_id = _3dsmax_facedata[i]._uid - 1;
            int normal_id = _3dsmax_facedata[i]._nid - 1;

            float vtx_x = _3dsmax_vertexdata[vertex_id].x;
            float vtx_y = _3dsmax_vertexdata[vertex_id].y;
            float vtx_z = _3dsmax_vertexdata[vertex_id].z;

            vertex_data[i] = new Vector3(vtx_x / scalefactor, vtx_y / scalefactor, vtx_z / scalefactor);

            float nrm_x = _3dsmax_normaldata[normal_id].x;
            float nrm_y = _3dsmax_normaldata[normal_id].y;
            float nrm_z = _3dsmax_normaldata[normal_id].z;

            normal_data[i] = new Vector3(nrm_x , nrm_y , nrm_z );

            float uv_x = _3dsmax_uvdata[texcoord_id].x;
            float uv_y = _3dsmax_uvdata[texcoord_id].y;

            texcoord_data[i] = new Vector2(uv_x, uv_y);

            triangles[i] = vertex_id;
        }

        mesh.Clear();
        mesh.vertices =vertex_data;
        mesh.normals = normal_data;
        mesh.uv = texcoord_data;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
        simple_mesh.GetComponent<MeshRenderer>().material = DefaultMaterial;

    }
}

Data is a simple 3ds max box.

What am I doing wrong? How can I make it work?

\$\endgroup\$
  • \$\begingroup\$ It looks strange to me that your code always has as many triangle entries as it has vertices. This would be unusual for a mesh, letting you reference each vertex only once. We'd often expect to visit a vertex multiple times wherever two triangles meet along an edge or at a point without a hard shading edge or UV seam between them. \$\endgroup\$ – DMGregory Jan 25 at 13:49
  • \$\begingroup\$ Yes this seems strange to myself too but how can I make this object in unity with data I have Its just exact data stored in a obj file \$\endgroup\$ – RusselDawg Jan 25 at 18:08
0
\$\begingroup\$

Your for loop is doing too much work. Here's a version that should do what you want; I'm not convinced it's the right way to do it:

        Vector3[] vertex_data   =   new Vector3[f_count];
        Vector3[] normal_data   =   new Vector3[f_count];
        Vector2[] texcoord_data =   new Vector2[f_count];
        int[] triangles         =   new int[f_count];

        for (int i = 0; i < f_count; i++)
        {
            triangles[i] = i;
            var face = _3dsmax_facedata[i];
            vertex_data[i] = _3dsmax_vertexdata[face._vid-1];
            normal_data[i] = _3dsmax_normaldata[face._nid-1];
            texcoord_data[i] = _3dsmax_uvdata[face._uid-1];
        }

        mesh.Clear();
        mesh.vertices = vertex_data;
        mesh.normals = normal_data;
        mesh.uv = texcoord_data;
        mesh.triangles = triangles;

The key here is to understand that triangles contains an array of indexes into the entire set of (vertex, normal, uv) data. The underlying code will use that in batches of 3 to create triangles. Each index needs to have all the relevant pieces at the same index in all three datasets. This is wasteful, but I don't know Unity's mesh system well enough to offer an alternative.

\$\endgroup\$
  • \$\begingroup\$ One small efficiency you could add is to identify unique combinations of {position, texcoord, normal}, and add an entry to the vertex/uv/normal collections only once for each distinct triplet. That cuts down the first three arrays to 24 entries in the example cube, instead of 36. Then recycle those unique entries when building your triangles array, wherever two triangles share an identical trio (ie. along smooth/non-seam edges). For the box this already cuts our vertex data by a third; in meshes with more smooth seams or high-order vertices, the savings can be even more dramatic. \$\endgroup\$ – DMGregory Jan 25 at 21:42
  • \$\begingroup\$ @DMGregory I'm really interested in that , Can you provide a code example , I'm working with huge data like 4 milion tris which makes me use 4 milion for vertex , normal and uv arrays. How can I reduce them? Thanks \$\endgroup\$ – RusselDawg Jan 25 at 22:56
  • \$\begingroup\$ @RusselDawg I show a related technique in this question about omitting inner faces when building voxel chunks. Take a look at the GetVertexIndex method to see how it reduces each unique vertex to a signature, then checks to see whether it's already assigned an index to that unique signature or needs to allocate a new one. \$\endgroup\$ – DMGregory Jan 26 at 0:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.