diff options
author | Piotr Dziwinski <piotrdz@gmail.com> | 2012-07-15 19:17:49 +0200 |
---|---|---|
committer | Piotr Dziwinski <piotrdz@gmail.com> | 2012-07-15 19:17:49 +0200 |
commit | 54f4da87923465a5387e2e854b58616647deb7af (patch) | |
tree | fc52b1866b29393be7d61a2341f04d430c078fdd /src/graphics/opengl/test/model_test.cpp | |
parent | eca6d26459200d2956d64ccf8a2713d96a82c989 (diff) | |
download | colobot-54f4da87923465a5387e2e854b58616647deb7af.tar.gz colobot-54f4da87923465a5387e2e854b58616647deb7af.tar.bz2 colobot-54f4da87923465a5387e2e854b58616647deb7af.zip |
Fix in model loading; simple model viewer
- fixed model loading code
- added simple model viewer (model_test) in src/graphics/opengl/test
- added system time stamp code
- split the code in app/system modules to separate headers
- added debug messages in model loading
- minor fixes in OpenGL engine
Diffstat (limited to 'src/graphics/opengl/test/model_test.cpp')
-rw-r--r-- | src/graphics/opengl/test/model_test.cpp | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/src/graphics/opengl/test/model_test.cpp b/src/graphics/opengl/test/model_test.cpp new file mode 100644 index 0000000..b73dc71 --- /dev/null +++ b/src/graphics/opengl/test/model_test.cpp @@ -0,0 +1,385 @@ +#include "app/system.h" +#include "common/logger.h" +#include "common/image.h" +#include "common/iman.h" +#include "graphics/common/modelfile.h" +#include "graphics/opengl/gldevice.h" +#include "math/geometry.h" + +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <unistd.h> + +#include <iostream> +#include <map> + +enum KeySlots +{ + K_RotXUp, + K_RotXDown, + K_RotYLeft, + K_RotYRight, + K_Forward, + K_Back, + K_Left, + K_Right, + K_Up, + K_Down, + K_Count +}; +bool KEYMAP[K_Count] = { false }; + +Math::Vector TRANSLATION(0.0f, 0.0f, 30.0f); +Math::Vector ROTATION; + +const int FRAME_DELAY = 5000; + +std::map<std::string, Gfx::Texture*> TEXS; + +SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL; + +Gfx::Texture* GetTexture(const std::string &name) +{ + std::map<std::string, Gfx::Texture*>::iterator it = TEXS.find(name); + if (it == TEXS.end()) + return NULL; + + return (*it).second; +} + +void LoadTexture(Gfx::CGLDevice *device, const std::string &name) +{ + if (name.empty()) + return; + + if (GetTexture(name) != NULL) + return; + + Gfx::Texture *tex = NULL; + + CImage img; + if (! img.Load(std::string("tex/") + name)) + { + std::string err = img.GetError(); + GetLogger()->Error("Texture not loaded, error: %s!\n", err.c_str()); + } + else + { + Gfx::TextureCreateParams texCreateParams; + texCreateParams.alpha = false; + texCreateParams.mipmap = true; + texCreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR; + texCreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR; + texCreateParams.wrapT = Gfx::TEX_WRAP_CLAMP; + + tex = device->CreateTexture(&img, texCreateParams); + } + + TEXS[name] = tex; +} + +void Init(Gfx::CGLDevice *device, Gfx::CModelFile *model) +{ + std::vector<Gfx::ModelTriangle> &triangles = model->GetTriangles(); + + for (int i = 0; i < (int) triangles.size(); ++i) + { + LoadTexture(device, triangles[i].tex1Name); + LoadTexture(device, triangles[i].tex2Name); + } + + device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); + device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true); + device->SetShadeModel(Gfx::SHADE_SMOOTH); + + Gfx::Light light; + light.type = Gfx::LIGHT_DIRECTIONAL; + light.ambient = Gfx::Color(0.4f, 0.4f, 0.4f, 0.0f); + light.diffuse = Gfx::Color(0.8f, 0.8f, 0.8f, 0.0f); + light.specular = Gfx::Color(0.2f, 0.2f, 0.2f, 0.0f); + light.position = Math::Vector(0.0f, 0.0f, -1.0f); + light.direction = Math::Vector(0.0f, 0.0f, 1.0f); + + device->SetGlobalAmbient(Gfx::Color(0.5f, 0.5f, 0.5f, 0.0f)); + device->SetLight(0, light); + device->SetLightEnabled(0, true); +} + +void Render(Gfx::CGLDevice *device, Gfx::CModelFile *modelFile) +{ + device->BeginScene(); + + Math::Matrix persp; + Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (600.0f) / (800.0f), 0.1f, 100.0f); + device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp); + + Math::Matrix id; + id.LoadIdentity(); + device->SetTransform(Gfx::TRANSFORM_WORLD, id); + + Math::Matrix viewMat; + Math::LoadTranslationMatrix(viewMat, TRANSLATION); + Math::Matrix rot; + Math::LoadRotationXZYMatrix(rot, ROTATION); + viewMat = Math::MultiplyMatrices(viewMat, rot); + device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat); + + std::vector<Gfx::ModelTriangle> &triangles = modelFile->GetTriangles(); + + Gfx::VertexTex2 tri[3]; + + for (int i = 0; i < (int) triangles.size(); ++i) + { + device->SetTexture(0, GetTexture(triangles[i].tex1Name)); + device->SetTexture(1, GetTexture(triangles[i].tex2Name)); + device->SetTextureEnabled(0, true); + device->SetTextureEnabled(1, true); + + Gfx::TextureParams tex1Params; + tex1Params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + tex1Params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; + device->SetTextureParams(0, tex1Params); + + Gfx::TextureParams tex2Params; + tex2Params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + tex2Params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; + device->SetTextureParams(1, tex2Params); + + device->SetMaterial(triangles[i].material); + + tri[0] = triangles[i].p1; + tri[1] = triangles[i].p2; + tri[2] = triangles[i].p3; + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, tri, 3); + } + + device->EndScene(); +} + +void Update() +{ + const float ROT_SPEED = 80.0f * Math::DEG_TO_RAD; // rad / sec + const float TRANS_SPEED = 3.0f; // units / sec + + GetCurrentTimeStamp(CURR_TIME); + float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC); + CopyTimeStamp(PREV_TIME, CURR_TIME); + + if (KEYMAP[K_RotYLeft]) + ROTATION.y -= ROT_SPEED * timeDiff; + if (KEYMAP[K_RotYRight]) + ROTATION.y += ROT_SPEED * timeDiff; + if (KEYMAP[K_RotXDown]) + ROTATION.x -= ROT_SPEED * timeDiff; + if (KEYMAP[K_RotXUp]) + ROTATION.x += ROT_SPEED * timeDiff; + + if (KEYMAP[K_Forward]) + TRANSLATION.z -= TRANS_SPEED * timeDiff; + if (KEYMAP[K_Back]) + TRANSLATION.z += TRANS_SPEED * timeDiff; + if (KEYMAP[K_Left]) + TRANSLATION.x += TRANS_SPEED * timeDiff; + if (KEYMAP[K_Right]) + TRANSLATION.x -= TRANS_SPEED * timeDiff; + if (KEYMAP[K_Up]) + TRANSLATION.y += TRANS_SPEED * timeDiff; + if (KEYMAP[K_Down]) + TRANSLATION.y -= TRANS_SPEED * timeDiff; +} + +void KeyboardDown(SDLKey key) +{ + switch (key) + { + case SDLK_LEFT: + KEYMAP[K_RotYLeft] = true; + break; + case SDLK_RIGHT: + KEYMAP[K_RotYRight] = true; + break; + case SDLK_UP: + KEYMAP[K_RotXUp] = true; + break; + case SDLK_DOWN: + KEYMAP[K_RotXDown] = true; + break; + case SDLK_w: + KEYMAP[K_Forward] = true; + break; + case SDLK_s: + KEYMAP[K_Back] = true; + break; + case SDLK_a: + KEYMAP[K_Left] = true; + break; + case SDLK_d: + KEYMAP[K_Right] = true; + break; + case SDLK_z: + KEYMAP[K_Down] = true; + break; + case SDLK_x: + KEYMAP[K_Up] = true; + break; + default: + break; + } +} + +void KeyboardUp(SDLKey key) +{ + switch (key) + { + case SDLK_LEFT: + KEYMAP[K_RotYLeft] = false; + break; + case SDLK_RIGHT: + KEYMAP[K_RotYRight] = false; + break; + case SDLK_UP: + KEYMAP[K_RotXUp] = false; + break; + case SDLK_DOWN: + KEYMAP[K_RotXDown] = false; + break; + case SDLK_w: + KEYMAP[K_Forward] = false; + break; + case SDLK_s: + KEYMAP[K_Back] = false; + break; + case SDLK_a: + KEYMAP[K_Left] = false; + break; + case SDLK_d: + KEYMAP[K_Right] = false; + break; + case SDLK_z: + KEYMAP[K_Down] = false; + break; + case SDLK_x: + KEYMAP[K_Up] = false; + break; + default: + break; + } +} + +int main(int argc, char *argv[]) +{ + CLogger logger; + + PREV_TIME = CreateTimeStamp(); + CURR_TIME = CreateTimeStamp(); + + GetCurrentTimeStamp(PREV_TIME); + GetCurrentTimeStamp(CURR_TIME); + + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << "{mod|dxf} model_file" << std::endl; + return 1; + } + + CInstanceManager iMan; + + Gfx::CModelFile *modelFile = new Gfx::CModelFile(&iMan); + if (std::string(argv[1]) == "mod") + { + if (! modelFile->ReadModel(argv[2], false, false)) + { + std::cerr << "Error reading MOD: " << modelFile->GetError() << std::endl; + return 1; + } + } + else if (std::string(argv[1]) == "dxf") + { + if (! modelFile->ReadDXF(argv[2], 0.0f, 0.0f)) + { + std::cerr << "Error reading DXF: " << modelFile->GetError() << std::endl; + return 1; + } + } + else + { + std::cerr << "Usage: " << argv[0] << "{mod|dxf} model_file" << std::endl; + return 1; + } + + // Without any error checking, for simplicity + + SDL_Init(SDL_INIT_VIDEO); + + IMG_Init(IMG_INIT_PNG); + + const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); + + Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE; + + if (videoInfo->hw_available) + videoFlags |= SDL_HWSURFACE; + else + videoFlags |= SDL_SWSURFACE; + + if (videoInfo->blit_hw) + videoFlags |= SDL_HWACCEL; + + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags); + + + SDL_WM_SetCaption("Model Test", "Model Test"); + + Gfx::CGLDevice *device = new Gfx::CGLDevice(); + device->Create(); + + Init(device, modelFile); + + bool done = false; + while (! done) + { + Render(device, modelFile); + Update(); + + SDL_GL_SwapBuffers(); + + SDL_Event event; + SDL_PollEvent(&event); + if (event.type == SDL_QUIT) + done = true; + else if (event.type == SDL_KEYDOWN) + KeyboardDown(event.key.keysym.sym); + else if (event.type == SDL_KEYUP) + KeyboardUp(event.key.keysym.sym); + + usleep(FRAME_DELAY); + } + + delete modelFile; + + device->Destroy(); + delete device; + + SDL_FreeSurface(surface); + + IMG_Quit(); + + SDL_Quit(); + + DestroyTimeStamp(PREV_TIME); + DestroyTimeStamp(CURR_TIME); + + return 0; +} |