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

游戏引擎

开发平台:

Visual C++

  1. /* Bsp
  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 "console.h"
  20. #include "engine.h"
  21. #include "frustum.h"
  22. #include "material.h"
  23. #include "mesh.h"
  24. #include "meshvbo.h"
  25. #include "object.h"
  26. #include "objectmesh.h"
  27. #include "bsp.h"
  28. /*****************************************************************************/
  29. /*                                                                           */
  30. /* Node                                                                      */
  31. /*                                                                           */
  32. /*****************************************************************************/
  33. Node::Node() : left(NULL), right(NULL), object(NULL) {
  34. min = vec3(1000000,1000000,1000000);
  35. max = vec3(-1000000,-1000000,-1000000);
  36. center = vec3(0,0,0);
  37. radius = 1000000;
  38. }
  39. Node::~Node() {
  40. if(left) delete left;
  41. if(right) delete right;
  42. if(object) {
  43. delete object->mesh;
  44. delete object;
  45. }
  46. }
  47. /*
  48.  */
  49. void Node::create(Mesh *mesh) {
  50. min = mesh->getMin();
  51. max = mesh->getMax();
  52. center = mesh->getCenter();
  53. radius = mesh->getRadius();
  54. int num_vertex = 0;
  55. for(int i = 0; i < mesh->getNumSurfaces(); i++) num_vertex += mesh->getNumVertex(i);
  56. if(num_vertex / 3 > TRIANGLES_PER_NODE) {
  57. vec4 plane;
  58. vec3 size = max - min;
  59. if(size.x > size.y) { // find clip plane
  60. if(size.x > size.z) plane = vec4(1,0,0,1);
  61. else plane = vec4(0,0,1,1);
  62. } else{
  63. if(size.y > size.z) plane = vec4(0,1,0,1);
  64. else plane = vec4(0,0,1,1);
  65. }
  66. vec3 center(0,0,0);
  67. int num_vertex = 0; // find center of node
  68. for(int i = 0; i < mesh->getNumSurfaces(); i++) {
  69. Mesh::Vertex *vertex = mesh->getVertex(i);
  70. for(int j = 0; j < mesh->getNumVertex(i); j++) {
  71. center += vertex[j].xyz;
  72. num_vertex++;
  73. }
  74. }
  75. center /= (float)num_vertex;
  76. plane.w = -(plane * vec4(center,1));
  77. Mesh *left_mesh = new Mesh();
  78. Mesh *right_mesh = new Mesh();
  79. for(int i = 0; i < mesh->getNumSurfaces(); i++) {
  80. int num_vertex = mesh->getNumVertex(i);
  81. Mesh::Vertex *vertex = mesh->getVertex(i);
  82. int left_mesh_num_vertex = 0;
  83. Mesh::Vertex *left_mesh_vertex = new Mesh::Vertex[num_vertex * 2];
  84. int right_mesh_num_vertex = 0;
  85. Mesh::Vertex *right_mesh_vertex = new Mesh::Vertex[num_vertex * 2];
  86. for(int j = 0; j < num_vertex; j += 3) {
  87. /*int pos = 0;
  88. if(plane * vec4(vertex[j + 0].xyz,1) > 0.0) pos++;
  89. if(plane * vec4(vertex[j + 1].xyz,1) > 0.0) pos++;
  90. if(plane * vec4(vertex[j + 2].xyz,1) > 0.0) pos++;
  91. if(pos > 1) {
  92. left_mesh_vertex[left_mesh_num_vertex++] = vertex[j + 0];
  93. left_mesh_vertex[left_mesh_num_vertex++] = vertex[j + 1];
  94. left_mesh_vertex[left_mesh_num_vertex++] = vertex[j + 2];
  95. } else {
  96. right_mesh_vertex[right_mesh_num_vertex++] = vertex[j + 0];
  97. right_mesh_vertex[right_mesh_num_vertex++] = vertex[j + 1];
  98. right_mesh_vertex[right_mesh_num_vertex++] = vertex[j + 2];
  99. }*/
  100. int num_left = 0;
  101. int num_right = 0;
  102. Mesh::Vertex *left = &left_mesh_vertex[left_mesh_num_vertex];
  103. Mesh::Vertex *right = &right_mesh_vertex[right_mesh_num_vertex];
  104. float cur_dot = plane * vec4(vertex[j + 0].xyz,1);
  105. for(int cur = 0; cur < 3; cur++) {
  106. int next = (cur + 1) % 3;
  107. float next_dot = plane * vec4(vertex[j + next].xyz,1);
  108. if(cur_dot <= 0.0) left[num_left++] = vertex[j + cur];
  109. if(cur_dot > 0.0) right[num_right++] = vertex[j + cur];
  110. if((cur_dot <= 0.0) != (next_dot <= 0.0)) {
  111. float k = -cur_dot / (next_dot - cur_dot);
  112. Mesh::Vertex v;
  113. v.xyz = vertex[j + cur].xyz * (1.0f - k) + vertex[j + next].xyz * k;
  114. v.normal = vertex[j + cur].normal * (1.0f - k) + vertex[j + next].normal * k;
  115. v.tangent = vertex[j + cur].tangent * (1.0f - k) + vertex[j + next].tangent * k;
  116. v.binormal = vertex[j + cur].binormal * (1.0f - k) + vertex[j + next].binormal * k;
  117. v.texcoord = vertex[j + cur].texcoord * (1.0f - k) + vertex[j + next].texcoord * k;
  118. left[num_left++] = v;
  119. right[num_right++] = v;
  120. }
  121. cur_dot = next_dot;
  122. }
  123. if(num_left == 3) left_mesh_num_vertex += 3;
  124. else if(num_left == 4) {
  125. left[4] = left[0];
  126. left[5] = left[2];
  127. left_mesh_num_vertex += 6;
  128. }
  129. if(num_right == 3) right_mesh_num_vertex += 3;
  130. else if(num_right == 4) {
  131. right[4] = right[0];
  132. right[5] = right[2];
  133. right_mesh_num_vertex += 6;
  134. }
  135. }
  136. if(left_mesh_num_vertex > 0) left_mesh->addSurface(mesh->getSurfaceName(i),left_mesh_vertex,left_mesh_num_vertex);
  137. if(right_mesh_num_vertex > 0) right_mesh->addSurface(mesh->getSurfaceName(i),right_mesh_vertex,right_mesh_num_vertex);
  138. delete right_mesh_vertex;
  139. delete left_mesh_vertex;
  140. }
  141. int left_mesh_num_vertex = 0;
  142. for(int i = 0; i < left_mesh->getNumSurfaces(); i++) left_mesh_num_vertex += left_mesh->getNumVertex(i);
  143. int right_mesh_num_vertex = 0;
  144. for(int i = 0; i < right_mesh->getNumSurfaces(); i++) right_mesh_num_vertex += right_mesh->getNumVertex(i);
  145. if(left_mesh_num_vertex > 0 && right_mesh_num_vertex > 0) {
  146. left_mesh->calculate_bounds();
  147. left = new Node();
  148. left->create(left_mesh);
  149. right_mesh->calculate_bounds();
  150. right = new Node();
  151. right->create(right_mesh);
  152. } else {
  153. mesh->create_shadow_volumes();
  154. mesh->create_triangle_strips();
  155. object = new ObjectMesh(new MeshVBO(mesh));
  156. delete right_mesh;
  157. delete left_mesh;
  158. }
  159. } else {
  160. mesh->create_shadow_volumes();
  161. mesh->create_triangle_strips();
  162. object = new ObjectMesh(new MeshVBO(mesh));
  163. }
  164. delete mesh;
  165. }
  166. /*
  167.  */
  168. void Node::load(FILE *file) {
  169. int header;
  170. fread(&header,sizeof(int),1,file);
  171. if(header == 0x7fffffff) {
  172. fread(&min,sizeof(vec3),1,file);
  173. fread(&max,sizeof(vec3),1,file);
  174. fread(&center,sizeof(vec3),1,file);
  175. fread(&radius,sizeof(float),1,file);
  176. left = new Node();
  177. left->load(file);
  178. right = new Node();
  179. right->load(file);
  180. } else {
  181. fseek(file,-sizeof(int),SEEK_CUR);
  182. Mesh *mesh = new Mesh();
  183. mesh->load(file);
  184. min = mesh->getMin();
  185. max = mesh->getMax();
  186. center = mesh->getCenter();
  187. radius = mesh->getRadius();
  188. object = new ObjectMesh(new MeshVBO(mesh));
  189. delete mesh;
  190. }
  191. }
  192. /*
  193.  */
  194. void Node::save(FILE *file) {
  195. if(left && right) {
  196. int header = 0x7fffffff;
  197. fwrite(&header,sizeof(int),1,file);
  198. fwrite(&min,sizeof(vec3),1,file);
  199. fwrite(&max,sizeof(vec3),1,file);
  200. fwrite(&center,sizeof(vec3),1,file);
  201. fwrite(&radius,sizeof(float),1,file);
  202. left->save(file);
  203. right->save(file);
  204. } else {
  205. object->mesh->save(file);
  206. }
  207. }
  208. /*
  209.  */
  210. void Node::bindMaterial(const char *name,Material *material) {
  211. if(left) left->bindMaterial(name,material);
  212. if(right) right->bindMaterial(name,material);
  213. if(object) object->bindMaterial(name,material);
  214. }
  215. /*
  216.  */
  217. void Node::render() {
  218. if(left && right) {
  219. int check_left = Engine::frustum->inside(left->center,left->radius);
  220. int check_right = Engine::frustum->inside(right->center,right->radius);
  221. if(check_left && check_right) {
  222. if((left->center - Engine::camera).length() < (right->center - Engine::camera).length()) {
  223. left->render();
  224. right->render();
  225. } else {
  226. right->render();
  227. left->render();
  228. }
  229. return;
  230. }
  231. if(check_left) left->render();
  232. else if(check_right) right->render();
  233. return;
  234. }
  235. if(object && object->frame != Engine::frame) {
  236. Sector *s = Bsp::visible_sectors[Bsp::num_visible_sectors - 1];
  237. s->visible_objects[s->num_visible_objects++] = object;
  238. Engine::num_triangles += object->render(Object::RENDER_OPACITY);
  239. }
  240. }
  241. /*****************************************************************************/
  242. /*                                                                           */
  243. /* Portal                                                                    */
  244. /*                                                                           */
  245. /*****************************************************************************/
  246. Portal::Portal() : center(0,0,0), radius(1000000.0), num_sectors(0), sectors(NULL), frame(0) {
  247. }
  248. Portal::~Portal() {
  249. if(sectors) delete sectors;
  250. }
  251. /*
  252.  */
  253. void Portal::create(Mesh *mesh,int s) {
  254. center = mesh->getCenter(s);
  255. radius = mesh->getRadius(s);
  256. int num_vertex = mesh->getNumVertex(s);
  257. if(num_vertex != 6) {
  258. fprintf(stderr,"Portal::create(): portal mesh must have only two trianglen");
  259. return;
  260. }
  261. Mesh::Vertex *v = mesh->getVertex(s);
  262. int flag[6]; // create quad from the six vertexes
  263. for(int i = 0; i < 6; i++) {
  264. flag[i] = 0;
  265. for(int j = 0; j < 6; j++) {
  266. if(i == j) continue;
  267. if(v[i].xyz == v[j].xyz) flag[i] = 1;
  268. }
  269. }
  270. for(int i = 0, j = 0; i < 6; i++) {
  271. if(flag[i] == 0) points[j++] = v[i].xyz;
  272. if(i == 5 && j != 2) {
  273. fprintf(stderr,"Portal::create(): can`t find two similar vertexes for create quadn");
  274. return;
  275. }
  276. }
  277. points[2] = points[1];
  278. for(int i = 0, j = 1; i < 3; i++) {
  279. if(flag[i] != 0) {
  280. points[j] = v[i].xyz;
  281. j += 2;
  282. }
  283. }
  284. }
  285. void Portal::getScissor(int *scissor) {
  286. if((center - Engine::camera).length() < radius) {
  287. scissor[0] = Engine::viewport[0];
  288. scissor[1] = Engine::viewport[1];
  289. scissor[2] = Engine::viewport[2];
  290. scissor[3] = Engine::viewport[3];
  291. return;
  292. }
  293. mat4 mvp = Engine::projection * Engine::modelview;
  294. vec4 p[4];
  295. p[0] = mvp * vec4(points[0],1);
  296. p[1] = mvp * vec4(points[1],1);
  297. p[2] = mvp * vec4(points[2],1);
  298. p[3] = mvp * vec4(points[3],1);
  299. p[0] /= p[0].w;
  300. p[1] /= p[1].w;
  301. p[2] /= p[2].w;
  302. p[3] /= p[3].w;
  303. vec3 min = vec3(1000000,1000000,1000000);
  304. vec3 max = vec3(-1000000,-1000000,-1000000);
  305. for(int i = 0; i < 4; i++) {
  306. if(min.x > p[i].x) min.x = p[i].x;
  307. if(max.x < p[i].x) max.x = p[i].x;
  308. if(min.y > p[i].y) min.y = p[i].y;
  309. if(max.y < p[i].y) max.y = p[i].y;
  310. }
  311. scissor[0] = Engine::viewport[0] + (int)((float)Engine::viewport[2] * (min.x + 1.0) / 2.0) - 4; // remove it
  312. scissor[1] = Engine::viewport[1] + (int)((float)Engine::viewport[3] * (min.y + 1.0) / 2.0) - 4;
  313. scissor[2] = Engine::viewport[0] + (int)((float)Engine::viewport[2] * (max.x + 1.0) / 2.0) + 4;
  314. scissor[3] = Engine::viewport[1] + (int)((float)Engine::viewport[3] * (max.y + 1.0) / 2.0) + 4;
  315. if(scissor[0] < Engine::viewport[0]) scissor[0] = Engine::viewport[0];
  316. else if(scissor[0] > Engine::viewport[0] + Engine::viewport[2]) scissor[0] = Engine::viewport[0] + Engine::viewport[2];
  317. if(scissor[1] < Engine::viewport[1]) scissor[1] = Engine::viewport[1];
  318. else if(scissor[1] > Engine::viewport[1] + Engine::viewport[3]) scissor[1] = Engine::viewport[1] + Engine::viewport[3];
  319. if(scissor[2] < Engine::viewport[0]) scissor[2] = Engine::viewport[0];
  320. else if(scissor[2] > Engine::viewport[2] + Engine::viewport[3]) scissor[2] = Engine::viewport[0] + Engine::viewport[2];
  321. if(scissor[3] < Engine::viewport[1]) scissor[3] = Engine::viewport[1];
  322. else if(scissor[3] > Engine::viewport[1] + Engine::viewport[3]) scissor[3] = Engine::viewport[1] + Engine::viewport[3];
  323. scissor[2] -= scissor[0];
  324. scissor[3] -= scissor[1];
  325. }
  326. /*
  327.  */
  328. void Portal::render() {
  329. glBegin(GL_QUADS);
  330. glVertex3fv(points[0]);
  331. glVertex3fv(points[1]);
  332. glVertex3fv(points[2]);
  333. glVertex3fv(points[3]);
  334. glEnd();
  335. }
  336. /*****************************************************************************/
  337. /*                                                                           */
  338. /* Sector                                                                    */
  339. /*                                                                           */
  340. /*****************************************************************************/
  341. Sector::Sector() : center(0,0,0), radius(1000000.0), num_planes(0), planes(NULL), root(NULL),
  342. num_portals(0), portals(NULL), num_objects(0), objects(NULL), num_node_objects(0), node_objects(NULL),
  343. num_visible_objects(0), visible_objects(NULL), portal(NULL), frame(0),
  344. old_num_visible_objects(0), old_visible_objects(NULL), old_portal(NULL), old_frame(0) {
  345. }
  346. Sector::~Sector() {
  347. if(portals) delete portals;
  348. if(planes) delete planes;
  349. if(root) delete root;
  350. if(objects) delete objects;
  351. if(node_objects) delete node_objects;
  352. if(visible_objects) delete visible_objects;
  353. if(old_visible_objects) delete old_visible_objects;
  354. }
  355. /*
  356.  */
  357. void Sector::create(Mesh *mesh,int s) {
  358. center = mesh->getCenter(s);
  359. radius = mesh->getRadius(s);
  360. num_planes = mesh->getNumVertex(s) / 3;
  361. planes = new vec4[num_planes];
  362. Mesh::Vertex *v = mesh->getVertex(s);
  363. for(int i = 0; i < num_planes; i++) {
  364. vec3 normal;
  365. normal.cross(v[i * 3 + 1].xyz - v[i * 3 + 0].xyz,v[i * 3 + 2].xyz - v[i * 3 + 0].xyz);
  366. normal.normalize();
  367. planes[i] = vec4(normal,-normal * v[i * 3 + 0].xyz);
  368. }
  369. }
  370. /* get all objects from the tree
  371.  */
  372. void Sector::getNodeObjects(Node *node) {
  373. if(node->left && node->right) {
  374. getNodeObjects(node->left);
  375. getNodeObjects(node->right);
  376. }
  377. if(node->object) {
  378. if(node_objects) node_objects[num_node_objects] = node->object;
  379. num_node_objects++;
  380. }
  381. }
  382. /*
  383.  */
  384. void Sector::create() {
  385. objects = new Object*[NUM_OBJECTS];
  386. num_node_objects = 0;
  387. getNodeObjects(root);
  388. node_objects = new Object*[num_node_objects];
  389. visible_objects = new Object*[num_node_objects + NUM_OBJECTS];
  390. old_visible_objects = new Object*[num_node_objects + NUM_OBJECTS];
  391. num_node_objects = 0;
  392. getNodeObjects(root);
  393. }
  394. /*
  395.  */
  396. int Sector::inside(const vec3 &point) {
  397. for(int i = 0; i < num_planes; i++) {
  398. if(planes[i] * vec4(point,1) > 0.0) return 0;
  399. }
  400. return 1;
  401. }
  402. int Sector::inside(Portal *portal) {
  403. if(inside(portal->points[0]) == 0) return 0;
  404. if(inside(portal->points[1]) == 0) return 0;
  405. if(inside(portal->points[2]) == 0) return 0;
  406. if(inside(portal->points[3]) == 0) return 0;
  407. return 1;
  408. }
  409. int Sector::inside(const vec3 &center,float radius) {
  410. for(int i = 0; i < num_planes; i++) {
  411. if(planes[i] * vec4(center,1) > radius) return 0;
  412. }
  413. return 1;
  414. }
  415. int Sector::inside(Mesh *mesh,int s) {
  416. Mesh::Vertex *v = mesh->getVertex(s);
  417. for(int i = 0; i < mesh->getNumVertex(s); i++) {
  418. if(inside(v[i].xyz) == 0) return 0;
  419. }
  420. return 1;
  421. }
  422. /*
  423.  */
  424. void Sector::addObject(Object *object) {
  425. if(!objects) return;
  426. int i = 0;
  427. for(; i < num_objects; i++) if(objects[i] == object) return;
  428. objects[num_objects++] = object;
  429. }
  430. /*
  431.  */
  432. void Sector::removeObject(Object *object) {
  433. for(int i = 0; i < num_objects; i++) {
  434. if(objects[i] == object) {
  435. num_objects--;
  436. for(; i < num_objects; i++) objects[i] = objects[i + 1];
  437. return;
  438. }
  439. }
  440. }
  441. /*
  442.  */
  443. void Sector::bindMaterial(const char *name,Material *material) {
  444. root->bindMaterial(name,material);
  445. }
  446. /*
  447.  */
  448. void Sector::render(Portal *portal) {
  449. if(frame == Engine::frame) return;
  450. frame = Engine::frame;
  451. this->portal = portal;
  452. Bsp::visible_sectors[Bsp::num_visible_sectors++] = this;
  453. num_visible_objects = 0;
  454. root->render();
  455. for(int i = 0; i < num_objects; i++) {
  456. Object *o = objects[i];
  457. if(o->frame == Engine::frame) continue;
  458. if(Engine::frustum->inside(o->pos + o->getCenter(),o->getRadius())) {
  459. Engine::num_triangles += o->render(Object::RENDER_OPACITY);
  460. visible_objects[num_visible_objects++] = o;
  461. }
  462. }
  463. for(int i = 0; i < num_portals; i++) {
  464. Portal *p = &Bsp::portals[portals[i]];
  465. if(p->frame == Engine::frame) continue;
  466. p->frame = Engine::frame;
  467. if(Engine::frustum->inside(p->center,p->radius)) {
  468. float dist = (Engine::camera - p->center).length();
  469. if(Engine::have_occlusion && dist > p->radius) {
  470. if(Material::old_material) Material::old_material->disable();
  471. glDisable(GL_CULL_FACE);
  472. glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
  473. glDepthMask(GL_FALSE);
  474. glBeginQueryARB(GL_SAMPLES_PASSED_ARB,Engine::query_id);
  475. p->render();
  476. glEndQueryARB(GL_SAMPLES_PASSED_ARB);
  477. glDepthMask(GL_TRUE);
  478. glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
  479. glEnable(GL_CULL_FACE);
  480. GLuint samples;
  481. glGetQueryObjectuivARB(Engine::query_id,GL_QUERY_RESULT_ARB,&samples);
  482. if(samples == 0) continue;
  483. }
  484. if(dist > p->radius) Engine::frustum->addPortal(Engine::camera,p->points);
  485. for(int j = 0; j < p->num_sectors; j++) {
  486. Bsp::sectors[p->sectors[j]].render(dist > p->radius ? p : NULL);
  487. }
  488. if(dist > p->radius) Engine::frustum->removePortal();
  489. }
  490. }
  491. }
  492. /*
  493.  */
  494. void Sector::saveState() {
  495. old_num_visible_objects = num_visible_objects;
  496. for(int i = 0; i < num_visible_objects; i++) {
  497. old_visible_objects[i] = visible_objects[i];
  498. }
  499. old_portal = portal;
  500. old_frame = frame;
  501. }
  502. void Sector::restoreState(int frame) {
  503. num_visible_objects = old_num_visible_objects;
  504. for(int i = 0; i < num_visible_objects; i++) {
  505. visible_objects[i] = old_visible_objects[i];
  506. }
  507. portal = old_portal;
  508. this->frame = frame;
  509. }
  510. /*****************************************************************************/
  511. /*                                                                           */
  512. /* Bsp                                                                       */
  513. /*                                                                           */
  514. /*****************************************************************************/
  515. int Bsp::num_portals;
  516. Portal *Bsp::portals;
  517. int Bsp::num_sectors;
  518. Sector *Bsp::sectors;
  519. int Bsp::num_visible_sectors;
  520. Sector **Bsp::visible_sectors;
  521. int Bsp::old_num_visible_sectors;
  522. Sector **Bsp::old_visible_sectors;
  523. Bsp::Bsp() {
  524. num_portals = 0;
  525. portals = NULL;
  526. num_sectors = 0;
  527. sectors = NULL;
  528. num_visible_sectors = 0;
  529. visible_sectors = NULL;
  530. old_num_visible_sectors = 0;
  531. old_visible_sectors = NULL;
  532. }
  533. Bsp::~Bsp() {
  534. if(num_portals) delete [] portals;
  535. num_portals = 0;
  536. portals = NULL;
  537. if(num_sectors) delete [] sectors;
  538. num_sectors = 0;
  539. sectors = NULL;
  540. if(visible_sectors) delete visible_sectors;
  541. num_visible_sectors = 0;
  542. visible_sectors = NULL;
  543. if(old_visible_sectors) delete old_visible_sectors;
  544. old_num_visible_sectors = 0;
  545. old_visible_sectors = NULL;
  546. }
  547. /*****************************************************************************/
  548. /*                                                                           */
  549. /* Bsp IO                                                                    */
  550. /*                                                                           */
  551. /*****************************************************************************/
  552. /*
  553.  */
  554. void Bsp::load(const char *name) {
  555. if(strstr(name,".bsp")) { // read own binary bsp format
  556. FILE *file = fopen(name,"rb");
  557. if(!file) {
  558. fprintf(stderr,"Bsp::load(): error open "%s" filen",name);
  559. return;
  560. }
  561. int magic;
  562. fread(&magic,sizeof(int),1,file);
  563. if(magic != BSP_MAGIC) {
  564. fprintf(stderr,"Bsp::load(): wrong magic in "%s" filen",name);
  565. fclose(file);
  566. return;
  567. }
  568. fread(&num_portals,sizeof(int),1,file);
  569. portals = new Portal[num_portals];
  570. for(int i = 0; i < num_portals; i++) {
  571. Portal *p = &portals[i];
  572. fread(&p->center,sizeof(vec3),1,file);
  573. fread(&p->radius,sizeof(float),1,file);
  574. fread(&p->num_sectors,sizeof(int),1,file);
  575. p->sectors = new int[p->num_sectors];
  576. fread(p->sectors,sizeof(int),p->num_sectors,file);
  577. fread(p->points,sizeof(vec3),4,file);
  578. }
  579. fread(&num_sectors,sizeof(int),1,file);
  580. sectors = new Sector[num_sectors];
  581. for(int i = 0; i < num_sectors; i++) {
  582. Sector *s = &sectors[i];
  583. fread(&s->center,sizeof(vec3),1,file);
  584. fread(&s->radius,sizeof(float),1,file);
  585. fread(&s->num_portals,sizeof(int),1,file);
  586. s->portals = new int[s->num_portals];
  587. fread(s->portals,sizeof(int),s->num_portals,file);
  588. fread(&s->num_planes,sizeof(int),1,file);
  589. s->planes = new vec4[s->num_planes];
  590. fread(s->planes,sizeof(vec4),s->num_planes,file);
  591. s->root = new Node();
  592. s->root->load(file);
  593. s->create();
  594. }
  595. fclose(file);
  596. visible_sectors = new Sector*[num_sectors];
  597. old_visible_sectors = new Sector*[num_sectors];
  598. Engine::console->printf("sectors %dnportals %dn",num_sectors,num_portals);
  599. return;
  600. }
  601. // else generate bsp tree with portals and sectors
  602. Mesh *mesh = new Mesh();
  603. if(strstr(name,".3ds")) mesh->load_3ds(name);
  604. else if(strstr(name,".mesh")) mesh->load_mesh(name);
  605. mesh->calculate_bounds();
  606. mesh->calculate_tangent();
  607. for(int i = 0; i < mesh->getNumSurfaces(); i++) {
  608. const char *name = mesh->getSurfaceName(i);
  609. if(!strncmp(name,"portal",6)) num_portals++;
  610. else if(!strncmp(name,"sector",6)) num_sectors++;
  611. }
  612. if(num_portals == 0 || num_sectors == 0) {
  613. num_sectors = 1;
  614. sectors = new Sector[1];
  615. sectors[0].root = new Node();
  616. sectors[0].root->create(mesh);
  617. sectors[0].create();
  618. } else {
  619. portals = new Portal[num_portals];
  620. sectors = new Sector[num_sectors];
  621. int *usage_flag = new int[mesh->getNumSurfaces()];
  622. num_portals = 0;
  623. num_sectors = 0;
  624. for(int i = 0; i < mesh->getNumSurfaces(); i++) {
  625. const char *name = mesh->getSurfaceName(i);
  626. if(!strncmp(name,"portal",6)) {
  627. portals[num_portals++].create(mesh,i);
  628. usage_flag[i] = 1;
  629. } else if(!strncmp(name,"sector",6)) {
  630. sectors[num_sectors++].create(mesh,i);
  631. usage_flag[i] = 1;
  632. } else usage_flag[i] = 0;
  633. }
  634. for(int i = 0; i < num_portals; i++) portals[i].sectors = new int[num_sectors];
  635. for(int i = 0; i < num_sectors; i++) sectors[i].portals = new int[num_portals];
  636. for(int i = 0; i < num_sectors; i++) {
  637. Sector *s = &sectors[i];
  638. for(int j = 0; j < num_portals; j++) {
  639. Portal *p = &portals[j];
  640. if(s->inside(p)) {
  641. p->sectors[p->num_sectors++] = i;
  642. s->portals[s->num_portals++] = j;
  643. }
  644. }
  645. }
  646. for(int i = 0; i < num_sectors; i++) {
  647. Sector *s = &sectors[i];
  648. Mesh *m = new Mesh();
  649. for(int j = 0; j < mesh->getNumSurfaces(); j++) {
  650. if(usage_flag[j]) continue;
  651. if(s->inside(mesh,j)) {
  652. m->addSurface(mesh,j);
  653. usage_flag[j] = 1;
  654. }
  655. }
  656. s->root = new Node();
  657. s->root->create(m);
  658. s->create();
  659. }
  660. delete usage_flag;
  661. delete mesh;
  662. }
  663. visible_sectors = new Sector*[num_sectors];
  664. old_visible_sectors = new Sector*[num_sectors];
  665. Engine::console->printf("sectors %dnportals %dn",num_sectors,num_portals);
  666. }
  667. /*
  668.  */
  669. void Bsp::save(const char *name) {
  670. FILE *file = fopen(name,"wb");
  671. if(!file) {
  672. fprintf(stderr,"Bsp::save(): can`t create "%s" filen",name);
  673. return;
  674. }
  675. int magic = BSP_MAGIC;
  676. fwrite(&magic,sizeof(int),1,file);
  677. fwrite(&num_portals,sizeof(int),1,file);
  678. for(int i = 0; i < num_portals; i++) {
  679. Portal *p = &portals[i];
  680. fwrite(&p->center,sizeof(vec3),1,file);
  681. fwrite(&p->radius,sizeof(float),1,file);
  682. fwrite(&p->num_sectors,sizeof(int),1,file);
  683. fwrite(p->sectors,sizeof(int),p->num_sectors,file);
  684. fwrite(p->points,sizeof(vec3),4,file);
  685. }
  686. fwrite(&num_sectors,sizeof(int),1,file);
  687. for(int i = 0; i < num_sectors; i++) {
  688. Sector *s = &sectors[i];
  689. fwrite(&s->center,sizeof(vec3),1,file);
  690. fwrite(&s->radius,sizeof(float),1,file);
  691. fwrite(&s->num_portals,sizeof(int),1,file);
  692. fwrite(s->portals,sizeof(int),s->num_portals,file);
  693. fwrite(&s->num_planes,sizeof(int),1,file);
  694. fwrite(s->planes,sizeof(vec4),s->num_planes,file);
  695. s->root->save(file);
  696. }
  697. fclose(file);
  698. }
  699. /*****************************************************************************/
  700. /*                                                                           */
  701. /* Bsp Render                                                                */
  702. /*                                                                           */
  703. /*****************************************************************************/
  704. /*
  705.  */
  706. void Bsp::bindMaterial(const char *name,Material *material) {
  707. for(int i = 0; i < num_sectors; i++) sectors[i].bindMaterial(name,material);
  708. }
  709. /*
  710.  */
  711. void Bsp::render() {
  712. num_visible_sectors = 0;
  713. if(Engine::camera.sector != -1) {
  714. sectors[Engine::camera.sector].render();
  715. } else {
  716. int sector = -1;
  717. float dist = 1000000.0;
  718. for(int i = 0; i < num_sectors; i++) {
  719. float d = (sectors[i].center - Engine::camera).length();
  720. if(d < dist) {
  721. dist = d;
  722. sector = i;
  723. }
  724. }
  725. if(sector != -1) sectors[sector].render();
  726. }
  727. }
  728. /*
  729.  */
  730. void Bsp::saveState() {
  731. old_num_visible_sectors = num_visible_sectors;
  732. for(int i = 0; i < num_visible_sectors; i++) {
  733. old_visible_sectors[i] = visible_sectors[i];
  734. old_visible_sectors[i]->saveState();
  735. }
  736. }
  737. void Bsp::restoreState(int frame) {
  738. num_visible_sectors = old_num_visible_sectors;
  739. for(int i = 0; i < num_visible_sectors; i++) {
  740. visible_sectors[i] = old_visible_sectors[i];
  741. visible_sectors[i]->restoreState(frame);
  742. }
  743. }