0029303: Data Exchange - add RWObj_CafWriter tool for wavefront OBJ file
[occt.git] / src / RWObj / RWObj_ObjMaterialMap.cxx
1 // Copyright (c) 2015-2021 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <RWObj_ObjMaterialMap.hxx>
15
16 #include <Message.hxx>
17 #include <OSD_OpenFile.hxx>
18
19 IMPLEMENT_STANDARD_RTTIEXT(RWObj_ObjMaterialMap, RWMesh_MaterialMap)
20
21 // ================================================================
22 // Function : RWObj_ObjMaterialMap
23 // Purpose  :
24 // ================================================================
25 RWObj_ObjMaterialMap::RWObj_ObjMaterialMap (const TCollection_AsciiString& theFile)
26 : RWMesh_MaterialMap (theFile),
27   myFile (NULL)
28 {
29   //
30 }
31
32 // ================================================================
33 // Function : ~RWObj_ObjMaterialMap
34 // Purpose  :
35 // ================================================================
36 RWObj_ObjMaterialMap::~RWObj_ObjMaterialMap()
37 {
38   if (myFile != NULL)
39   {
40     if (::fclose (myFile) != 0)
41     {
42       myIsFailed = true;
43     }
44   }
45
46   if (myIsFailed)
47   {
48     Message::SendFail (TCollection_AsciiString ("File cannot be written\n") + myFileName);
49   }
50 }
51
52 // ================================================================
53 // Function : AddMaterial
54 // Purpose  :
55 // ================================================================
56 TCollection_AsciiString RWObj_ObjMaterialMap::AddMaterial (const XCAFPrs_Style& theStyle)
57 {
58   if (myFile == NULL
59   && !myIsFailed)
60   {
61     myFile = OSD_OpenFile (myFileName.ToCString(), "wb");
62     myIsFailed = myFile == NULL;
63     if (myFile != NULL)
64     {
65       Fprintf (myFile, "# Exported by Open CASCADE Technology [dev.opencascade.org]\n");
66     }
67   }
68   if (myFile == NULL)
69   {
70     return TCollection_AsciiString();
71   }
72
73   return RWMesh_MaterialMap::AddMaterial (theStyle);
74 }
75
76 // ================================================================
77 // Function : DefineMaterial
78 // Purpose  :
79 // ================================================================
80 void RWObj_ObjMaterialMap::DefineMaterial (const XCAFPrs_Style& theStyle,
81                                            const TCollection_AsciiString& theKey,
82                                            const TCollection_AsciiString& theName)
83 {
84   (void )theName;
85   Fprintf (myFile, "newmtl %s\n", theKey.ToCString());
86
87   bool hasMaterial = false;
88   const XCAFDoc_VisMaterialCommon aDefMat = !myDefaultStyle.Material().IsNull()
89                                            ? myDefaultStyle.Material()->ConvertToCommonMaterial()
90                                            : XCAFDoc_VisMaterialCommon();
91   Quantity_Color anAmbQ (aDefMat.AmbientColor), aDiffQ (aDefMat.DiffuseColor), aSpecQ (aDefMat.SpecularColor);
92   Standard_ShortReal aTransp = 0.0f;
93   Standard_ShortReal aSpecular = aDefMat.Shininess * 1000.0f;
94   if (!theStyle.Material().IsNull()
95    && !theStyle.Material()->IsEmpty())
96   {
97     hasMaterial = true;
98     const XCAFDoc_VisMaterialCommon aComMat = theStyle.Material()->ConvertToCommonMaterial();
99     anAmbQ  = aComMat.AmbientColor;
100     aDiffQ  = aComMat.DiffuseColor;
101     aSpecQ  = aComMat.SpecularColor;
102     aTransp = aComMat.Transparency;
103     aSpecular = aComMat.Shininess * 1000.0f;
104   }
105   if (theStyle.IsSetColorSurf())
106   {
107     hasMaterial = true;
108     aDiffQ = theStyle.GetColorSurf();
109     anAmbQ = Quantity_Color ((Graphic3d_Vec3 )theStyle.GetColorSurf() * 0.25f);
110     if (theStyle.GetColorSurfRGBA().Alpha() < 1.0f)
111     {
112       aTransp = 1.0f - theStyle.GetColorSurfRGBA().Alpha();
113     }
114   }
115
116   if (hasMaterial)
117   {
118     Graphic3d_Vec3d anAmb, aDiff, aSpec;
119     anAmbQ.Values (anAmb.r(), anAmb.g(), anAmb.b(), Quantity_TOC_sRGB);
120     aDiffQ.Values (aDiff.r(), aDiff.g(), aDiff.b(), Quantity_TOC_sRGB);
121     aSpecQ.Values (aSpec.r(), aSpec.g(), aSpec.b(), Quantity_TOC_sRGB);
122
123     Fprintf (myFile, "Ka %f %f %f\n", anAmb.r(), anAmb.g(), anAmb.b());
124     Fprintf (myFile, "Kd %f %f %f\n", aDiff.r(), aDiff.g(), aDiff.b());
125     Fprintf (myFile, "Ks %f %f %f\n", aSpec.r(), aSpec.g(), aSpec.b());
126     Fprintf (myFile, "Ns %f\n", aSpecular);
127     if (aTransp >= 0.0001f)
128     {
129       Fprintf (myFile, "Tr %f\n", aTransp);
130     }
131   }
132
133   if (const Handle(Image_Texture)& aBaseTexture = theStyle.BaseColorTexture())
134   {
135     TCollection_AsciiString aTexture;
136     if (!myImageMap.Find (aBaseTexture, aTexture)
137      && !myImageFailMap.Contains (aBaseTexture))
138     {
139       if (CopyTexture (aTexture, aBaseTexture, TCollection_AsciiString (myImageMap.Extent() + 1)))
140       {
141         myImageMap.Bind (aBaseTexture, aTexture);
142       }
143       else
144       {
145         myImageFailMap.Add (aBaseTexture);
146       }
147     }
148     if (!aTexture.IsEmpty())
149     {
150       Fprintf (myFile, "map_Kd %s\n", aTexture.ToCString());
151     }
152   }
153 }