/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: bottac@ee.ethz.ch */ #include "height_map.h" #include "model.h" #include "texture.h" #include "vector.h" #include "material.h" #include "p_node.h" #include "state.h" #include "resource_manager.h" #include "debug.h" // INCLUDING SDL_Image #ifdef HAVE_SDL_IMAGE_H #include #else #include #endif Tile::Tile(int i1, int j1, int i2, int j2, HeightMap* hm ) { PRINTF(0)("Tile Constructor\n"); highResModel = new VertexArrayModel(); lowResModel = new VertexArrayModel(); this->load(i1,j1,i2,j2,hm,highResModel,4); this->load(i1,j1,i2,j2,hm,lowResModel, 8); } Tile::Tile() { PRINTF(0)("ooops *********************************************************************************************************************************************************************************************************** \n"); } Tile::~Tile() { delete highResModel; delete lowResModel; } void Tile::draw() { // This Draws the LOD's //FIXME float cameraDistance = (State::getCamera()->getAbsCoor() - Vector(this->x, hmref->offsetY , this->z) ).len(); if(cameraDistance < 0) cameraDistance = -cameraDistance; if(cameraDistance > 5000 ) { return; } else if (cameraDistance >= 1000 ) { this->drawLowRes(); } else { this->drawHighRes(); } } void Tile::drawHighRes() { highResModel->draw(); } void Tile::drawLowRes() { lowResModel->draw(); } /* */ void Tile::load(int i1, int j1, int i2, int j2, HeightMap* hm, VertexArrayModel* model, int Res) { #define heightMap hm->heightMap #define colours hm->colours #define scaleX hm->scaleX #define scaleY hm->scaleY #define scaleZ hm->scaleZ #define shiftX hm->shiftX #define shiftY hm->shiftY #define shiftZ hm->shiftZ #define normalVectorField hm->normalVectorField hmref = hm; // FIXME this->x = hm->offsetX + (heightMap->h - ((i1+i2)/2))*scaleX; this->z = hm->offsetZ + ((j1 + j2 )/2 ) * scaleZ; int sampleRate = Res; float height = 0; int offset = 0; float r = 0.0; float g = 0.0; float b = 0.0; if(heightMap != NULL && heightMap->format->BitsPerPixel == 8 ) SDL_LockSurface(heightMap); SDL_LockSurface(hm->colourMap); for(int i = i1 ; i <= i2 ; i +=sampleRate) { int w = 0; if(hm->hasColourMap) { r = colours[(3*w+2 + 3*i*(heightMap->w )) ]; g = colours[(3*w+1 + 3*i*(heightMap->w)) ]; b = colours[(3*w+0 + 3*i*(heightMap->w))]; } w = j1; model->addVertex(scaleX*(heightMap->h -i)+ shiftX,shiftY,scaleZ*(w)+ shiftZ); // Top Right model->addNormal(normalVectorField[i % heightMap->h][w % heightMap->w].y,normalVectorField[i % heightMap->h][w % heightMap->w].z,normalVectorField[i % heightMap->h][w % heightMap->w].x); model->addTexCoor((float)(j1-sampleRate) /(texRate), (float)(i %heightMap->h)/(texRate)); model->addColor(r/255.0,g/255.0,b/255.0); for(int j = j1 ; j <= j2 ; j += sampleRate) { // To be fixed if(hm->hasColourMap) { r = colours[(3*j+2 + 3*i*(heightMap->w )) ]; g = colours[(3*j+1 + 3*i*(heightMap->w)) ]; b = colours[(3*j+0 + 3*i*(heightMap->w))]; } height = (float)(unsigned char) hm->heights[(j +sampleRate+ i*(heightMap->w )) ]; height += (float)(unsigned char) hm->heights[(j+ 1 + sampleRate + (i+1)*(heightMap->w )) ]; height += (float) (unsigned char) hm->heights[(j -1+ sampleRate + (i+1)*(heightMap->w ))]; height += (float)(unsigned char)hm->heights[(j +sampleRate+ (i+2)*(heightMap->w )) ]; height += (float)(unsigned char)hm->heights[(j+sampleRate + (i)*(heightMap->w )) ]; height=height/5.0; model->addVertex(scaleX*(heightMap->h -i) + shiftX ,((double)(height)*scaleY) + shiftY ,scaleZ*(j) + shiftZ); // Top Right model->addNormal(normalVectorField[i % heightMap->h][j % heightMap->w].y,normalVectorField[i % heightMap->h][j % heightMap->w].z,normalVectorField[i % heightMap->h][j % heightMap->w].x); model->addTexCoor((float)(j) /(texRate), (float)(i %heightMap->h)/(texRate)); //PRINTF(0)("TexCoord: %f %f \n",(float)j / 100.0, (float)(i %heightMap->h)/100.0); model->addColor(r/255.0,g/255.0,b/255.0); w = j; } model->addVertex(scaleX*(heightMap->h -i)+ shiftX,shiftY,scaleZ*(w)+ shiftZ); // Top Right model->addNormal(normalVectorField[i % heightMap->h][w % heightMap->w].y,normalVectorField[i % heightMap->h][w % heightMap->w].z,normalVectorField[i% heightMap->h][w % heightMap->w].x); model->addTexCoor((float)(j2+sampleRate) /(texRate), (float)(i %heightMap->h)/(texRate)); model->addColor(r/255.0,g/255.0,b/255.0); } SDL_UnlockSurface(heightMap); int cnt = 0; for(int i = i1 ; i < i2 ; i +=sampleRate) { for(int j = j1-sampleRate ; j < j2 + 2*sampleRate ; j += sampleRate) { model->addIndice(cnt); model->addIndice(cnt + (j2 -j1 + 3* sampleRate )/ sampleRate ); cnt++; } model->newStripe(); } cnt += (j2 -j1 + 3* sampleRate)/ sampleRate; for(int j = j1 ; j <= j2 ; j += sampleRate) { int i = i1; // To be fixed if(hm->hasColourMap) { r = (float)colours[(3*j+2 + 3*i*(heightMap->w )) ]; g = (float)colours[(3*j+1 + 3*i*(heightMap->w)) ]; b = (float)colours[(3*j+0 + 3*i*(heightMap->w))]; } model->addVertex(scaleX*(heightMap->h -i) + shiftX , shiftY ,scaleZ*(j) + shiftZ); // Top Right model->addNormal(normalVectorField[i % heightMap->h][j % heightMap->w].y,normalVectorField[i % heightMap->h][j % heightMap->w].z,normalVectorField[i % heightMap->h][j % heightMap->w].x); model->addTexCoor((float)j /(texRate), (float)((i - sampleRate) %heightMap->h)/(texRate)); model->addColor(r/255.0,g/255.0,b/255.0); } for(int j = j1 ; j <= j2 ; j += sampleRate) { int i = i1; height = (float)(unsigned char) hm->heights[(j +sampleRate+ i*(heightMap->w )) ]; height += (float)(unsigned char) hm->heights[(j+ 1 + sampleRate + (i+1)*(heightMap->w )) ]; height += (float) (unsigned char) hm->heights[(j -1+ sampleRate + (i+1)*(heightMap->w ))]; height += (float)(unsigned char)hm->heights[(j +sampleRate+ (i+2)*(heightMap->w )) ]; height += (float)(unsigned char)hm->heights[(j+sampleRate + (i)*(heightMap->w )) ]; height=height/5.0; model->addVertex(scaleX*(heightMap->h -i) + shiftX , ((double)(height)*scaleY) +shiftY ,scaleZ*(j) + shiftZ); // Top Right model->addNormal(normalVectorField[i % heightMap->h][j % heightMap->w].y,normalVectorField[i % heightMap->h][j% heightMap->w].z,normalVectorField[i%heightMap->h][j%heightMap->w].x); model->addTexCoor((float)j /(texRate), (float)(i %heightMap->h)/(texRate)); model->addColor(r/255.0,g/255.0,b/255.0); } for(int j = j1 ; j <= j2 ; j += sampleRate) { int i = i2; // To be fixed if(hm->hasColourMap) { r = (float)colours[3*j+2 + 3*i*(heightMap->w )]; g = (float)colours[3*j+1 + 3*i*(heightMap->w)]; b = (float)colours[3*j+0 + 3*i*(heightMap->w)]; } model->addVertex(scaleX*(heightMap->h -i) + shiftX , shiftY ,scaleZ*(j) + shiftZ); // Top Right model->addNormal(normalVectorField[i%heightMap->h][j%heightMap->w].y,normalVectorField[i%heightMap->h][j%heightMap->w].z,normalVectorField[i%heightMap->h][j%heightMap->w].x); model->addTexCoor((float)j /(texRate), (float)((i+ sampleRate) %heightMap->h)/(texRate)); model->addColor(r/255.0,g/255.0,b/255.0); } for(int j = j1 ; j <= j2 ; j += sampleRate) { int i = i2; height = (float)(unsigned char) hm->heights[(j +sampleRate+ i*(heightMap->w )) ]; height += (float)(unsigned char) hm->heights[(j+ 1 + sampleRate + (i+1)*(heightMap->w )) ]; height += (float) (unsigned char) hm->heights[(j -1+ sampleRate + (i+1)*(heightMap->w ))]; height += (float)(unsigned char)hm->heights[(j +sampleRate+ (i+2)*(heightMap->w ))]; height += (float)(unsigned char)hm->heights[(j+sampleRate + (i)*(heightMap->w )) ]; height=height/5.0; model->addVertex(scaleX*(heightMap->h -i) + shiftX , ((double)(height)*scaleY) +shiftY ,scaleZ*(j) + shiftZ); // Top Right model->addNormal(normalVectorField[i%heightMap->h][j%heightMap->w].y,normalVectorField[i%heightMap->h][j%heightMap->w].z,normalVectorField[i%heightMap->h][j%heightMap->w].x); model->addTexCoor((float)j /(texRate), (float)(i %heightMap->h)/(texRate)); model->addColor(r/255.0,g/255.0,b/255.0); } // link Boarder Stripe for(int j = j1-sampleRate ; j < j2 ; j += sampleRate) { model->addIndice(cnt); model->addIndice(cnt + (j2 -j1 + sampleRate )/ sampleRate ); cnt++; } cnt++; model->newStripe(); cnt += (j2-j1)/ sampleRate; // link 2nd BoarderStripe for(int j = j1-sampleRate ; j < j2 ; j += sampleRate) { model->addIndice(cnt); model->addIndice(cnt + (j2 -j1 + sampleRate )/ sampleRate ); cnt++; } SDL_UnlockSurface(hm->colourMap); model->finalize(); #undef heightMap #undef colours #undef scaleX #undef scaleY #undef scaleZ #undef shiftX #undef shiftY #undef shiftZ #undef normalVectorField } HeightMap::HeightMap() { } HeightMap::HeightMap(const char* height_map_name = NULL) : VertexArrayModel() { this->setClassID(CL_HEIGHT_MAP, "HeightMap"); heightMap = IMG_Load(height_map_name); if(heightMap!=NULL) { PRINTF(0)("loading Image %s\n", height_map_name); PRINTF(0)("width : %i\n", heightMap->w); PRINTF(0)("height : %i\n", heightMap->h); PRINTF(0)("%i Byte(s) per Pixel \n", heightMap->format->BytesPerPixel); PRINTF(0)("Rshift : %i\n", heightMap->format->Rshift); PRINTF(0)("Bshift: %i\n", heightMap->format->Bshift); PRINTF(0)("Gshift: %i\n", heightMap->format->Gshift); PRINTF(0)("Rmask: %i\n", heightMap->format->Rmask); PRINTF(0)("Gmask: %i\n", heightMap->format->Gmask); } else PRINTF(4)("oops! couldn't load %s for some reason.\n", height_map_name); generateNormalVectorField(); shiftX = 0; shiftY = 0; shiftZ = 0; } HeightMap::HeightMap(const char* height_map_name = NULL, const char* colour_map_name = NULL) : VertexArrayModel() { this->setClassID(CL_HEIGHT_MAP, "HeightMap"); heightMap = IMG_Load(height_map_name); if(heightMap!=NULL) { PRINTF(0)("loading Image %s\n", height_map_name); PRINTF(0)("width : %i\n", heightMap->w); PRINTF(0)("height : %i\n", heightMap->h); PRINTF(0)("%i Byte(s) per Pixel \n", heightMap->format->BytesPerPixel); PRINTF(0)("Rshift : %i\n", heightMap->format->Rshift); PRINTF(0)("Bshift: %i\n", heightMap->format->Bshift); PRINTF(0)("Gshift: %i\n", heightMap->format->Gshift); PRINTF(0)("Rmask: %i\n", heightMap->format->Rmask); PRINTF(0)("Gmask: %i\n", heightMap->format->Gmask); } else PRINTF(4)("oops! couldn't load %s for some reason.\n", height_map_name); generateNormalVectorField(); colourMap=NULL; if(colour_map_name != NULL) { colourMap = IMG_Load(colour_map_name); } if(colourMap != NULL) { PRINTF(0)("loading Image %s\n", colour_map_name); PRINTF(0)("width : %i\n", colourMap->w); PRINTF(0)("height : %i\n", colourMap->h); PRINTF(0)("%i Byte(s) per Pixel \n", colourMap->format->BytesPerPixel); PRINTF(0)("Rshift : %i\n", colourMap->format->Rshift); PRINTF(0)("Bshift: %i\n", colourMap->format->Bshift); PRINTF(0)("Gshift: %i\n", colourMap->format->Gshift); PRINTF(0)("Rmask: %i\n", colourMap->format->Rmask); PRINTF(0)("Gmask: %i\n", colourMap->format->Gmask); } else PRINTF(0)("oops! couldn't load colorMap for some reason.\n"); if(colourMap != NULL) { colours = (unsigned char *) colourMap->pixels; hasColourMap = true; } else hasColourMap = false; heights = (unsigned char*) heightMap->pixels; shiftX = 0; shiftY = 0; shiftZ = 0; } HeightMap::~HeightMap() { delete heightMap; delete colourMap; for(int i=0;i < heightMap->h/tileSize ; i++) { for(int j = 0; j < heightMap->w/ tileSize; j++) { delete tiles [i][j]; } } for(int i=0;i < heightMap->h/tileSize ; i++) delete[] tiles[i]; delete[] tiles; } void HeightMap::load() { //Create a Dynamicly sized 2D-Array for Tiles tiles = new Tile** [heightMap->h/tileSize]; for(int i=0;i < heightMap->h/tileSize ; i++) tiles [i]= new (Tile* [heightMap->w /tileSize ]); //SetUp Arrays for(int i = 0; i < (heightMap->h )/ tileSize; i ++) { for(int j = 0; j < (heightMap->w )/ tileSize; j ++) { tiles[i][j] = new Tile( i*tileSize , j*tileSize , (i+1)*tileSize, (j+1)*tileSize , this ) ; } } } void HeightMap::draw() { const PNode* camera = State::getCamera(); Vector v = camera->getAbsCoor(); int i_min = 0; int i_max = (heightMap->h )/ tileSize; int j_min = 0; int j_max= (heightMap->w ) / tileSize; for(int i = 0; i < i_max ; i ++) { for(int j = 0; j < j_max ; j++) { tiles[i][j]->draw(); } } } void HeightMap::generateNormalVectorField() { int delta = 1; heights = (unsigned char*) heightMap->pixels; //Create a Dynamicly sized 2D-Array to store our normals normalVectorField = new Vector* [heightMap->h]; for(int i=0;ih;i++) normalVectorField [i]= new (Vector [heightMap->w]); // Initialize for(int i=0; i< heightMap->h; i++) { for(int j = 0; j> heightMap->w; j++) { Vector v = Vector(0.0, 1.0, 0.0); normalVectorField[i][j] = v; } } // !!! Does not yet calculate the normals of some border points!!!!! if(heightMap != NULL && heightMap->format->BitsPerPixel == 8 ) { SDL_LockSurface(heightMap); for(int i = 0 ; i < heightMap->h - 1 ; i ++) { for(int j = 0; j < heightMap->w - 1 ; j ++) { delta = (int)heights[j + (i+1)*(heightMap->w )] - (int) heights[j + i*(heightMap->w )]; Vector a = Vector(-scaleX,(float)delta*scaleY ,0.0f); delta = (int)heights[j+1 + i*(heightMap->w )] - (int)heights[j + i*(heightMap->w )]; Vector b = Vector(0.0f,(float) delta*scaleY ,scaleZ); normalVectorField[i][j] = b.cross(a); normalVectorField[i][j].normalize(); } } SDL_UnlockSurface(heightMap); } } void HeightMap::scale(Vector v) { scaleX = v.x; scaleY = v.y; scaleZ = v.z; generateNormalVectorField(); } void HeightMap::setAbsCoor(Vector v) { offsetX = v.x; offsetY = v.y; offsetZ = v.z; } float HeightMap::getHeight(float x, float y) { x -= offsetX; y -= offsetZ; int xInt = (int)x / scaleX; x -= (float)((int)x); xInt = heightMap->h - xInt; int yInt = (int)y / scaleZ; y -= (float) ((int) y); /*yInt = heightMap->w - yInt;*/ //PRINTF(0)("xInt: %i, yInt: %i, x: %f, y: %f\n", xInt, yInt, x, y); if(xInt <= 0 || xInt >= heightMap->h || yInt <= 0 || yInt >= heightMap->w ) return 0; if( y >= 0.5*x) { // Check for ... } float height = heights[yInt + (xInt)*heightMap->w]*scaleY; float a = normalVectorField[(xInt)][yInt].x; float b = normalVectorField [(xInt)][yInt].z; float c = normalVectorField [(xInt)][yInt].y; PRINTF(0)("a: %f \n" ,a); PRINTF(0)("b: %f \n" ,b); PRINTF(0)("c: %f \n" ,c); height -= ( (a/c)*(x) + (b/c)*(y)); PRINTF(0)("height: %f \n" ,height ); return (height + offsetZ); }