00001 #include "main.h"
00002
00003 #define MAX_BUFFER_LEN 256
00004
00005 struct rvlHeader
00006 {
00007 char head[4];
00008 int version;
00009 int numGeometries;
00010 int numTextures;
00011 int numObjects;
00012 int numLights;
00013 };
00014
00015 struct gemetryHeader
00016 {
00017 int vertexSize;
00018 int vertexCount;
00019 int indexCount;
00020 char name[32];
00021 };
00022
00023 Level::Level(IPhysic& physic, IRender& render)
00024 : physic(physic),
00025 render(render)
00026 {
00027 numGeometries = 0;
00028 numTextures = 0;
00029 numBodies = 0;
00030 geometries = 0;
00031 textures = 0;
00032 bodies = 0;
00033 start.zero();
00034 end.zero();
00035 items.init(32);
00036 for(int i=0; i<4; itemGeometries[i] = 0, i++);
00037 }
00038
00039 Level::~Level()
00040 {
00041 }
00042
00043 bool Level::loadMeshData(FILE* file, MeshData& meshData, const char* name)
00044 {
00045 gemetryHeader header;
00046
00047
00048 if(fread(&header, sizeof(gemetryHeader), 1, file) != 1)
00049 return false;
00050
00051
00052 if(header.vertexSize != int(sizeof(Vertex)))
00053 return false;
00054 if(header.vertexCount < 3)
00055 return false;
00056 if((header.indexCount < 3) || ((header.indexCount % 3) != 0))
00057 return false;
00058
00059 if(name == 0 || strcmp(header.name, name) == 0){
00060
00061 void* memory = malloc(header.vertexSize*header.vertexCount + 2*header.indexCount);
00062 Vertex* vertices = (Vertex*)memory;
00063 ushort* indices = (ushort*)&vertices[header.vertexCount];
00064
00065
00066 if(fread(vertices, sizeof(Vertex), header.vertexCount, file) != header.vertexCount)
00067 return fclose(file), false;
00068
00069 if(fread(indices, sizeof(ushort), header.indexCount, file) != header.indexCount)
00070 return fclose(file), false;
00071
00072
00073 meshData.vertexSize = header.vertexSize;
00074 meshData.vertexCount = header.vertexCount;
00075 meshData.indexCount = header.indexCount;
00076 meshData.vertices = vertices;
00077 meshData.indices = indices;
00078 }else{
00079 if(fseek(file, sizeof(Vertex)*header.vertexCount, SEEK_CUR) != 0)
00080 return fclose(file), false;
00081 if(fseek(file, sizeof(ushort)*header.indexCount, SEEK_CUR) != 0)
00082 return fclose(file), false;
00083 }
00084
00085 return true;
00086 }
00087
00088 bool Level::loadUnknown(const wchar* filename, int& width, int& height, Pixel** outData)
00089 {
00090 bool ok = true;
00091 size_t filenameLength = wcslen(filename);
00092
00093 if(wcscmp(&filename[filenameLength-4], TEXT(".bmp")) == 0)
00094 ok = loadBMP(filename, width, height, outData);
00095 else if(wcscmp(&filename[filenameLength-4], TEXT(".tga")) == 0)
00096 ok = loadTGA(filename, width, height, outData);
00097 else
00098 return false;
00099
00100 if(outData == 0 && width != height)
00101 return false;
00102
00103 return ok;
00104 }
00105
00106 bool Level::loadTextureData(const wchar* colorFilename, const wchar* normalFilename, const wchar* heightFilename, TextureData& out)
00107 {
00108 Pixel* colorData = 0;
00109 Pixel* normalData = 0;
00110 Pixel* heightData = 0;
00111 int widthColor = 0, heightColor = 0;
00112 int widthDetail = 0, heightDetail = 0;
00113 bool ok = true;
00114
00115 ok = loadUnknown(colorFilename, widthColor, heightColor, 0);
00116 if(ok) ok = loadUnknown(colorFilename, widthColor, heightColor, &colorData);
00117 ok = loadUnknown(normalFilename, widthDetail, heightDetail, 0);
00118 if(ok) ok = loadUnknown(normalFilename, widthDetail, heightDetail, &normalData);
00119 if(ok) ok = loadUnknown(heightFilename, widthDetail, heightDetail, &heightData);
00120
00121 if(ok == false)
00122 {
00123 SAVEFREE(colorData);
00124 SAVEFREE(normalData);
00125 SAVEFREE(heightData);
00126 return false;
00127 }
00128
00129 int mipmapsColor = 0;
00130 int mipmapsDetail = 0;
00131 int mipmapPixelsColor = 0;
00132 int mipmapPixelsDetail = 0;
00133 MipMap* colorMipmaps;
00134 MipMap* detailMipmaps;
00135
00136 for(int w=widthColor; w>0; mipmapPixelsColor+=w*w, w/=2, mipmapsColor++);
00137 for(int w=widthDetail; w>0; mipmapPixelsDetail+=w*w, w/=2, mipmapsDetail++);
00138
00139 void* mem = malloc(sizeof(MipMap)*(mipmapsColor+mipmapsDetail) + sizeof(Pixel)*(mipmapPixelsColor+mipmapPixelsDetail));
00140
00141 colorMipmaps = (MipMap*)mem;
00142 detailMipmaps = &colorMipmaps[mipmapsColor];
00143 Pixel* colorPixels = (Pixel*)&detailMipmaps[mipmapsDetail];
00144 Pixel* detailPixels = &colorPixels[mipmapPixelsColor];
00145
00146 for(int i=0, w=widthColor, curPixel=0; i<mipmapsColor; curPixel+=w*w, w/=2, i++)
00147 {
00148 colorMipmaps[i].width = w;
00149 colorMipmaps[i].height = w;
00150 colorMipmaps[i].data = &colorPixels[curPixel];
00151 }
00152
00153 for(int i=0, w=widthDetail, curPixel=0; i<mipmapsDetail; curPixel+=w*w, w/=2, i++)
00154 {
00155 detailMipmaps[i].width = w;
00156 detailMipmaps[i].height = w;
00157 detailMipmaps[i].data = &detailPixels[curPixel];
00158 }
00159
00160
00161 for(int y=0; y<colorMipmaps[0].height; y++)
00162 {
00163 for(int x=0; x<colorMipmaps[0].width; x++)
00164 colorMipmaps[0].data[y*widthColor+x] = colorData[y*widthColor+x];
00165 }
00166
00167
00168 for(int i=0; i<mipmapsColor-1; i++)
00169 {
00170 for(int y=0; y<colorMipmaps[i+1].height; y++)
00171 {
00172 for(int x=0; x<colorMipmaps[i+1].width; x++)
00173 {
00174 int color[4];
00175 for(int c=0; c<4; color[c] = colorMipmaps[i].data[((y+0)* colorMipmaps[i].width + x + 0)*2].canal[c], c++);
00176 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+0)* colorMipmaps[i].width + x + 1)*2].canal[c], c++);
00177 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+1)* colorMipmaps[i].width + x + 0)*2].canal[c], c++);
00178 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+1)* colorMipmaps[i].width + x + 1)*2].canal[c], c++);
00179 for(int c=0; c<4; colorMipmaps[i+1].data[y * colorMipmaps[i+1].width + x].canal[c] = uchar(color[c]/4), c++);
00180 }
00181 }
00182 }
00183
00184
00185 for(int y=0; y<detailMipmaps[0].height; y++)
00186 {
00187 for(int x=0; x<detailMipmaps[0].width; x++)
00188 {
00189 normalData[y*widthDetail+x].a = heightData[y*widthDetail+x].r;
00190 detailMipmaps[0].data[y*widthDetail+x] = normalData[y*widthDetail+x];
00191 }
00192 }
00193
00194
00195 for(int i=0; i<mipmapsDetail-1; i++)
00196 {
00197 for(int y=0; y<detailMipmaps[i].height/2; y++)
00198 {
00199 for(int x=0; x<detailMipmaps[i].width/2; x++)
00200 {
00201 int normal[4];
00202 for(int c=0; c<4; normal[c] = detailMipmaps[i].data[((y+0)* detailMipmaps[i].width + x + 0)*2].canal[c], c++);
00203 for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+0)* detailMipmaps[i].width + x + 1)*2].canal[c], c++);
00204 for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+1)* detailMipmaps[i].width + x + 0)*2].canal[c], c++);
00205 for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+1)* detailMipmaps[i].width + x + 1)*2].canal[c], c++);
00206 for(int c=0; c<4; detailMipmaps[i+1].data[y * detailMipmaps[i+1].width + x].canal[c] = uchar(normal[c]/4), c++);
00207 }
00208 }
00209 }
00210
00211
00212 SAVEFREE(colorData);
00213 SAVEFREE(normalData);
00214 SAVEFREE(heightData);
00215
00216
00217 out.mipmapsColor = mipmapsColor;
00218 out.mipmapsDetail = mipmapsDetail;
00219 out.color = colorMipmaps;
00220 out.detail = detailMipmaps;
00221 return true;
00222 }
00223
00224 bool Level::load(const wchar* filename, const wchar* textureDir)
00225 {
00226 unload();
00227
00228 FILE* file;
00229 const char rvlHead[] = "RVL ";
00230 rvlHeader header;
00231 int i;
00232 int lenBuffer;
00233 wchar bufferColor[MAX_BUFFER_LEN+1];
00234 wchar bufferNormal[MAX_BUFFER_LEN+1];
00235 wchar bufferHeight[MAX_BUFFER_LEN+1];
00236 char charBuffer[32];
00237 MeshData* meshDatas;
00238
00239 bufferColor[MAX_BUFFER_LEN] = bufferNormal[MAX_BUFFER_LEN] = bufferHeight[MAX_BUFFER_LEN] = 0;
00240
00241 if(wcslen(textureDir) + 32 > MAX_BUFFER_LEN)
00242 return false;
00243
00244
00245 if(_wfopen_s(&file, filename, TEXT("rb")) != 0)
00246 return false;
00247
00248
00249 if(fread(&header, sizeof(rvlHeader), 1, file) != 1)
00250 return fclose(file), false;
00251
00252
00253 if(*(uint*)header.head != *(uint*)rvlHead)
00254 return fclose(file), false;
00255 if(header.version != 1)
00256 return fclose(file), false;
00257
00258 numGeometries = header.numGeometries;
00259 numTextures = header.numTextures;
00260 numBodies = header.numObjects;
00261 numLights = header.numLights;
00262
00263
00264 void* memory = malloc((sizeof(pIGeometry)+sizeof(MeshData))*numGeometries + sizeof(pITexture)*numTextures + sizeof(pIBody)*numBodies);
00265 geometries = (pIGeometry*)memory;
00266 textures = (pITexture*)&geometries[numGeometries];
00267 bodies = (pIBody*)&textures[numTextures];
00268 meshDatas = (MeshData*)&bodies[numBodies];
00269
00270
00271 for(i=0; i<numGeometries; i++){
00272
00273 if(loadMeshData(file, meshDatas[i]) == false){
00274 printf("%s", "Geometry mesh data could not be loaded.");
00275 break;
00276 }
00277
00278 pIGeometry geom = render.createGeometry(meshDatas[i]);
00279
00280 if(geom == 0){
00281 printf("%s", "Geometry could not be created.");
00282 break;
00283 }
00284
00285 geometries[i] = geom;
00286 }
00287
00288 if(i != numGeometries){
00289 for(int a=0; a<i; meshDatas[a].free(), a++);
00290 return free(memory), fclose(file), false;
00291 }
00292
00293
00294 lenBuffer = wcslen(textureDir);
00295 for(int l=0; l<lenBuffer; bufferColor[l] = textureDir[l], l++);
00296 for(int l=0; l<lenBuffer; bufferNormal[l] = textureDir[l], l++);
00297 for(int l=0; l<lenBuffer; bufferHeight[l] = textureDir[l], l++);
00298
00299 for(i=0; i<numTextures; i++){
00300 int len;
00301 TextureData textureData;
00302
00303 memset(&charBuffer, 0, sizeof(char)*32);
00304 if(fread(&charBuffer, sizeof(char), 32, file) != 32){
00305 printf("%s", "Color texture name could not be read from the file.");
00306 break;
00307 }
00308 len = strlen(charBuffer);
00309 MultiByteToWideChar(CP_ACP, 0, charBuffer, len, &bufferColor[lenBuffer], len);
00310 bufferColor[lenBuffer+len] = 0;
00311
00312 memset(&charBuffer, 0, sizeof(char)*32);
00313 if(fread(&charBuffer, sizeof(char), 32, file) != 32){
00314 printf("%s", "Normal texture name could not be read from the file.");
00315 break;
00316 }
00317 len = strlen(charBuffer);
00318 MultiByteToWideChar(CP_ACP, 0, charBuffer, len, &bufferNormal[lenBuffer], len);
00319 bufferNormal[lenBuffer+len] = 0;
00320
00321 memset(&charBuffer, 0, sizeof(char)*32);
00322 if(fread(&charBuffer, sizeof(char), 32, file) != 32){
00323 printf("%s", "Height texture name could not be read from the file.");
00324 break;
00325 }
00326 len = strlen(charBuffer);
00327 MultiByteToWideChar(CP_ACP, 0, charBuffer, len, &bufferHeight[lenBuffer], len);
00328 bufferHeight[lenBuffer+len] = 0;
00329
00330 if(loadTextureData(bufferColor, bufferNormal, bufferHeight, textureData) == false){
00331 printf("%s", "Texture data could not be loaded.");
00332 break;
00333 }
00334
00335 pITexture tex = render.createTexture(textureData);
00336
00337 if(tex == 0){
00338 printf("Texture '%s' could not be loaded.", &bufferColor[lenBuffer]);
00339 break;
00340 }
00341
00342 textures[i] = tex;
00343 }
00344
00345 if(i != numTextures){
00346 for(int a=0; a<numGeometries; meshDatas[a].free(), a++);
00347 return free(memory), fclose(file), false;
00348 }
00349
00350
00351 for(i=0; i<numBodies; i++){
00352 pIBody body = 0;
00353 LevelObjectBody objData;
00354
00355 if(fread(&objData, sizeof(LevelObjectBody), 1, file) != 1){
00356 printf("%s", "Object data could not be loaded.");
00357 break;
00358 }
00359
00360 float boundingRadius = float3(objData.width/2, objData.height/2, objData.depth/2).length();
00361
00362 switch(objData.geom){
00363 case bodyDummy:
00364 body = physic.createDummy(
00365 objData.position,
00366 objData.rotation);
00367 break;
00368 case bodySphere:
00369 body = physic.createSphere(
00370 objData.position,
00371 objData.rotation,
00372 boundingRadius,
00373 objData.density,
00374 ushort(objData.group),
00375 objData.material,
00376 objData.type == typeDynamic);
00377 break;
00378 case bodyBox:
00379 body = physic.createBox(
00380 objData.position,
00381 objData.rotation,
00382 objData.width,
00383 objData.height,
00384 objData.depth,
00385 objData.density,
00386 ushort(objData.group),
00387 objData.material,
00388 objData.type == typeDynamic);
00389 break;
00390 case bodyMesh:
00391 body = physic.createMesh(
00392 objData.position,
00393 objData.rotation,
00394 meshDatas[objData.geometryID].vertices[0].position.v,
00395 meshDatas[objData.geometryID].vertexSize,
00396 meshDatas[objData.geometryID].vertexCount,
00397 meshDatas[objData.geometryID].indices,
00398 meshDatas[objData.geometryID].indexCount,
00399 objData.density,
00400 ushort(objData.group),
00401 objData.material,
00402 objData.type == typeDynamic);
00403 break;
00404 default:
00405 break;
00406 }
00407
00408 if(body == 0){
00409 printf("%s", "Object could not be loaded.");
00410 break;
00411 }
00412
00413 body->setRadius(boundingRadius);
00414
00415 bodies[i] = body;
00416
00417
00418 if(objData.textureID >= 0)
00419 render.createDrawCall(textures[objData.textureID], geometries[objData.geometryID], bodies[i]);
00420 else
00421 render.createColorDrawCall(geometries[objData.geometryID], bodies[i]);
00422 }
00423
00424 if(i != numBodies){
00425 for(int a=0; a<numGeometries; meshDatas[a].free(), a++);
00426 return free(memory), fclose(file), false;
00427 }
00428
00429 for(i=0; i<numLights; i++){
00430 LightData lightData;
00431
00432 if(fread(&lightData, sizeof(LightData), 1, file) != 1){
00433 printf("%s", "Light data could not be loaded.");
00434 break;
00435 }
00436
00437 render.setLight(i, lightData);
00438 }
00439
00440
00441 fclose(file);
00442 for(int a=0; a<numGeometries; meshDatas[a].free(), a++);
00443
00444
00445 if(i != numLights)
00446 return false;
00447
00448 int numberOfItems = 0;
00449 LevelItem levelItem;
00450 float3 position;
00451 int type;
00452 int item;
00453 float value;
00454 int filenameLen = wcslen(filename);
00455 if(filenameLen + 4 > MAX_BUFFER_LEN)
00456 return false;
00457 wcscpy_s(bufferColor, MAX_BUFFER_LEN, filename);
00458 bufferColor[filenameLen++] = TEXT('.');
00459 bufferColor[filenameLen++] = TEXT('d');
00460 bufferColor[filenameLen++] = TEXT('e');
00461 bufferColor[filenameLen++] = TEXT('f');
00462 bufferColor[filenameLen] = 0;
00463
00464
00465 if(_wfopen_s(&file, bufferColor, TEXT("rb")) != 0)
00466 return false;
00467
00468
00469 if(fread(&numberOfItems, sizeof(int), 1, file) != 1)
00470 return fclose(file), false;
00471
00472 itemBodies.init(numberOfItems);
00473 itemInstances.init(numberOfItems);
00474
00475 for(int i=0; i<numberOfItems; i++){
00476
00477 if(fread(&position, sizeof(float3), 1, file) != 1)
00478 return fclose(file), false;
00479 if(fread(&type, sizeof(int), 1, file) != 1)
00480 return fclose(file), false;
00481 if(fread(&item, sizeof(int), 1, file) != 1)
00482 return fclose(file), false;
00483 if(fread(&value, sizeof(float), 1, file) != 1)
00484 return fclose(file), false;
00485
00486 switch(type){
00487 case 0:
00488 start = position;
00489 break;
00490 case 1:
00491 end = position;
00492 break;
00493 case 2:
00494 levelItem.position = position;
00495 levelItem.item = item;
00496 levelItem.value = int(value);
00497 items.add(levelItem);
00498 if(itemGeometries[item]){
00499 pIBody body = physic.createDummy(position, float3(0.f,0.f,0.f));
00500 itemBodies.add(body);
00501 pInstance instance = render.createColorDrawCall(itemGeometries[item], body);
00502 itemInstances.add(instance);
00503 }
00504 break;
00505 default:
00506 break;
00507 }
00508 }
00509
00510 fclose(file);
00511
00512 return true;
00513 }
00514
00515 bool Level::loadGeometry(const wchar* filename, const char* name, pIGeometry& geometry)
00516 {
00517 FILE* file;
00518 const char rvlHead[] = "RVL ";
00519 rvlHeader header;
00520 int i;
00521 MeshData meshData;
00522
00523
00524 if(_wfopen_s(&file, filename, TEXT("rb")) != 0)
00525 return false;
00526
00527
00528 if(fread(&header, sizeof(rvlHeader), 1, file) != 1)
00529 return fclose(file), false;
00530
00531
00532 if(*(uint*)header.head != *(uint*)rvlHead)
00533 return fclose(file), false;
00534 if(header.version != 1)
00535 return fclose(file), false;
00536
00537 numGeometries = header.numGeometries;
00538
00539
00540 for(i=0; i<numGeometries; i++){
00541 if(loadMeshData(file, meshData, name) == false)
00542 continue;
00543
00544 geometry = render.createGeometry(meshData);
00545 meshData.free();
00546
00547 if(geometry == 0)
00548 printf("%s", "Geometry could not be created.");
00549 break;
00550 }
00551
00552 fclose(file);
00553
00554 if(geometry == 0)
00555 return false;
00556
00557 return true;
00558 }
00559
00560 bool Level::loadGeometry(const wchar* filename, const char* name, pIGeometry& geometry, MeshData& meshData)
00561 {
00562 FILE* file;
00563 const char rvlHead[] = "RVL ";
00564 rvlHeader header;
00565 int i;
00566
00567
00568
00569 if(_wfopen_s(&file, filename, TEXT("rb")) != 0)
00570 return false;
00571
00572
00573 if(fread(&header, sizeof(rvlHeader), 1, file) != 1)
00574 return fclose(file), false;
00575
00576
00577 if(*(uint*)header.head != *(uint*)rvlHead)
00578 return fclose(file), false;
00579 if(header.version != 1)
00580 return fclose(file), false;
00581
00582 numGeometries = header.numGeometries;
00583
00584
00585 for(i=0; i<numGeometries; i++){
00586 if(loadMeshData(file, meshData, name) == false)
00587 continue;
00588
00589 geometry = render.createGeometry(meshData);
00590
00591
00592 if(geometry == 0)
00593 printf("%s", "Geometry could not be created.");
00594 break;
00595 }
00596
00597 fclose(file);
00598
00599 if(geometry == 0)
00600 return false;
00601
00602 return true;
00603 }
00604
00605 void Level::unload(void)
00606 {
00607 render.clear();
00608 if(bodies){
00609 for(int i=0; i<numBodies; i++)
00610 physic.freeBody(bodies[i]);
00611 }
00612 if(textures){
00613 for(int i=0; i<numTextures; i++)
00614 render.freeTexture(textures[i]);
00615 }
00616 if(geometries){
00617 for(int i=0; i<numGeometries; i++)
00618 render.freeGeometry(geometries[i]);
00619 free(geometries);
00620 }
00621 for(uint i=0; i<itemBodies.size(); i++)
00622 physic.freeBody(itemBodies.getRef(i));
00623 numGeometries = 0;
00624 numTextures = 0;
00625 numBodies = 0;
00626 geometries = 0;
00627 textures = 0;
00628 bodies = 0;
00629 start.zero();
00630 end.zero();
00631 items.clear();
00632 itemBodies.uninit();
00633 itemInstances.uninit();
00634 }