mirror.cpp
上传用户:qccn516
上传日期:2013-05-02
资源大小:3382k
文件大小:4k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /* Mirror
  2.  *
  3.  * Copyright (C) 2003-2004, Alexander Zaprjagaev <frustum@frustum.org>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. #include "engine.h"
  20. #include "frustum.h"
  21. #include "mesh.h"
  22. #include "material.h"
  23. #include "pbuffer.h"
  24. #include "texture.h"
  25. #include "mirror.h"
  26. int Mirror::counter = 0;
  27. PBuffer *Mirror::pbuffers[3];
  28. /*
  29.  */
  30. Mirror::Mirror(Mesh *mesh) : mesh(mesh), material(NULL) {
  31. pos = getCenter();
  32. if(mesh->getNumSurfaces() == 0) {
  33. fprintf(stderr,"Mirror::Mirror: bad meshn");
  34. } else {
  35. Mesh::Triangle *triangles = mesh->getTriangles(0);
  36. plane = triangles[0].plane;
  37. }
  38. for(int i = 0; i < 3; i++) mirror_texes[i] = new Texture(128 << i,128 << i,Texture::TEXTURE_2D,Texture::RGB | Texture::LINEAR | Texture::CLAMP);
  39. if(counter++ == 0) {
  40. for(int i =  0; i < 3; i++) {
  41. pbuffers[i] = new PBuffer(128 << i,128 << i,PBuffer::RGB | PBuffer::DEPTH | PBuffer::STENCIL);
  42. pbuffers[i]->enable();
  43. glEnable(GL_DEPTH_TEST);
  44. glDepthFunc(GL_LESS);
  45. glEnable(GL_CULL_FACE);
  46. glCullFace(GL_BACK);
  47. pbuffers[i]->disable();
  48. }
  49. }
  50. }
  51. Mirror::~Mirror() {
  52. if(--counter == 0) {
  53. for(int i = 0; i < 3; i++) delete pbuffers[i];
  54. }
  55. }
  56. /*
  57.  */
  58. int Mirror::bindMaterial(const char *name,Material *material) {
  59. this->material = material;
  60. return 1;
  61. }
  62. /*
  63.  */
  64. void Mirror::enable() {
  65. old_camera = Engine::camera;
  66. old_modelview = Engine::modelview;
  67. old_imodelview = Engine::imodelview;
  68. mat4 transform;
  69. transform.reflect(plane);
  70. Engine::modelview = Engine::modelview * transform;
  71. Engine::imodelview = Engine::modelview.inverse();
  72. // save modelview
  73. modelview = Engine::modelview;
  74. // select best resolution
  75. if(Engine::viewport[3] > 512) {
  76. pbuffer = pbuffers[2];
  77. mirror_tex = mirror_texes[2];
  78. } else if(Engine::viewport[3] > 256) {
  79. pbuffer = pbuffers[1];
  80. mirror_tex = mirror_texes[1];
  81. } else {
  82. pbuffer = pbuffers[0];
  83. mirror_tex = mirror_texes[0];
  84. }
  85. // activate pbuffer
  86. pbuffer->enable();
  87. glGetIntegerv(GL_VIEWPORT,Engine::viewport);
  88. // load matrixes
  89. glMatrixMode(GL_PROJECTION);
  90. glLoadMatrixf(Engine::projection);
  91. glMatrixMode(GL_MODELVIEW);
  92. glLoadMatrixf(Engine::modelview);
  93. if(Engine::modelview.det() < 0.0) glFrontFace(GL_CW);
  94. else glFrontFace(GL_CCW);
  95. // get camera
  96. Engine::camera = Engine::imodelview * vec3(0,0,0);
  97. // hehe :)
  98. Engine::camera.sector = pos.sector;
  99. // set frustum
  100. Engine::frustum->set(Engine::projection * Engine::modelview);
  101. // render scene
  102. }
  103. void Mirror::disable() {
  104. // mirror texture
  105. mirror_tex->bind();
  106. mirror_tex->copy();
  107. pbuffer->disable();
  108. glGetIntegerv(GL_VIEWPORT,Engine::viewport);
  109. // restore matrixes
  110. Engine::camera = old_camera;
  111. Engine::modelview = old_modelview;
  112. Engine::imodelview = old_imodelview;
  113. // restore frustum
  114. Engine::frustum->set(Engine::projection * Engine::modelview);
  115. }
  116. /*
  117.  */
  118. void Mirror::render() {
  119. if(!material) return;
  120. if(!material->enable()) return;
  121. if(material->blend) {
  122. if(Engine::num_visible_lights == 0) glDepthMask(GL_FALSE);
  123. else glDepthFunc(GL_LESS);
  124. }
  125. material->bind();
  126. // <texture0> - mirror texture
  127. material->bindTexture(0,mirror_tex);
  128. glMatrixMode(GL_TEXTURE);
  129. glTranslatef(0.5,0.5,0);
  130. glScalef(0.5,0.5,0);
  131. glMultMatrixf(Engine::projection);
  132. glMultMatrixf(modelview);
  133. glDisable(GL_CULL_FACE);
  134. mesh->render(true);
  135. glEnable(GL_CULL_FACE);
  136. if(material->blend) {
  137. if(Engine::num_visible_lights == 0) glDepthMask(GL_TRUE);
  138. else glDepthFunc(GL_EQUAL);
  139. }
  140. glLoadIdentity();
  141. glMatrixMode(GL_MODELVIEW);
  142. }
  143. /*
  144.  */
  145. const vec3 &Mirror::getMin() {
  146. return mesh->getMin();
  147. }
  148. const vec3 &Mirror::getMax() {
  149. return mesh->getMax();
  150. }
  151. const vec3 &Mirror::getCenter() {
  152. return mesh->getCenter();
  153. }
  154. float Mirror::getRadius() {
  155. return mesh->getRadius();
  156. }