How to extract material information when importing OBJ files

Discuss and ask questions about CAD VCL (Delphi and C++ Builder).

Moderators: SDS, support, admin

Post Reply
cmOdeon
Posts: 11
Joined: 08 Apr 2019, 11:23

How to extract material information when importing OBJ files

Post by cmOdeon » 05 Mar 2020, 13:02

Hi,

I am using CAD VCL import library to read different geometry format files for a Delphi application.
for .obj format I am using Tsg3DNavigator as follows:

Code: Select all

N3D := Tsg3DNavigator.Create(nil);
N3D.LoadFromFile(MyFileName);

for i := 0 to N3D.GLFreeForm.MeshObjects.Count-1 do
begin
   CurrMeshObject := N3D.GLFreeForm.MeshObjects[i];
   MaterialName     := CurrMeshObject.FaceGroups.Items[0].MaterialName;

   vTrianglesList      := CurrMeshObject.ExtractTriangles;
   for I := 0 to (vTrianglesList.Count div 3) - 1 do
   begin 
      v1 := Vect2FPoint(vTrianglesList[I*3]);
      v2 := Vect2FPoint(vTrianglesList[I*3+1]);
      v3 := Vect2FPoint(vTrianglesList[I*3+2]);

     // here I just create a new triangle in my application 
     // using vertices v1, v2, v3 and MaterialName
  end;
end;
My problem is that the material name is an empty string instead of the specified material in the .mtl file.
I can see using break points inside N3D.LoadFromFile(MyFileName) that .mtl file is detected and the material information is stored somewhere in GLFileOBJ unit in TGLOBJVectorFile.LoadFromStream(aStream: TStream).
So the question is how to access that information from Tsg3DNavigator class.

Regards, carlos

P.S. I used the above implementation to import 3DS format and material information was correctly attached to the triangles.

support
Posts: 3271
Joined: 30 Mar 2005, 11:36
Contact:

Re: How to extract material information when importing OBJ files

Post by support » 05 Mar 2020, 20:05

Hello Carlos,

The material name is assigned to a FaceGroup object in the procedure SetCurrentFaceGroup of TGLOBJVectorFile.LoadFromStream(aStream: TStream) and should be accessed through a Tsg3DNavigator.GLFreeForm.MeshObjects.Items[Index].FaceGroups.Items[Index].MaterialName property once the .obj file is imported.

Code: Select all

unit GLFileOBJ;
...

  procedure SetCurrentFaceGroup(aName: string; const matlName: string);
  var
    i: Integer;
  begin
    i := faceGroupNames.IndexOf(aName);
    if i >= 0 then
    begin
      faceGroup := TOBJFGVertexNormalTexIndexList(faceGroupNames.Objects[i]);

      if faceGroup.MaterialName <> matlName then
      begin
        i := faceGroupNames.IndexOf(aName);
        if i >= 0 then
        begin
          faceGroup := TOBJFGVertexNormalTexIndexList(faceGroupNames.Objects[i]);
          if faceGroup.MaterialName <> matlName then
            faceGroup := nil;
        end;
      end;
    end;

    if (faceGroup = nil) or (faceGroup.Name <> aName)
      or (faceGroup.PolygonVertices.Count > 0)
      or (faceGroup.MaterialName <> matlName) then
    begin
      faceGroup := TOBJFGVertexNormalTexIndexList.CreateOwned(Mesh.FaceGroups);
      faceGroup.FName := aName;
      faceGroup.Mode := objfgmmPolygons;
      faceGroup.MaterialName := matlName;
      faceGroupNames.AddObject(aName, faceGroup);
    end;
  end;
Please check if the material name is assigned to a FaceGroup object in the code above.

Mikhail
Technical Support E-mail: support@cadsofttools.com
Chat support on Skype: cadsofttools.support

cmOdeon
Posts: 11
Joined: 08 Apr 2019, 11:23

Re: How to extract material information when importing OBJ files

Post by cmOdeon » 06 Mar 2020, 12:25

Ok, I think my problem is solved

The thing is that not all the triangles extracted from CurMeshObject belong to FaceGroups.Items[0] and material might change for each of the entries in FaceGroups. I could get the material of each extracted triangle as follows

Code: Select all

N3D := Tsg3DNavigator.Create(nil);
N3D.LoadFromFile(MyFileName);

for i := 0 to N3D.GLFreeForm.MeshObjects.Count-1 do
begin
   CurrMeshObject := N3D.GLFreeForm.MeshObjects[i];
   MaterialName     := CurrMeshObject.FaceGroups.Items[0].MaterialName;

   layerNames     := TList<String>.create;
   vTrianglesList  := TAffineVectorList.Create;
   oldCount          := vTrianglesList.count;
   for j := 0 to CurrMeshObject.FaceGroups.Count-1 do
   begin
     FaceGroup := MeshObject.FaceGroups.Items[j];
     FaceGroup.AddToTriangles(vTrianglesList, nil, nil);
     Ntriangles := (vTrianglesList.Count - oldCount) div 3;
     for k := 1 to Ntriangles do
       materialNames.Add(FaceGroup.MaterialName);

     oldCount   := vTrianglesList.Count;
   end;

   for j := 0 to (vTrianglesList.Count div 3) - 1 do
   begin 
      v1                     := Vect2FPoint(vTrianglesList[j*3]);
      v2                     := Vect2FPoint(vTrianglesList[j*3+1]);
      v3                     := Vect2FPoint(vTrianglesList[j*3+2]);
     MaterialName := materialNames[j];

     // here I just create a new triangle in my application 
     // using vertices v1, v2, v3 and MaterialName] 
  end;
end;
Thanks for the help

Post Reply