diff options
author | David Walter Seikel | 2016-03-28 22:28:34 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-03-28 22:28:34 +1000 |
commit | 7028cbe09c688437910a25623098762bf0fa592d (patch) | |
tree | 10b5af58277d9880380c2251f109325542c4e6eb /src/others/irrlicht-1.8.1/source/Irrlicht/COCTLoader.cpp | |
parent | Move lemon to the src/others directory. (diff) | |
download | SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.zip SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.gz SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.bz2 SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.xz |
Move Irrlicht to src/others.
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/COCTLoader.cpp')
-rw-r--r-- | src/others/irrlicht-1.8.1/source/Irrlicht/COCTLoader.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/COCTLoader.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/COCTLoader.cpp new file mode 100644 index 0000000..fd03a9b --- /dev/null +++ b/src/others/irrlicht-1.8.1/source/Irrlicht/COCTLoader.cpp | |||
@@ -0,0 +1,336 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | // | ||
5 | // originally written by Murphy McCauley, see COCTLoader.h for details. | ||
6 | // | ||
7 | // COCTLoader by Murphy McCauley (February 2005) | ||
8 | // An Irrlicht loader for OCT files | ||
9 | // | ||
10 | // See the header file for additional information including use and distribution rights. | ||
11 | |||
12 | #include "IrrCompileConfig.h" | ||
13 | #ifdef _IRR_COMPILE_WITH_OCT_LOADER_ | ||
14 | |||
15 | #include "COCTLoader.h" | ||
16 | #include "IVideoDriver.h" | ||
17 | #include "IFileSystem.h" | ||
18 | #include "os.h" | ||
19 | #include "SAnimatedMesh.h" | ||
20 | #include "SMeshBufferLightMap.h" | ||
21 | #include "irrString.h" | ||
22 | #include "ISceneManager.h" | ||
23 | |||
24 | namespace irr | ||
25 | { | ||
26 | namespace scene | ||
27 | { | ||
28 | |||
29 | //! constructor | ||
30 | COCTLoader::COCTLoader(ISceneManager* smgr, io::IFileSystem* fs) | ||
31 | : SceneManager(smgr), FileSystem(fs) | ||
32 | { | ||
33 | #ifdef _DEBUG | ||
34 | setDebugName("COCTLoader"); | ||
35 | #endif | ||
36 | if (FileSystem) | ||
37 | FileSystem->grab(); | ||
38 | } | ||
39 | |||
40 | |||
41 | //! destructor | ||
42 | COCTLoader::~COCTLoader() | ||
43 | { | ||
44 | if (FileSystem) | ||
45 | FileSystem->drop(); | ||
46 | } | ||
47 | |||
48 | |||
49 | // Doesn't really belong here, but it's jammed in for now. | ||
50 | void COCTLoader::OCTLoadLights(io::IReadFile* file, scene::ISceneNode * parent, f32 radius, f32 intensityScale, bool rewind) | ||
51 | { | ||
52 | if (rewind) | ||
53 | file->seek(0); | ||
54 | |||
55 | octHeader header; | ||
56 | file->read(&header, sizeof(octHeader)); | ||
57 | |||
58 | file->seek(sizeof(octVert)*header.numVerts, true); | ||
59 | file->seek(sizeof(octFace)*header.numFaces, true); | ||
60 | file->seek(sizeof(octTexture)*header.numTextures, true); | ||
61 | file->seek(sizeof(octLightmap)*header.numLightmaps, true); | ||
62 | |||
63 | octLight * lights = new octLight[header.numLights]; | ||
64 | file->read(lights, header.numLights * sizeof(octLight)); | ||
65 | |||
66 | //TODO: Skip past my extended data just for good form | ||
67 | |||
68 | for (u32 i = 0; i < header.numLights; i++) | ||
69 | { | ||
70 | const f32 intensity = lights[i].intensity * intensityScale; | ||
71 | |||
72 | SceneManager->addLightSceneNode(parent, core::vector3df(lights[i].pos[0], lights[i].pos[2], lights[i].pos[1]), | ||
73 | video::SColorf(lights[i].color[0] * intensity, lights[i].color[1] * intensity, lights[i].color[2] * intensity, 1.0f), | ||
74 | radius); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | |||
79 | //! creates/loads an animated mesh from the file. | ||
80 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | ||
81 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | ||
82 | //! See IReferenceCounted::drop() for more information. | ||
83 | IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file) | ||
84 | { | ||
85 | if (!file) | ||
86 | return 0; | ||
87 | |||
88 | octHeader header; | ||
89 | file->read(&header, sizeof(octHeader)); | ||
90 | |||
91 | octVert * verts = new octVert[header.numVerts]; | ||
92 | octFace * faces = new octFace[header.numFaces]; | ||
93 | octTexture * textures = new octTexture[header.numTextures]; | ||
94 | octLightmap * lightmaps = new octLightmap[header.numLightmaps]; | ||
95 | octLight * lights = new octLight[header.numLights]; | ||
96 | |||
97 | file->read(verts, sizeof(octVert) * header.numVerts); | ||
98 | file->read(faces, sizeof(octFace) * header.numFaces); | ||
99 | //TODO: Make sure id is in the legal range for Textures and Lightmaps | ||
100 | |||
101 | u32 i; | ||
102 | for (i = 0; i < header.numTextures; i++) { | ||
103 | octTexture t; | ||
104 | file->read(&t, sizeof(octTexture)); | ||
105 | textures[t.id] = t; | ||
106 | } | ||
107 | for (i = 0; i < header.numLightmaps; i++) { | ||
108 | octLightmap t; | ||
109 | file->read(&t, sizeof(octLightmap)); | ||
110 | lightmaps[t.id] = t; | ||
111 | } | ||
112 | file->read(lights, sizeof(octLight) * header.numLights); | ||
113 | |||
114 | //TODO: Now read in my extended OCT header (flexible lightmaps and vertex normals) | ||
115 | |||
116 | |||
117 | // This is the method Nikolaus Gebhardt used in the Q3 loader -- create a | ||
118 | // meshbuffer for every possible combination of lightmap and texture including | ||
119 | // a "null" texture and "null" lightmap. Ones that end up with nothing in them | ||
120 | // will be removed later. | ||
121 | |||
122 | SMesh * Mesh = new SMesh(); | ||
123 | for (i=0; i<(header.numTextures+1) * (header.numLightmaps+1); ++i) | ||
124 | { | ||
125 | scene::SMeshBufferLightMap* buffer = new scene::SMeshBufferLightMap(); | ||
126 | |||
127 | buffer->Material.MaterialType = video::EMT_LIGHTMAP; | ||
128 | buffer->Material.Lighting = false; | ||
129 | Mesh->addMeshBuffer(buffer); | ||
130 | buffer->drop(); | ||
131 | } | ||
132 | |||
133 | |||
134 | // Build the mesh buffers | ||
135 | for (i = 0; i < header.numFaces; i++) | ||
136 | { | ||
137 | if (faces[i].numVerts < 3) | ||
138 | continue; | ||
139 | |||
140 | const f32* const a = verts[faces[i].firstVert].pos; | ||
141 | const f32* const b = verts[faces[i].firstVert+1].pos; | ||
142 | const f32* const c = verts[faces[i].firstVert+2].pos; | ||
143 | const core::vector3df normal = | ||
144 | core::plane3df(core::vector3df(a[0],a[1],a[2]), core::vector3df(b[0],c[1],c[2]), core::vector3df(c[0],c[1],c[2])).Normal; | ||
145 | |||
146 | const u32 textureID = core::min_(s32(faces[i].textureID), s32(header.numTextures - 1)) + 1; | ||
147 | const u32 lightmapID = core::min_(s32(faces[i].lightmapID),s32(header.numLightmaps - 1)) + 1; | ||
148 | SMeshBufferLightMap * meshBuffer = (SMeshBufferLightMap*)Mesh->getMeshBuffer(lightmapID * (header.numTextures + 1) + textureID); | ||
149 | const u32 base = meshBuffer->Vertices.size(); | ||
150 | |||
151 | // Add this face's verts | ||
152 | u32 v; | ||
153 | for (v = 0; v < faces[i].numVerts; ++v) | ||
154 | { | ||
155 | octVert * vv = &verts[faces[i].firstVert + v]; | ||
156 | video::S3DVertex2TCoords vert; | ||
157 | vert.Pos.set(vv->pos[0], vv->pos[1], vv->pos[2]); | ||
158 | vert.Color = video::SColor(0,255,255,255); | ||
159 | vert.Normal.set(normal); | ||
160 | |||
161 | if (textureID == 0) | ||
162 | { | ||
163 | // No texture -- just a lightmap. Thus, use lightmap coords for texture 1. | ||
164 | // (the actual texture will be swapped later) | ||
165 | vert.TCoords.set(vv->lc[0], vv->lc[1]); | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | vert.TCoords.set(vv->tc[0], vv->tc[1]); | ||
170 | vert.TCoords2.set(vv->lc[0], vv->lc[1]); | ||
171 | } | ||
172 | |||
173 | meshBuffer->Vertices.push_back(vert); | ||
174 | } | ||
175 | |||
176 | // Now add the indices | ||
177 | // This weird loop turns convex polygons into triangle strips. | ||
178 | // I do it this way instead of a simple fan because it usually looks a lot better in wireframe, for example. | ||
179 | // High, Low | ||
180 | u32 h = faces[i].numVerts - 1; | ||
181 | u32 l = 0; | ||
182 | for (v = 0; v < faces[i].numVerts - 2; ++v) | ||
183 | { | ||
184 | const u32 center = (v & 1)? h - 1: l + 1; | ||
185 | |||
186 | meshBuffer->Indices.push_back(base + h); | ||
187 | meshBuffer->Indices.push_back(base + l); | ||
188 | meshBuffer->Indices.push_back(base + center); | ||
189 | |||
190 | if (v & 1) | ||
191 | --h; | ||
192 | else | ||
193 | ++l; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | // load textures | ||
198 | core::array<video::ITexture*> tex; | ||
199 | tex.reallocate(header.numTextures + 1); | ||
200 | tex.push_back(0); | ||
201 | |||
202 | const core::stringc relpath = FileSystem->getFileDir(file->getFileName())+"/"; | ||
203 | for (i = 1; i < (header.numTextures + 1); i++) | ||
204 | { | ||
205 | core::stringc path(textures[i-1].fileName); | ||
206 | path.replace('\\','/'); | ||
207 | if (FileSystem->existFile(path)) | ||
208 | tex.push_back(SceneManager->getVideoDriver()->getTexture(path)); | ||
209 | else | ||
210 | // try to read in the relative path of the OCT file | ||
211 | tex.push_back(SceneManager->getVideoDriver()->getTexture( (relpath + path) )); | ||
212 | } | ||
213 | |||
214 | // prepare lightmaps | ||
215 | core::array<video::ITexture*> lig; | ||
216 | lig.set_used(header.numLightmaps + 1); | ||
217 | lig[0] = 0; | ||
218 | |||
219 | const u32 lightmapWidth = 128; | ||
220 | const u32 lightmapHeight = 128; | ||
221 | const core::dimension2d<u32> lmapsize(lightmapWidth, lightmapHeight); | ||
222 | |||
223 | bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); | ||
224 | SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); | ||
225 | |||
226 | video::IImage* tmpImage = SceneManager->getVideoDriver()->createImage(video::ECF_R8G8B8, lmapsize); | ||
227 | for (i = 1; i < (header.numLightmaps + 1); ++i) | ||
228 | { | ||
229 | core::stringc lightmapname = file->getFileName(); | ||
230 | lightmapname += ".lightmap."; | ||
231 | lightmapname += (int)i; | ||
232 | |||
233 | const octLightmap* lm = &lightmaps[i-1]; | ||
234 | |||
235 | for (u32 x=0; x<lightmapWidth; ++x) | ||
236 | { | ||
237 | for (u32 y=0; y<lightmapHeight; ++y) | ||
238 | { | ||
239 | tmpImage->setPixel(x, y, | ||
240 | video::SColor(255, | ||
241 | lm->data[x][y][2], | ||
242 | lm->data[x][y][1], | ||
243 | lm->data[x][y][0])); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | lig[i] = SceneManager->getVideoDriver()->addTexture(lightmapname.c_str(), tmpImage); | ||
248 | } | ||
249 | tmpImage->drop(); | ||
250 | SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); | ||
251 | |||
252 | // Free stuff | ||
253 | delete [] verts; | ||
254 | delete [] faces; | ||
255 | delete [] textures; | ||
256 | delete [] lightmaps; | ||
257 | delete [] lights; | ||
258 | |||
259 | // attach materials | ||
260 | for (i = 0; i < header.numLightmaps + 1; i++) | ||
261 | { | ||
262 | for (u32 j = 0; j < header.numTextures + 1; j++) | ||
263 | { | ||
264 | u32 mb = i * (header.numTextures + 1) + j; | ||
265 | SMeshBufferLightMap * meshBuffer = (SMeshBufferLightMap*)Mesh->getMeshBuffer(mb); | ||
266 | meshBuffer->Material.setTexture(0, tex[j]); | ||
267 | meshBuffer->Material.setTexture(1, lig[i]); | ||
268 | |||
269 | if (meshBuffer->Material.getTexture(0) == 0) | ||
270 | { | ||
271 | // This material has no texture, so we'll just show the lightmap if there is one. | ||
272 | // We swapped the texture coordinates earlier. | ||
273 | meshBuffer->Material.setTexture(0, meshBuffer->Material.getTexture(1)); | ||
274 | meshBuffer->Material.setTexture(1, 0); | ||
275 | } | ||
276 | if (meshBuffer->Material.getTexture(1) == 0) | ||
277 | { | ||
278 | // If there is only one texture, it should be solid and lit. | ||
279 | // Among other things, this way you can preview OCT lights. | ||
280 | meshBuffer->Material.MaterialType = video::EMT_SOLID; | ||
281 | meshBuffer->Material.Lighting = true; | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | // delete all buffers without geometry in it. | ||
287 | i = 0; | ||
288 | while(i < Mesh->MeshBuffers.size()) | ||
289 | { | ||
290 | if (Mesh->MeshBuffers[i]->getVertexCount() == 0 || | ||
291 | Mesh->MeshBuffers[i]->getIndexCount() == 0 || | ||
292 | Mesh->MeshBuffers[i]->getMaterial().getTexture(0) == 0) | ||
293 | { | ||
294 | // Meshbuffer is empty -- drop it | ||
295 | Mesh->MeshBuffers[i]->drop(); | ||
296 | Mesh->MeshBuffers.erase(i); | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | ++i; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | |||
305 | // create bounding box | ||
306 | for (i = 0; i < Mesh->MeshBuffers.size(); ++i) | ||
307 | { | ||
308 | Mesh->MeshBuffers[i]->recalculateBoundingBox(); | ||
309 | } | ||
310 | Mesh->recalculateBoundingBox(); | ||
311 | |||
312 | |||
313 | // Set up an animated mesh to hold the mesh | ||
314 | SAnimatedMesh* AMesh = new SAnimatedMesh(); | ||
315 | AMesh->Type = EAMT_OCT; | ||
316 | AMesh->addMesh(Mesh); | ||
317 | AMesh->recalculateBoundingBox(); | ||
318 | Mesh->drop(); | ||
319 | |||
320 | return AMesh; | ||
321 | } | ||
322 | |||
323 | |||
324 | //! returns true if the file maybe is able to be loaded by this class | ||
325 | //! based on the file extension (e.g. ".bsp") | ||
326 | bool COCTLoader::isALoadableFileExtension(const io::path& filename) const | ||
327 | { | ||
328 | return core::hasFileExtension ( filename, "oct" ); | ||
329 | } | ||
330 | |||
331 | |||
332 | } // end namespace scene | ||
333 | } // end namespace irr | ||
334 | |||
335 | #endif // _IRR_COMPILE_WITH_OCT_LOADER_ | ||
336 | |||