absence_thelab
diff src/3deng/sceneloader.cpp @ 0:1cffe3409164
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 23 Oct 2014 01:46:07 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/3deng/sceneloader.cpp Thu Oct 23 01:46:07 2014 +0300 1.3 @@ -0,0 +1,923 @@ 1.4 +//#include <fstream> 1.5 +#include <windows.h> 1.6 +#include <string> 1.7 +#include <cassert> 1.8 +#include "sceneloader.h" 1.9 +#include "3dschunks.h" 1.10 +#include "typedefs.h" 1.11 + 1.12 +using std::ifstream; 1.13 +using std::string; 1.14 + 1.15 +namespace SceneLoader { 1.16 + GraphicsContext *gc; 1.17 + dword ReadCounter; 1.18 + Material *mat; 1.19 + dword MatCount; 1.20 + 1.21 + bool eof = false; 1.22 + 1.23 + string datapath = ""; 1.24 + 1.25 + string SceneFileName; 1.26 + string ObjectName; 1.27 + 1.28 + bool SaveNormalFile = false; 1.29 +} 1.30 + 1.31 +using namespace SceneLoader; 1.32 + 1.33 +struct ChunkHeader { 1.34 + ChunkID id; 1.35 + dword size; 1.36 +}; 1.37 + 1.38 +struct Percent { 1.39 + int IntPercent; 1.40 + float FloatPercent; 1.41 + 1.42 + Percent(int p = 0) {IntPercent = p; FloatPercent = (float)p / 100.0f; } 1.43 + Percent(float p) {FloatPercent = p; IntPercent = (int)(p * 100.0f); } 1.44 +}; 1.45 + 1.46 +struct TexMap { 1.47 + string filename; 1.48 + TextureType type; 1.49 + float intensity; 1.50 + float rotation; 1.51 + Vector2 offset; 1.52 + Vector2 scale; 1.53 +}; 1.54 + 1.55 +const dword HeaderSize = 6; 1.56 + 1.57 +enum {OBJ_MESH, OBJ_PTLIGHT, OBJ_SPLIGHT, OBJ_CAMERA, OBJ_CURVE}; 1.58 + 1.59 +// local function prototypes 1.60 +byte ReadByte(HANDLE file); 1.61 +word ReadWord(HANDLE file); 1.62 +dword ReadDword(HANDLE file); 1.63 +float ReadFloat(HANDLE file); 1.64 +Vector3 ReadVector(HANDLE file, bool FlipYZ = true); 1.65 +string ReadString(HANDLE file); 1.66 +Color ReadColor(HANDLE file); 1.67 +Percent ReadPercent(HANDLE file); 1.68 +ChunkHeader ReadChunkHeader(HANDLE file); 1.69 +void SkipChunk(HANDLE file, const ChunkHeader &chunk); 1.70 +void SkipBytes(HANDLE file, dword bytes); 1.71 + 1.72 +int ReadObject(HANDLE file, const ChunkHeader &ch, void **obj); 1.73 +int ReadLight(HANDLE file, const ChunkHeader &ch, Light **lt); 1.74 +Material ReadMaterial(HANDLE file, const ChunkHeader &ch); 1.75 +TexMap ReadTextureMap(HANDLE file, const ChunkHeader &ch); 1.76 + 1.77 +Material *FindMaterial(string name); 1.78 + 1.79 +bool LoadNormalsFromFile(const char *fname, Scene *scene); 1.80 +void SaveNormalsToFile(const char *fname, Scene *scene); 1.81 + 1.82 + 1.83 +void SceneLoader::SetGraphicsContext(GraphicsContext *gfx) { 1.84 + gc = gfx; 1.85 +} 1.86 + 1.87 + 1.88 +void SceneLoader::SetDataPath(const char *path) { 1.89 + datapath = path; 1.90 +} 1.91 + 1.92 +void SceneLoader::SetNormalFileSaving(bool enable) { 1.93 + SaveNormalFile = enable; 1.94 +} 1.95 + 1.96 + 1.97 + 1.98 +//////////////////////////////////////// 1.99 +// --==( function LoadScene )==-- // 1.100 +// ---------------------------------- // 1.101 +// Creates a Scene instance and loads // 1.102 +// the data from specified file // 1.103 +//////////////////////////////////////// 1.104 + 1.105 +bool SceneLoader::LoadScene(const char *fname, Scene **scene) { 1.106 + if(!gc) return false; 1.107 + 1.108 + if(!LoadMaterials(fname, &mat)) return false; 1.109 + 1.110 + //ifstream file(fname); 1.111 + //if(!file.is_open()) return false; 1.112 + HANDLE file = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); 1.113 + assert(file != NULL); 1.114 + eof = false; 1.115 + 1.116 + SceneFileName = string(fname); 1.117 + 1.118 + ChunkHeader chunk; 1.119 + Scene *scn = new Scene(gc); // new scene instance 1.120 + 1.121 + chunk = ReadChunkHeader(file); 1.122 + if(chunk.id != Chunk_3DSMain) { 1.123 + CloseHandle(file); 1.124 + return false; 1.125 + } 1.126 + 1.127 + //while(!file.eof()) { 1.128 + while(!eof) { 1.129 + 1.130 + chunk = ReadChunkHeader(file); 1.131 + 1.132 + void *objptr; 1.133 + int type; 1.134 + 1.135 + switch(chunk.id) { 1.136 + case Chunk_Main_3DEditor: 1.137 + break; // dont skip 1.138 + 1.139 + case Chunk_Edit_AmbientColor: 1.140 + scn->SetAmbientLight(ReadColor(file)); 1.141 + break; 1.142 + 1.143 + case Chunk_Edit_Fog: 1.144 + // **TODO** find out chunk structure 1.145 + break; 1.146 + 1.147 + case Chunk_Edit_Object: 1.148 + type = ReadObject(file, chunk, &objptr); 1.149 + switch(type) { 1.150 + case OBJ_MESH: 1.151 + { 1.152 + Object *object = (Object*)objptr; 1.153 + scn->AddObject(object); 1.154 + } 1.155 + break; 1.156 + 1.157 + case OBJ_CAMERA: 1.158 + { 1.159 + Camera *cam = (Camera*)objptr; 1.160 + scn->AddCamera(cam); 1.161 + } 1.162 + break; 1.163 + 1.164 + case OBJ_PTLIGHT: 1.165 + { 1.166 + PointLight *lt = (PointLight*)objptr; 1.167 + scn->AddLight(lt); 1.168 + } 1.169 + break; 1.170 + 1.171 + case OBJ_SPLIGHT: 1.172 + { 1.173 + SpotLight *lt = (SpotLight*)objptr; 1.174 + scn->AddLight(lt); 1.175 + } 1.176 + break; 1.177 + 1.178 + case OBJ_CURVE: 1.179 + { 1.180 + CatmullRomSpline *spline = (CatmullRomSpline*)objptr; 1.181 + scn->AddCurve(spline); 1.182 + } 1.183 + break; 1.184 + } 1.185 + 1.186 + break; 1.187 + 1.188 + default: 1.189 + SkipChunk(file, chunk); 1.190 + } 1.191 + } 1.192 + 1.193 + CloseHandle(file); 1.194 + 1.195 + 1.196 + // check if there is a normals file in the same dir and load them, or else calculate them 1.197 + if(!LoadNormalsFromFile((SceneFileName + string(".normals")).c_str(), scn)) { 1.198 + std::list<Object*>::iterator objiter = scn->GetObjectsList()->begin(); 1.199 + while(objiter != scn->GetObjectsList()->end()) { 1.200 + (*objiter++)->GetTriMesh()->CalculateNormals(); 1.201 + } 1.202 + if(SaveNormalFile) SaveNormalsToFile((SceneFileName + string(".normals")).c_str(), scn); 1.203 + } 1.204 + 1.205 + *scene = scn; 1.206 + return true; 1.207 +} 1.208 + 1.209 + 1.210 + 1.211 +bool SceneLoader::LoadObject(const char *fname, const char *ObjectName, Object **obj) { 1.212 + if(!gc) return false; 1.213 + 1.214 + if(!LoadMaterials(fname, &mat)) return false; 1.215 + 1.216 + //ifstream file(fname); 1.217 + //if(!file.is_open()) return false; 1.218 + HANDLE file = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); 1.219 + assert(file != NULL); 1.220 + eof = false; 1.221 + 1.222 + ChunkHeader chunk = ReadChunkHeader(file); 1.223 + if(chunk.id != Chunk_3DSMain) { 1.224 + CloseHandle(file); 1.225 + return false; 1.226 + } 1.227 + 1.228 + while(!eof) { 1.229 + 1.230 + chunk = ReadChunkHeader(file); 1.231 + 1.232 + void *objptr; 1.233 + int type; 1.234 + 1.235 + switch(chunk.id) { 1.236 + case Chunk_Main_3DEditor: 1.237 + break; // dont skip 1.238 + 1.239 + case Chunk_Edit_Object: 1.240 + type = ReadObject(file, chunk, &objptr); 1.241 + if(type == OBJ_MESH) { 1.242 + Object *object = (Object*)objptr; 1.243 + if(!strcmp(object->name.c_str(), ObjectName)) { 1.244 + object->GetTriMesh()->CalculateNormals(); 1.245 + *obj = object; 1.246 + CloseHandle(file); 1.247 + return true; 1.248 + } 1.249 + } 1.250 + break; 1.251 + 1.252 + default: 1.253 + SkipChunk(file, chunk); 1.254 + } 1.255 + } 1.256 + 1.257 + CloseHandle(file); 1.258 + return false; 1.259 +} 1.260 + 1.261 + 1.262 + 1.263 +bool FindChunk(HANDLE file, word ChunkID) { 1.264 + 1.265 + ChunkHeader chunk = ReadChunkHeader(file); 1.266 + 1.267 + while(chunk.id != ChunkID) { 1.268 + SkipChunk(file, chunk); 1.269 + chunk = ReadChunkHeader(file); 1.270 + } 1.271 + 1.272 + return chunk.id == ChunkID; 1.273 +} 1.274 + 1.275 + 1.276 + 1.277 +bool SceneLoader::LoadMaterials(const char *fname, Material **materials) { 1.278 + if(!materials) return false; 1.279 + 1.280 + //ifstream file(fname); 1.281 + //if(!file.is_open()) return false; 1.282 + HANDLE file = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); 1.283 + assert(file != NULL); 1.284 + eof = false; 1.285 + 1.286 + ChunkHeader chunk; 1.287 + 1.288 + chunk = ReadChunkHeader(file); 1.289 + if(chunk.id != Chunk_3DSMain) { 1.290 + CloseHandle(file); 1.291 + return false; 1.292 + } 1.293 + 1.294 + if(!FindChunk(file, Chunk_Main_3DEditor)) { 1.295 + CloseHandle(file); 1.296 + return false; 1.297 + } 1.298 + 1.299 + std::vector<Material> mats; 1.300 + 1.301 + while(!eof) { 1.302 + 1.303 + chunk = ReadChunkHeader(file); 1.304 + 1.305 + if(chunk.id == Chunk_Edit_Material) { 1.306 + Material mat = ReadMaterial(file, chunk); 1.307 + mats.push_back(mat); 1.308 + } else { 1.309 + SkipChunk(file, chunk); 1.310 + } 1.311 + } 1.312 + 1.313 + MatCount = (dword)mats.size(); 1.314 + 1.315 + if(*materials) delete [] *materials; 1.316 + Material *m = new Material[MatCount]; 1.317 + 1.318 + for(dword i=0; i<MatCount; i++) { 1.319 + m[i] = mats[i]; 1.320 + } 1.321 + 1.322 + *materials = m; 1.323 + 1.324 + CloseHandle(file); 1.325 + return true; 1.326 +} 1.327 + 1.328 + 1.329 +TexMap ReadTextureMap(HANDLE file, const ChunkHeader &ch) { 1.330 + assert(ch.id == Chunk_Mat_TextureMap || ch.id == Chunk_Mat_TextureMap2 || ch.id == Chunk_Mat_OpacityMap || ch.id == Chunk_Mat_BumpMap || ch.id == Chunk_Mat_ReflectionMap || ch.id == Chunk_Mat_SelfIlluminationMap); 1.331 + 1.332 + TexMap map; 1.333 + Percent p = ReadPercent(file); 1.334 + map.intensity = p.FloatPercent; 1.335 + 1.336 + switch(ch.id) { 1.337 + case Chunk_Mat_TextureMap: 1.338 + map.type = TextureMap; 1.339 + break; 1.340 + 1.341 + case Chunk_Mat_TextureMap2: 1.342 + map.type = DetailMap; 1.343 + break; 1.344 + 1.345 + case Chunk_Mat_OpacityMap: 1.346 + map.type = OpacityMap; 1.347 + break; 1.348 + 1.349 + case Chunk_Mat_BumpMap: 1.350 + map.type = BumpMap; 1.351 + break; 1.352 + 1.353 + case Chunk_Mat_ReflectionMap: 1.354 + map.type = EnvironmentMap; 1.355 + break; 1.356 + 1.357 + case Chunk_Mat_SelfIlluminationMap: 1.358 + map.type = LightMap; 1.359 + break; 1.360 + default: 1.361 + assert(0); 1.362 + } 1.363 + 1.364 + ChunkHeader chunk = ReadChunkHeader(file); 1.365 + assert(chunk.id == Chunk_Map_FileName); 1.366 + 1.367 + map.filename = ReadString(file); 1.368 + return map; 1.369 +} 1.370 + 1.371 + 1.372 + 1.373 + 1.374 + 1.375 +Material ReadMaterial(HANDLE file, const ChunkHeader &ch) { 1.376 + 1.377 + Material mat; 1.378 + 1.379 + assert(ch.id == Chunk_Edit_Material); 1.380 + 1.381 + ReadCounter = HeaderSize; 1.382 + dword ChunkSize = ch.size; 1.383 + 1.384 + while(ReadCounter < ChunkSize) { 1.385 + ChunkHeader chunk = ReadChunkHeader(file); 1.386 + 1.387 + Percent p; 1.388 + TexMap map; 1.389 + 1.390 + switch(chunk.id) { 1.391 + case Chunk_Mat_Name: 1.392 + mat.name = ReadString(file); 1.393 + break; 1.394 + 1.395 + case Chunk_Mat_AmbientColor: 1.396 + mat.Ambient = ReadColor(file); 1.397 + break; 1.398 + 1.399 + case Chunk_Mat_DiffuseColor: 1.400 + mat.Diffuse = ReadColor(file); 1.401 + break; 1.402 + 1.403 + case Chunk_Mat_SpecularColor: 1.404 + mat.Specular = ReadColor(file); 1.405 + break; 1.406 + 1.407 + case Chunk_Mat_Specular: 1.408 + p = ReadPercent(file); 1.409 + mat.Power = (float)p.IntPercent; 1.410 + if(mat.Power > 0.0f) mat.SpecularEnable = true; 1.411 + break; 1.412 + 1.413 + case Chunk_Mat_SpecularIntensity: 1.414 + p = ReadPercent(file); 1.415 + mat.Specular.r *= p.FloatPercent; 1.416 + mat.Specular.g *= p.FloatPercent; 1.417 + mat.Specular.b *= p.FloatPercent; 1.418 + break; 1.419 + 1.420 + case Chunk_Mat_Transparency: 1.421 + p = ReadPercent(file); 1.422 + mat.Alpha = 1.0f - p.FloatPercent; 1.423 + break; 1.424 + 1.425 + case Chunk_Mat_SelfIllumination: 1.426 + p = ReadPercent(file); 1.427 + mat.Emissive = Color(p.FloatPercent); 1.428 + break; 1.429 + 1.430 + case Chunk_Mat_TextureMap: 1.431 + case Chunk_Mat_TextureMap2: 1.432 + case Chunk_Mat_OpacityMap: 1.433 + case Chunk_Mat_SelfIlluminationMap: 1.434 + map = ReadTextureMap(file, chunk); 1.435 + mat.SetTexture(gc->texman->LoadTexture((datapath + map.filename).c_str()), map.type); 1.436 + break; 1.437 + 1.438 + case Chunk_Mat_ReflectionMap: 1.439 + map = ReadTextureMap(file, chunk); 1.440 + mat.SetTexture(gc->texman->LoadTexture((datapath + map.filename).c_str()), map.type); 1.441 + mat.EnvBlend = map.intensity; 1.442 + break; 1.443 + 1.444 + case Chunk_Mat_BumpMap: 1.445 + map = ReadTextureMap(file, chunk); 1.446 + mat.SetTexture(gc->texman->LoadTexture((datapath + map.filename).c_str()), map.type); 1.447 + mat.BumpIntensity = map.intensity; 1.448 + break; 1.449 + 1.450 + default: 1.451 + SkipChunk(file, chunk); 1.452 + } 1.453 + } 1.454 + 1.455 + return mat; 1.456 +} 1.457 + 1.458 + 1.459 + 1.460 + 1.461 + 1.462 +//////////////////////////////////////////////////// 1.463 +byte ReadByte(HANDLE file) { 1.464 + byte val; 1.465 + dword numread; 1.466 + ReadFile(file, &val, sizeof(byte), &numread, NULL); 1.467 + if(numread < sizeof(byte)) eof = true; 1.468 + ReadCounter++; 1.469 + return val; 1.470 +} 1.471 + 1.472 +word ReadWord(HANDLE file) { 1.473 + word val; 1.474 + dword numread; 1.475 + ReadFile(file, &val, sizeof(word), &numread, NULL); 1.476 + if(numread < sizeof(word)) eof = true; 1.477 + ReadCounter += sizeof(word); 1.478 + return val; 1.479 +} 1.480 + 1.481 +dword ReadDword(HANDLE file) { 1.482 + dword val; 1.483 + dword numread; 1.484 + ReadFile(file, &val, sizeof(dword), &numread, NULL); 1.485 + if(numread < sizeof(dword)) eof = true; 1.486 + ReadCounter += sizeof(dword); 1.487 + return val; 1.488 +} 1.489 + 1.490 +float ReadFloat(HANDLE file) { 1.491 + float val; 1.492 + dword numread; 1.493 + ReadFile(file, &val, sizeof(float), &numread, NULL); 1.494 + if(numread < sizeof(float)) eof = true; 1.495 + ReadCounter += sizeof(float); 1.496 + return val; 1.497 +} 1.498 +/* 1.499 +byte ReadByte(HANDLE file) { 1.500 + byte val; 1.501 + file.read((char*)&val, 1); 1.502 + ReadCounter++; 1.503 + return val; 1.504 +} 1.505 + 1.506 +word ReadWord(HANDLE file) { 1.507 + word val; 1.508 + file.read((char*)&val, sizeof(word)); 1.509 + ReadCounter += sizeof(word); 1.510 + return val; 1.511 +} 1.512 + 1.513 +dword ReadDword(HANDLE file) { 1.514 + dword val; 1.515 + file.read((char*)&val, sizeof(dword)); 1.516 + ReadCounter += sizeof(dword); 1.517 + return val; 1.518 +} 1.519 + 1.520 +float ReadFloat(HANDLE file) { 1.521 + float val; 1.522 + file.read((char*)&val, sizeof(float)); 1.523 + ReadCounter += sizeof(float); 1.524 + return val; 1.525 +} 1.526 +*/ 1.527 +Vector3 ReadVector(HANDLE file, bool FlipYZ) { 1.528 + Vector3 vector; 1.529 + vector.x = ReadFloat(file); 1.530 + if(!FlipYZ) vector.y = ReadFloat(file); 1.531 + vector.z = ReadFloat(file); 1.532 + if(FlipYZ) vector.y = ReadFloat(file); 1.533 + return vector; 1.534 +} 1.535 + 1.536 +string ReadString(HANDLE file) { 1.537 + string str; 1.538 + char c; 1.539 + while(c = (char)ReadByte(file)) { 1.540 + str.push_back(c); 1.541 + } 1.542 + str.push_back('\0'); 1.543 + ReadCounter++; 1.544 + 1.545 + return str; 1.546 +} 1.547 +/* 1.548 +string ReadString(HANDLE file) { 1.549 + string str; 1.550 + char c; 1.551 + while(c = file.get()) { 1.552 + str.push_back(c); 1.553 + ReadCounter++; 1.554 + } 1.555 + str.push_back('\0'); 1.556 + ReadCounter++; 1.557 + 1.558 + return str; 1.559 +} 1.560 +*/ 1.561 + 1.562 +Color ReadColor(HANDLE file) { 1.563 + ChunkHeader chunk = ReadChunkHeader(file); 1.564 + if(chunk.id < 0x0010 || chunk.id > 0x0013) return Color(-1.0f, -1.0f, -1.0f); 1.565 + 1.566 + Color color; 1.567 + 1.568 + if(chunk.id == Chunk_Color_Byte3 || chunk.id == Chunk_Color_GammaByte3) { 1.569 + byte r = ReadByte(file); 1.570 + byte g = ReadByte(file); 1.571 + byte b = ReadByte(file); 1.572 + color = Color(r, g, b); 1.573 + } else { 1.574 + color.r = ReadFloat(file); 1.575 + color.g = ReadFloat(file); 1.576 + color.b = ReadFloat(file); 1.577 + } 1.578 + 1.579 + return color; 1.580 +} 1.581 + 1.582 +Percent ReadPercent(HANDLE file) { 1.583 + ChunkHeader chunk = ReadChunkHeader(file); 1.584 + Percent p; 1.585 + if(chunk.id != Chunk_PercentInt && chunk.id != Chunk_PercentFloat) return p; 1.586 + 1.587 + if(chunk.id == Chunk_PercentInt) { 1.588 + p = Percent(ReadWord(file)); 1.589 + } else { 1.590 + p = Percent(ReadFloat(file)); 1.591 + } 1.592 + 1.593 + return p; 1.594 +} 1.595 + 1.596 + 1.597 +ChunkHeader ReadChunkHeader(HANDLE file) { 1.598 + ChunkHeader chunk; 1.599 + chunk.id = (ChunkID)ReadWord(file); 1.600 + chunk.size = ReadDword(file); 1.601 + return chunk; 1.602 +} 1.603 + 1.604 +void SkipChunk(HANDLE file, const ChunkHeader &chunk) { 1.605 + //file.ignore(chunk.size - HeaderSize); 1.606 + SetFilePointer(file, chunk.size - HeaderSize, 0, FILE_CURRENT); 1.607 + ReadCounter += chunk.size - HeaderSize; 1.608 +} 1.609 + 1.610 +void SkipBytes(HANDLE file, dword bytes) { 1.611 + SetFilePointer(file, bytes, 0, FILE_CURRENT); 1.612 + ReadCounter += bytes; 1.613 +} 1.614 + 1.615 +Material *FindMaterial(string name) { 1.616 + dword i=0; 1.617 + while(i < MatCount) { 1.618 + if(mat[i].name == name) return &mat[i]; 1.619 + i++; 1.620 + } 1.621 + 1.622 + return 0; 1.623 +} 1.624 + 1.625 +///////////////////// Read Object Function ////////////////////// 1.626 +int ReadObject(HANDLE file, const ChunkHeader &ch, void **obj) { 1.627 + if(!obj || !gc) return -1; 1.628 + 1.629 + ReadCounter = HeaderSize; // reset the global read counter 1.630 + 1.631 + string name = ReadString(file); 1.632 + 1.633 + ChunkHeader chunk; 1.634 + chunk = ReadChunkHeader(file); 1.635 + if(chunk.id == Chunk_Obj_TriMesh) { 1.636 + // object is a trimesh... load it 1.637 + Vertex *varray; 1.638 + Triangle *tarray; 1.639 + dword VertexCount=0, TriCount=0; 1.640 + Material mat; 1.641 + Base base; 1.642 + Vector3 translation; 1.643 + 1.644 + bool curve = true; 1.645 + 1.646 + dword ObjChunkSize = ch.size; 1.647 + 1.648 + while(ReadCounter < ObjChunkSize) { // make sure we only read subchunks of this object chunk 1.649 + //assert(!file.eof()); 1.650 + assert(!eof); 1.651 + chunk = ReadChunkHeader(file); 1.652 + 1.653 + switch(chunk.id) { 1.654 + case Chunk_TriMesh_VertexList: 1.655 + VertexCount = (dword)ReadWord(file); 1.656 + varray = new Vertex[VertexCount]; 1.657 + 1.658 + for(dword i=0; i<VertexCount; i++) { 1.659 + varray[i].pos = ReadVector(file); 1.660 + } 1.661 + 1.662 + break; 1.663 + 1.664 + case Chunk_TriMesh_FaceDesc: 1.665 + curve = false; // it is a real object not a curve since it has triangles 1.666 + TriCount = (dword)ReadWord(file); 1.667 + tarray = new Triangle[TriCount]; 1.668 + 1.669 + for(dword i=0; i<TriCount; i++) { 1.670 + tarray[i].vertices[0] = (Index)ReadWord(file); // 1.671 + tarray[i].vertices[2] = (Index)ReadWord(file); // flip order to CW 1.672 + tarray[i].vertices[1] = (Index)ReadWord(file); // 1.673 + ReadWord(file); // discard edge visibility flags 1.674 + } 1.675 + break; 1.676 + 1.677 + case Chunk_Face_Material: 1.678 + mat = *FindMaterial(ReadString(file)); 1.679 + 1.680 + SkipBytes(file, ReadWord(file)<<1); 1.681 + break; 1.682 + 1.683 + case Chunk_TriMesh_TexCoords: 1.684 + assert((dword)ReadWord(file) == VertexCount); 1.685 + 1.686 + for(dword i=0; i<VertexCount; i++) { 1.687 + varray[i].tex[0].u = varray[i].tex[1].u = ReadFloat(file); 1.688 + varray[i].tex[0].v = varray[i].tex[1].v = -ReadFloat(file); 1.689 + } 1.690 + break; 1.691 + 1.692 + case Chunk_TriMesh_SmoothingGroup: 1.693 + // **TODO** abide by smoothing groups duplicate vertices, weld others etc 1.694 + SkipChunk(file, chunk); 1.695 + break; 1.696 + 1.697 + case Chunk_TriMesh_WorldTransform: 1.698 + base.i = ReadVector(file); 1.699 + base.k = ReadVector(file); // flip 1.700 + base.j = ReadVector(file); 1.701 + translation = ReadVector(file); 1.702 + break; 1.703 + 1.704 + default: 1.705 + SkipChunk(file, chunk); 1.706 + } 1.707 + } 1.708 + 1.709 + if(curve) { 1.710 + CatmullRomSpline *spline = new CatmullRomSpline; 1.711 + spline->name = name; 1.712 + for(dword i=0; i<VertexCount; i++) { 1.713 + spline->AddControlPoint(varray[i].pos); 1.714 + } 1.715 + 1.716 + *obj = spline; 1.717 + return OBJ_CURVE; 1.718 + } else { 1.719 + 1.720 + base.i.Normalize(); 1.721 + base.j.Normalize(); 1.722 + base.k.Normalize(); 1.723 + Matrix3x3 RotXForm = base.CreateRotationMatrix(); 1.724 + RotXForm.OrthoNormalize(); 1.725 + 1.726 + for(dword i=0; i<VertexCount; i++) { 1.727 + varray[i].pos.Translate(-translation.x, -translation.y, -translation.z); 1.728 + varray[i].pos.Transform(RotXForm.Transposed()); 1.729 + } 1.730 + 1.731 + Object *object = new Object(gc); 1.732 + object->name = name; 1.733 + object->GetTriMesh()->SetData(varray, tarray, VertexCount, TriCount); 1.734 + object->material = mat; 1.735 + object->SetRotation(RotXForm); 1.736 + object->SetTranslation(translation.x, translation.y, translation.z); 1.737 + *obj = object; 1.738 + 1.739 + return OBJ_MESH; 1.740 + } 1.741 + } else { 1.742 + 1.743 + if(chunk.id == Chunk_Obj_Light) { 1.744 + 1.745 + dword ObjChunkSize = ch.size; 1.746 + 1.747 + Vector3 pos = ReadVector(file); 1.748 + Color color = ReadColor(file); 1.749 + 1.750 + Vector3 SpotTarget; 1.751 + float InnerCone, OuterCone; 1.752 + bool spot = false; 1.753 + bool att = false; 1.754 + bool CastShadows = false; 1.755 + float AttEnd = 10000.0f; 1.756 + float Intensity = 1.0f; 1.757 + 1.758 + while(ReadCounter < ObjChunkSize) { 1.759 + 1.760 + chunk = ReadChunkHeader(file); 1.761 + 1.762 + switch(chunk.id) { 1.763 + case Chunk_Light_SpotLight: 1.764 + spot = true; 1.765 + SpotTarget = ReadVector(file); 1.766 + InnerCone = ReadFloat(file) / 180.0f; 1.767 + OuterCone = ReadFloat(file) / 180.0f; 1.768 + break; 1.769 + 1.770 + case Chunk_Light_Attenuation: 1.771 + att = true; 1.772 + break; 1.773 + 1.774 + case Chunk_Light_AttenuationEnd: 1.775 + AttEnd = ReadFloat(file); 1.776 + break; 1.777 + 1.778 + case Chunk_Light_Intensity: 1.779 + Intensity = ReadFloat(file); 1.780 + break; 1.781 + 1.782 + case Chunk_Spot_CastShadows: 1.783 + CastShadows = true; 1.784 + break; 1.785 + 1.786 + default: 1.787 + SkipChunk(file, chunk); 1.788 + } 1.789 + } 1.790 + 1.791 + Light *light; 1.792 + if(spot) { 1.793 + light = new TargetSpotLight(pos, SpotTarget, InnerCone, OuterCone); 1.794 + } else { 1.795 + light = new PointLight(pos); 1.796 + } 1.797 + light->SetColor(color); 1.798 + light->SetShadowCasting(CastShadows); 1.799 + light->SetIntensity(Intensity); 1.800 + light->name = name; 1.801 + 1.802 + *obj = light; 1.803 + return spot ? OBJ_SPLIGHT : OBJ_PTLIGHT; 1.804 + } 1.805 + 1.806 + if(chunk.id == Chunk_Obj_Camera) { 1.807 + Camera *cam = new Camera; 1.808 + Vector3 pos = ReadVector(file); 1.809 + Vector3 targ = ReadVector(file); 1.810 + float roll = ReadFloat(file); 1.811 + float FOV = ReadFloat(file); 1.812 + 1.813 + Vector3 up = VECTOR3_J; 1.814 + Vector3 view = targ - pos; 1.815 + up.Rotate(view.Normalized(), roll); 1.816 + 1.817 + cam->SetCamera(pos, targ, up); 1.818 + cam->name = name; 1.819 + cam->SetFOV(DEGTORAD(FOV) / 1.33333f); 1.820 + 1.821 + *obj = cam; 1.822 + return OBJ_CAMERA; 1.823 + } 1.824 + } 1.825 + 1.826 + return -1; // should have already left by now, if not something is wrong 1.827 +} 1.828 + 1.829 + 1.830 +//////////////////////////////////////////////////////////////////////////////// 1.831 +// functions to save/load normals from file 1.832 + 1.833 +void WriteByte(HANDLE file, byte val) { 1.834 + dword junk; 1.835 + WriteFile(file, &val, sizeof(byte), &junk, 0); 1.836 +} 1.837 + 1.838 +void WriteDword(HANDLE file, dword val) { 1.839 + dword junk; 1.840 + WriteFile(file, &val, sizeof(dword), &junk, 0); 1.841 + assert(junk == sizeof(dword)); 1.842 +} 1.843 + 1.844 +void WriteFloat(HANDLE file, float val) { 1.845 + dword junk; 1.846 + WriteFile(file, &val, sizeof(float), &junk, 0); 1.847 + assert(junk == sizeof(float)); 1.848 +} 1.849 + 1.850 +void WriteString(HANDLE file, string str) { 1.851 + dword junk; 1.852 + for(dword i=0; i<(dword)str.size(); i++) { 1.853 + WriteFile(file, &str[i], sizeof(char), &junk, 0); 1.854 + } 1.855 +} 1.856 + 1.857 + 1.858 +void SaveNormalsToFile(const char *fname, Scene *scene) { 1.859 + 1.860 + HANDLE file = CreateFile(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 1.861 + assert(file); 1.862 + 1.863 + WriteDword(file, (dword)scene->GetObjectsList()->size()); 1.864 + 1.865 + std::list<Object*>::iterator objiter = scene->GetObjectsList()->begin(); 1.866 + while(objiter != scene->GetObjectsList()->end()) { 1.867 + WriteString(file, (*objiter)->name); 1.868 + dword VertexCount = (*objiter)->GetTriMesh()->GetVertexCount(); 1.869 + WriteDword(file, VertexCount); 1.870 + 1.871 + const Vertex *varray = (*objiter)->GetTriMesh()->GetVertexArray(); 1.872 + for(dword i=0; i<VertexCount; i++) { 1.873 + WriteFloat(file, varray[i].normal.x); 1.874 + WriteFloat(file, varray[i].normal.y); 1.875 + WriteFloat(file, varray[i].normal.z); 1.876 + } 1.877 + 1.878 + objiter++; 1.879 + } 1.880 + 1.881 + CloseHandle(file); 1.882 +} 1.883 + 1.884 +bool LoadNormalsFromFile(const char *fname, Scene *scene) { 1.885 + 1.886 + HANDLE file = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); 1.887 + if(!file) return false; 1.888 + 1.889 + eof = false; 1.890 + ReadCounter = 0; 1.891 + 1.892 + dword FileSize = SetFilePointer(file, 0, 0, FILE_END) - SetFilePointer(file, 0, 0, FILE_BEGIN); 1.893 + 1.894 + SetFilePointer(file, 0, 0, FILE_BEGIN); 1.895 + 1.896 + dword ObjectCount = ReadDword(file); 1.897 + if(ObjectCount != scene->GetObjectsList()->size()) { // detect changes 1.898 + CloseHandle(file); 1.899 + return false; 1.900 + } 1.901 + 1.902 + while(SceneLoader::ReadCounter < FileSize) { 1.903 + string name = ReadString(file); 1.904 + dword VertexCount = ReadDword(file); 1.905 + 1.906 + Object *obj = scene->GetObject(name.c_str()); 1.907 + if(!obj) { 1.908 + CloseHandle(file); 1.909 + return false; 1.910 + } 1.911 + 1.912 + if(VertexCount != obj->GetTriMesh()->GetVertexCount()) { // again detect changes 1.913 + CloseHandle(file); 1.914 + return false; 1.915 + } 1.916 + 1.917 + Vertex *varray = obj->GetTriMesh()->GetModVertexArray(); 1.918 + for(dword i=0; i<VertexCount; i++) { 1.919 + varray[i].normal = ReadVector(file, false); 1.920 + } 1.921 + } 1.922 + 1.923 + CloseHandle(file); 1.924 + return true; 1.925 +} 1.926 +