Menu

Export many TGLCylinder and TGLFreeForm to obj

Help
Roman
2016-07-18
2016-07-25
  • Roman

    Roman - 2016-07-18

    Hello!
    Help me please!

    I have many TGLCylinder and TGLFreeForm.
    I need export all scene to .obj or .3ds or *.stl.

    How can i do this?

    Ps
    Maybe need combine all objects in one TGLFreeForm..

    Sorry my english
    Tnank you in advance.

     
  • Roman

    Roman - 2016-07-19
    uses ..., GLFile3ds, GLVectorLists, GLFileSTL;
    
    ...
    
    procedure AddExportFile(FF:TGLFreeForm);
    var i:integer;
    dataFace:TSTLFace;
    list:TaffineVectorlist;
    begin
      //ExportList = TStringList
      FormatSettings.DecimalSeparator:='.';
      list:=FF.MeshObjects.ExtractTriangles;
      if list.Count>0 then
      begin
        try
          i:=0;
          ExportList.Add('solid TestObj');
          with dataFace do
          while i<list.Count do
          begin
            normal:=CalcPlaneNormal(list[i], list[i+1], list[i+2]);
            v1:=VectorTransform(list[i],TGLFREeform(FF).AbsoluteMatrix);
            v2:=VectorTransform(list[i+1],TGLFREeform(FF).AbsoluteMatrix);
            v3:=VectorTransform(list[i+2],TGLFREeform(FF).AbsoluteMatrix);
            ExportList.Add(format('facet normal %.6f %.6f %.6f',[normal.X,normal.Y,normal.Z]));
            ExportList.Add('outer loop');
            ExportList.Add(format('vertex %.6f %.6f %.6f',[v1.X,v1.Y,v1.Z]));
            ExportList.Add(format('vertex %.6f %.6f %.6f',[v2.X,v2.Y,v2.Z]));
            ExportList.Add(format('vertex %.6f %.6f %.6f',[v3.X,v3.Y,v3.Z]));
            ExportList.Add('endloop');
            ExportList.Add('endfacet');
            Inc(i, 3);
          end;
          ExportList.Add('endsolid TestObj');
        finally
          list.Free;
        end;
      end;
      FormatSettings.DecimalSeparator:=',';
    end;
    

    Work for FreeForm.
    How can i do this for TGLCylinder?

     

    Last edit: Roman 2016-07-19
  • Jerome.D (BeanzMaster)

    Hi you must use FreeForm instead TGLCylinder. You can easly convert it. See MeshUtils.pas or something like that. See also this discussion https://sourceforge.net/p/glscene/discussion/93606/thread/889219fc/

     
  • Roman

    Roman - 2016-07-25

    Jerome Delauney, thank you!
    I will do as you advise.

     
  • Roman

    Roman - 2016-07-25

    Combine all GLFreeForm and export to one .Obj:

    Bad code is below:

    unit GLFileOBJ; //File GLFileOBJ.pas
        ...
    interface
    
    uses
        ...
      var My_VCount,My_FCount:integer; //<- Bad global variable
        ...
    
    procedure TGLOBJVectorFile.SaveToStream(aStream: TStream);
    var OldDecimalSeparator:char;
    tMy_VCount:integer;
    
      procedure Write(const s: AnsiString);
      begin
        if s <> '' then
          aStream.Write(s[1], Length(s));
      end;
    
      procedure WriteLn(const s: string);
      begin
        Write(AnsiString(s));
        Write(#13#10);
      end;
    
      procedure WriteHeader;
      begin
        WriteLn('# My OBJ-File exported by GLScene');
        WriteLn('');
      end;
    
      procedure WriteVertices;
      var
        s: string;
        j, i, n: integer;
        v:Tvector3f;
      begin
        n := 0;
        for j := 0 to Owner.MeshObjects.Count - 1 do
        begin
          //Writeln(Format('# Mesh %d', [j + 1]));
          with Owner.MeshObjects[j].Vertices do
          begin
            for i := 0 to Count - 1 do
            begin
              //Use absolute matrix
              v:=VectorTransform(List^[i],TGLFREeform(Owner).AbsoluteMatrix);
              s := Format('v %g %g %g', [v.V[0], v.V[1], v.V[2]]);
              Writeln(s);
              inc(tMy_VCount);
            end;
            Inc(n, Count);
          end;
        end;
        WriteLn(Format('# %d Vertices', [n]));
        WriteLn('');
      end;
    
      procedure WriteNormals;
      var
        s: string;
        j, i, n: integer;
      begin
        n := 0;
        for j := 0 to Owner.MeshObjects.Count - 1 do
        begin
          with Owner.MeshObjects[j].Normals do
          begin
            for i := 0 to Count - 1 do
            begin
              s := Format('vn %g %g %g', [List^[i].V[0],
                                          List^[i].V[1],
                                          List^[i].V[2]]);
              Writeln(s);
            end;
            Inc(n, Count);
          end;
        end;
        WriteLn(Format('# %d Normals', [n]));
        WriteLn('');
      end;
    
      procedure WriteTexCoords;
      var
        s: string;
        j, i, n: integer;
      begin
        n := 0;
        for j := 0 to Owner.MeshObjects.Count - 1 do
        begin
          with Owner.MeshObjects[j].TexCoords do
          begin
            for i := 0 to Count - 1 do
            begin
              s := Format('vt %g %g', [List^[i].V[0], List^[i].V[1]]);
              Writeln(s);
            end;
            Inc(n, Count);
          end;
        end;
        WriteLn(Format('# %d Texture-Coordinates', [n]));
        WriteLn('');
      end;
    
      procedure WriteOBJFaceGroup(aFaceGroup: TOBJFGVertexNormalTexIndexList; o: Integer = 0);
      var
        vIdx, nIdx, tIdx: integer;
        i, Index, Polygon: integer;
        Line, t: string;
      begin
        with aFaceGroup do
        begin
          Index := 0;
          for Polygon := 0 to PolygonVertices.Count - 1 do
          begin
            Line := 'f ';
            for i := 1 to PolygonVertices[Polygon] do
            begin
              vIdx := VertexIndices[Index] + 1 + o;
              nIdx := NormalIndices[Index] + 1 + o;
              tIdx := TexCoordIndices[Index] + 1 + o;
              t := IntToStr(vIdx) + '/';
              if tIdx = -1 then
                t := t + '/'
              else
                t := t + IntToStr(tIdx) + '/';
              if nIdx = -1 then
                t := t + '/'
              else
                t := t + IntToStr(nIdx) + '/';
              Line := Line + Copy(t, 1, length(t) - 1) + ' ';
              inc(Index);
            end;
            Writeln(Line);
          end;
        end;
        Writeln('');
      end;
    
      procedure WriteVertexIndexList(fg: TFGVertexIndexList; o: Integer = 0);
      var
        i, n: Integer;
      begin
        case fg.Mode of
          fgmmTriangles:
            begin
              n := fg.VertexIndices.Count - 3;
              i := 0;
              while i <= n do
              begin
                Writeln(Format('f %d/%0:d %d/%1:d %d/%2:d',
                  [fg.VertexIndices[i]     + 1 + o,
                   fg.VertexIndices[i + 1] + 1 + o,
                   fg.VertexIndices[i + 2] + 1 + o]));
                Inc(i, 3);
              end;
            end;
          fgmmTriangleFan:
            begin
              Write('f ');
              n := fg.VertexIndices.Count - 1;
              i := 0;
              while i <= n do
              begin
                if i < n then
                  Write(AnsiString(Format('%d/%0:d ', [fg.VertexIndices[i] + 1 + o])))
                else
                  Writeln(Format('%d/%0:d', [fg.VertexIndices[i] + 1 + o]));
                Inc(i);
              end;
            end;
          fgmmTriangleStrip:
            begin
              n := fg.VertexIndices.Count - 3;
              i := 0;
              while i <= n do
              begin
                Writeln(Format('f %d/%0:d %d/%1:d %d/%2:d',
                  [fg.VertexIndices[i] + 1 + o,
                  fg.VertexIndices[i + 1] + 1 + o,
                    fg.VertexIndices[i + 2] + 1 + o]));
    
                Inc(i);
              end;
            end;
        end;
      end;
    
      procedure WriteFaceGroups;
      var
        j, i, k: Integer;
        fg: TGLFaceGroup;
        MoName: string;
      begin
        k := 0;
        for j := 0 to Owner.MeshObjects.Count - 1 do
        begin
          MoName := Owner.MeshObjects[j].Name;
          if MoName = '' then
            MoName := Format('Mesh%d', [j + 1+My_FCount]);
          Writeln('g ' + MoName);
          for i := 0 to Owner.MeshObjects[j].FaceGroups.Count - 1 do
          begin
            Writeln(Format('s %d', [i + 1]));
            fg := Owner.MeshObjects[j].FaceGroups[i];
            if fg is TOBJFGVertexNormalTexIndexList then
              WriteOBJFaceGroup(TOBJFGVertexNormalTexIndexList(fg), k+My_VCount)
            else if fg is TFGVertexIndexList then
              WriteVertexIndexList(TFGVertexIndexList(fg), k+My_VCount)
            else
              Assert(False); //unsupported face group
          end;
          //advance vertex index offset
          Inc(k, Owner.MeshObjects[j].Vertices.Count);
        end;
      end;
    
    begin
      Assert(Owner is TGLFreeForm, 'Can only save FreeForms.');
    
      OldDecimalSeparator := GetDecimalSeparator;
      SetDecimalSeparator('.');
    
      { Better not call anything that wants the system-locale intact
        from this block }
      try
        tMy_VCount:=0;
        WriteHeader;
        WriteVertices;
        WriteNormals;
        WriteTexCoords;
        WriteFaceGroups;
        My_VCount:=My_VCount+tMy_VCount;
        inc(My_FCount);
      finally
        SetDecimalSeparator(OldDecimalSeparator);
      end;
    end;
    
    //Use bad code:
    
    procedure TForm1.PanelClick(Sender: TObject);
    var aStream:TStream;
    OVF:TGLOBJVectorFile;
    ExportList:TStringList;
    begin
      //Model_1, Model_2 = TGLFreeForm
      My_FCount:=0;
      My_VCount:=0;
      ExportList:=TStringList.Create;
      aStream:=TMemoryStream.Create;
      OVF:=TGLOBJVectorFile.Create(Model_1);
      OVF.SaveToStream(aStream);
    
      OVF:=TGLOBJVectorFile.Create(Model_2);
      OVF.SaveToStream(aStream);
    
      aStream.Position:=0;
      ExportList.LoadFromStream(aStream);
      ExportList.SaveToFile(extractfilepath(paramstr(0))+'TestExport.OBJ');
      ExportList.Free;
    end;
    
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.