0030691: Data Exchange - implement import of mesh data from files in glTF format
[occt.git] / src / RWGltf / RWGltf_PrimitiveArrayReader.cxx
1 // Author: Kirill Gavrilov
2 // Copyright (c) 2019 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <RWGltf_PrimitiveArrayReader.hxx>
16
17 #include <RWGltf_GltfLatePrimitiveArray.hxx>
18
19 #include <BRep_Builder.hxx>
20 #include <Message.hxx>
21 #include <Message_Messenger.hxx>
22 #include <OSD_OpenFile.hxx>
23 #include <Standard_ArrayStreamBuffer.hxx>
24 #include <TopoDS.hxx>
25 #include <TopoDS_Iterator.hxx>
26
27 IMPLEMENT_STANDARD_RTTIEXT(RWGltf_PrimitiveArrayReader, Standard_Transient)
28
29 // =======================================================================
30 // function : reportError
31 // purpose  :
32 // =======================================================================
33 void RWGltf_PrimitiveArrayReader::reportError (const TCollection_AsciiString& theText)
34 {
35   Message::DefaultMessenger()->Send (myErrorPrefix + theText, Message_Fail);
36 }
37
38 // =======================================================================
39 // function : load
40 // purpose  :
41 // =======================================================================
42 bool RWGltf_PrimitiveArrayReader::load (const Handle(RWGltf_GltfLatePrimitiveArray)& theMesh)
43 {
44   reset();
45   if (theMesh.IsNull()
46    || theMesh->PrimitiveMode() == RWGltf_GltfPrimitiveMode_UNKNOWN)
47   {
48     return false;
49   }
50
51   for (NCollection_Sequence<RWGltf_GltfPrimArrayData>::Iterator aDataIter (theMesh->Data()); aDataIter.More(); aDataIter.Next())
52   {
53     const RWGltf_GltfPrimArrayData& aData = aDataIter.Value();
54     if (!aData.StreamData.IsNull())
55     {
56       Standard_ArrayStreamBuffer aStreamBuffer ((const char* )aData.StreamData->Data(), aData.StreamData->Size());
57       std::istream aStream (&aStreamBuffer);
58       aStream.seekg ((std::streamoff )aData.StreamOffset, std::ios_base::beg);
59       if (!readBuffer (aStream, theMesh->Id(), aData.Accessor, aData.Type, theMesh->PrimitiveMode()))
60       {
61         return false;
62       }
63       continue;
64     }
65     else if (aData.StreamUri.IsEmpty())
66     {
67       reportError (TCollection_AsciiString ("Buffer '") + theMesh->Id() + "' does not define uri.");
68       return false;
69     }
70
71     if (mySharedStream.Path != aData.StreamUri)
72     {
73       mySharedStream.Stream.close();
74       mySharedStream.Path = aData.StreamUri;
75     }
76     if (!mySharedStream.Stream.is_open())
77     {
78       OSD_OpenStream (mySharedStream.Stream, aData.StreamUri.ToCString(), std::ios::in | std::ios::binary);
79       if (!mySharedStream.Stream.is_open())
80       {
81         mySharedStream.Stream.close();
82         reportError (TCollection_AsciiString ("Buffer '") + theMesh->Id() + "refers to non-existing file '" + aData.StreamUri + "'.");
83         return false;
84       }
85     }
86
87     mySharedStream.Stream.seekg ((std::streamoff )aData.StreamOffset, std::ios_base::beg);
88     if (!mySharedStream.Stream.good())
89     {
90       mySharedStream.Stream.close();
91       reportError (TCollection_AsciiString ("Buffer '") + theMesh->Id() + "refers to invalid location.");
92       return false;
93     }
94
95     if (!readBuffer (mySharedStream.Stream, theMesh->Id(), aData.Accessor, aData.Type, theMesh->PrimitiveMode()))
96     {
97       return false;
98     }
99   }
100   return true;
101 }