/* 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(0.0,100.0,0.0)).len(); if (cameraDistance > 10000 ) { } else if (cameraDistance >= 50000 ) { 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 int sampleRate = Res; float height = 0; int offset = 0; float r = 0.0; float g = 0.0; float b = 0.0; PRINTF(0)("loadin * \n"); if(heightMap != NULL && heightMap->format->BitsPerPixel == 8 ) SDL_LockSurface(heightMap); for(int i = i1 ; i <= i2 ; i +=sampleRate) { int w = 0; if(hm->hasColourMap) { r = (float)colours[3*w+2 + 3*i*(heightMap->w )]; g = (float)colours[3*w+1 + 3*i*(heightMap->w)]; b = (float)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][w].y,normalVectorField[i][w].z,normalVectorField[i][w].x); model->addTexCoor((float)(j1-sampleRate) /(texRate), (float)(i %heightMap->h)/(texRate)); PRINTF(0)("shiftX %f,shiftY %f,shiftZ %f\n", shiftX, shiftY ,shiftZ); 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 = (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)]; } 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][j].y,normalVectorField[i][j].z,normalVectorField[i][j].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][w].y,normalVectorField[i][w].z,normalVectorField[i][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][j].y,normalVectorField[i][j].z,normalVectorField[i][j].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][j].y,normalVectorField[i][j].z,normalVectorField[i][j].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][j].y,normalVectorField[i][j].z,normalVectorField[i][j].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][j].y,normalVectorField[i][j].z,normalVectorField[i][j].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++; } 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; } 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 )/ tileSize; i ++) { for(int j = 0; j < (heightMap->w - tileSize )/ 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 = 1; int i_max = (heightMap->h - tileSize )/ tileSize; int j_min = 1; int j_max= (heightMap->w - tileSize) / tileSize; for(int i = 1; i < i_max ; i ++) { for(int j = 1; 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]); // !!! 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; } 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; 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; height -= ( (a/c)*(x) + (b/c)*(y)); */ PRINTF(0)("height: %f \n" ,height ); return (height ); }