diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CSTLMeshFileLoader.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CSTLMeshFileLoader.cpp | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CSTLMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CSTLMeshFileLoader.cpp new file mode 100644 index 0000000..bf9ffb3 --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CSTLMeshFileLoader.cpp | |||
@@ -0,0 +1,253 @@ | |||
1 | // Copyright (C) 2007-2012 Christian Stehno | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "IrrCompileConfig.h" | ||
6 | |||
7 | #ifdef _IRR_COMPILE_WITH_STL_LOADER_ | ||
8 | |||
9 | #include "CSTLMeshFileLoader.h" | ||
10 | #include "SMesh.h" | ||
11 | #include "SMeshBuffer.h" | ||
12 | #include "SAnimatedMesh.h" | ||
13 | #include "IReadFile.h" | ||
14 | #include "fast_atof.h" | ||
15 | #include "coreutil.h" | ||
16 | #include "os.h" | ||
17 | |||
18 | namespace irr | ||
19 | { | ||
20 | namespace scene | ||
21 | { | ||
22 | |||
23 | |||
24 | //! returns true if the file maybe is able to be loaded by this class | ||
25 | //! based on the file extension (e.g. ".bsp") | ||
26 | bool CSTLMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | ||
27 | { | ||
28 | return core::hasFileExtension ( filename, "stl" ); | ||
29 | } | ||
30 | |||
31 | |||
32 | |||
33 | //! creates/loads an animated mesh from the file. | ||
34 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | ||
35 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | ||
36 | //! See IReferenceCounted::drop() for more information. | ||
37 | IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file) | ||
38 | { | ||
39 | const long filesize = file->getSize(); | ||
40 | if (filesize < 6) // we need a header | ||
41 | return 0; | ||
42 | |||
43 | SMesh* mesh = new SMesh(); | ||
44 | SMeshBuffer* meshBuffer = new SMeshBuffer(); | ||
45 | mesh->addMeshBuffer(meshBuffer); | ||
46 | meshBuffer->drop(); | ||
47 | |||
48 | core::vector3df vertex[3]; | ||
49 | core::vector3df normal; | ||
50 | |||
51 | bool binary = false; | ||
52 | core::stringc token; | ||
53 | if (getNextToken(file, token) != "solid") | ||
54 | binary = true; | ||
55 | // read/skip header | ||
56 | u32 binFaceCount = 0; | ||
57 | if (binary) | ||
58 | { | ||
59 | file->seek(80); | ||
60 | file->read(&binFaceCount, 4); | ||
61 | #ifdef __BIG_ENDIAN__ | ||
62 | binFaceCount = os::Byteswap::byteswap(binFaceCount); | ||
63 | #endif | ||
64 | } | ||
65 | else | ||
66 | goNextLine(file); | ||
67 | |||
68 | u16 attrib=0; | ||
69 | token.reserve(32); | ||
70 | |||
71 | while (file->getPos() < filesize) | ||
72 | { | ||
73 | if (!binary) | ||
74 | { | ||
75 | if (getNextToken(file, token) != "facet") | ||
76 | { | ||
77 | if (token=="endsolid") | ||
78 | break; | ||
79 | mesh->drop(); | ||
80 | return 0; | ||
81 | } | ||
82 | if (getNextToken(file, token) != "normal") | ||
83 | { | ||
84 | mesh->drop(); | ||
85 | return 0; | ||
86 | } | ||
87 | } | ||
88 | getNextVector(file, normal, binary); | ||
89 | if (!binary) | ||
90 | { | ||
91 | if (getNextToken(file, token) != "outer") | ||
92 | { | ||
93 | mesh->drop(); | ||
94 | return 0; | ||
95 | } | ||
96 | if (getNextToken(file, token) != "loop") | ||
97 | { | ||
98 | mesh->drop(); | ||
99 | return 0; | ||
100 | } | ||
101 | } | ||
102 | for (u32 i=0; i<3; ++i) | ||
103 | { | ||
104 | if (!binary) | ||
105 | { | ||
106 | if (getNextToken(file, token) != "vertex") | ||
107 | { | ||
108 | mesh->drop(); | ||
109 | return 0; | ||
110 | } | ||
111 | } | ||
112 | getNextVector(file, vertex[i], binary); | ||
113 | } | ||
114 | if (!binary) | ||
115 | { | ||
116 | if (getNextToken(file, token) != "endloop") | ||
117 | { | ||
118 | mesh->drop(); | ||
119 | return 0; | ||
120 | } | ||
121 | if (getNextToken(file, token) != "endfacet") | ||
122 | { | ||
123 | mesh->drop(); | ||
124 | return 0; | ||
125 | } | ||
126 | } | ||
127 | else | ||
128 | { | ||
129 | file->read(&attrib, 2); | ||
130 | #ifdef __BIG_ENDIAN__ | ||
131 | attrib = os::Byteswap::byteswap(attrib); | ||
132 | #endif | ||
133 | } | ||
134 | |||
135 | SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1)); | ||
136 | u32 vCount = mb->getVertexCount(); | ||
137 | video::SColor color(0xffffffff); | ||
138 | if (attrib & 0x8000) | ||
139 | color = video::A1R5G5B5toA8R8G8B8(attrib); | ||
140 | if (normal==core::vector3df()) | ||
141 | normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal; | ||
142 | mb->Vertices.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df())); | ||
143 | mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df())); | ||
144 | mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df())); | ||
145 | mb->Indices.push_back(vCount); | ||
146 | mb->Indices.push_back(vCount+1); | ||
147 | mb->Indices.push_back(vCount+2); | ||
148 | } // end while (file->getPos() < filesize) | ||
149 | mesh->getMeshBuffer(0)->recalculateBoundingBox(); | ||
150 | |||
151 | // Create the Animated mesh if there's anything in the mesh | ||
152 | SAnimatedMesh* pAM = 0; | ||
153 | if ( 0 != mesh->getMeshBufferCount() ) | ||
154 | { | ||
155 | mesh->recalculateBoundingBox(); | ||
156 | pAM = new SAnimatedMesh(); | ||
157 | pAM->Type = EAMT_OBJ; | ||
158 | pAM->addMesh(mesh); | ||
159 | pAM->recalculateBoundingBox(); | ||
160 | } | ||
161 | |||
162 | mesh->drop(); | ||
163 | |||
164 | return pAM; | ||
165 | } | ||
166 | |||
167 | |||
168 | //! Read 3d vector of floats | ||
169 | void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const | ||
170 | { | ||
171 | if (binary) | ||
172 | { | ||
173 | file->read(&vec.X, 4); | ||
174 | file->read(&vec.Y, 4); | ||
175 | file->read(&vec.Z, 4); | ||
176 | #ifdef __BIG_ENDIAN__ | ||
177 | vec.X = os::Byteswap::byteswap(vec.X); | ||
178 | vec.Y = os::Byteswap::byteswap(vec.Y); | ||
179 | vec.Z = os::Byteswap::byteswap(vec.Z); | ||
180 | #endif | ||
181 | } | ||
182 | else | ||
183 | { | ||
184 | goNextWord(file); | ||
185 | core::stringc tmp; | ||
186 | |||
187 | getNextToken(file, tmp); | ||
188 | core::fast_atof_move(tmp.c_str(), vec.X); | ||
189 | getNextToken(file, tmp); | ||
190 | core::fast_atof_move(tmp.c_str(), vec.Y); | ||
191 | getNextToken(file, tmp); | ||
192 | core::fast_atof_move(tmp.c_str(), vec.Z); | ||
193 | } | ||
194 | vec.X=-vec.X; | ||
195 | } | ||
196 | |||
197 | |||
198 | //! Read next word | ||
199 | const core::stringc& CSTLMeshFileLoader::getNextToken(io::IReadFile* file, core::stringc& token) const | ||
200 | { | ||
201 | goNextWord(file); | ||
202 | u8 c; | ||
203 | token = ""; | ||
204 | while(file->getPos() != file->getSize()) | ||
205 | { | ||
206 | file->read(&c, 1); | ||
207 | // found it, so leave | ||
208 | if (core::isspace(c)) | ||
209 | break; | ||
210 | token.append(c); | ||
211 | } | ||
212 | return token; | ||
213 | } | ||
214 | |||
215 | |||
216 | //! skip to next word | ||
217 | void CSTLMeshFileLoader::goNextWord(io::IReadFile* file) const | ||
218 | { | ||
219 | u8 c; | ||
220 | while(file->getPos() != file->getSize()) | ||
221 | { | ||
222 | file->read(&c, 1); | ||
223 | // found it, so leave | ||
224 | if (!core::isspace(c)) | ||
225 | { | ||
226 | file->seek(-1, true); | ||
227 | break; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | |||
233 | //! Read until line break is reached and stop at the next non-space character | ||
234 | void CSTLMeshFileLoader::goNextLine(io::IReadFile* file) const | ||
235 | { | ||
236 | u8 c; | ||
237 | // look for newline characters | ||
238 | while(file->getPos() != file->getSize()) | ||
239 | { | ||
240 | file->read(&c, 1); | ||
241 | // found it, so leave | ||
242 | if (c=='\n' || c=='\r') | ||
243 | break; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | |||
248 | } // end namespace scene | ||
249 | } // end namespace irr | ||
250 | |||
251 | |||
252 | #endif // _IRR_COMPILE_WITH_STL_LOADER_ | ||
253 | |||