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

游戏引擎

开发平台:

Visual C++

  1. /* Map
  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 "parser.h"
  20. #include "light.h"
  21. #include "fog.h"
  22. #include "mirror.h"
  23. #include "mesh.h"
  24. #include "objectmesh.h"
  25. #include "rigidbody.h"
  26. #include "particles.h"
  27. #include "objectparticles.h"
  28. #include "engine.h"
  29. #include "console.h"
  30. #include "map.h"
  31. char *Map::data;
  32. /*
  33.  */
  34. void Map::load(const char *name) {
  35. Parser *parser = new Parser(name);
  36. char file_name[1024];
  37. strcpy(file_name,name);
  38. if(parser->get("path")) {
  39. char *s = parser->get("path");
  40. char path[1024];
  41. char *d = path;
  42. while(*s) {
  43. if(!strchr(" tnr",*s)) *d++ = *s;
  44. s++;
  45. }
  46. *d = '';
  47. Engine::addPath(path);
  48. }
  49. char *data_block = (char*)Parser::interpret(parser->get("data"));
  50. if(!data_block) {
  51. fprintf(stderr,"Map::load(): can`t get data block in "%s" filen",file_name);
  52. delete parser;
  53. return;
  54. }
  55. data = data_block;
  56. try {
  57. while(*data) {
  58. const char *token = read_token();
  59. if(!token || !*token) break;
  60. else if(!strcmp(token,"bsp")) load_bsp();
  61. else if(!strcmp(token,"light")) load_light();
  62. else if(!strcmp(token,"fog")) load_fog();
  63. else if(!strcmp(token,"mirror")) load_mirror();
  64. else if(!strcmp(token,"mesh")) load_mesh();
  65. else if(!strcmp(token,"particles")) load_particles();
  66. else throw(error("unknown token "%s"",token));
  67. }
  68. }
  69. catch(const char *msg) {
  70. fprintf(stderr,"Map::load(): %s in "%s" filen",msg,file_name);
  71. delete data_block;
  72. delete parser;
  73. return;
  74. }
  75. delete data_block;
  76. delete parser;
  77. }
  78. /*****************************************************************************/
  79. /*                                                                           */
  80. /*                                                                           */
  81. /*                                                                           */
  82. /*****************************************************************************/
  83. /*
  84.  */
  85. const char *Map::error(const char *error,...) {
  86. static char buf[1024];
  87. va_list arg;
  88. va_start(arg,error);
  89. vsprintf(buf,error,arg);
  90. va_end(arg);
  91. return buf;
  92. }
  93. /*
  94.  */
  95. const char *Map::read_token(char *must) {
  96. if(!*data) return NULL;
  97. while(*data && strchr(" tnr",*data)) data++;
  98. char *token = data;
  99. char *s = token;
  100. while(*data && !strchr(" tnr",*data)) *s++ = *data++;
  101. if(*data) data++;
  102. *s = '';
  103. if(must) if(strcmp(token,must)) throw("unknown token");
  104. return token;
  105. }
  106. int Map::read_bool() {
  107. const char *token = read_token();
  108. if(token) {
  109. if(!strcmp(token,"false") || !strcmp(token,"0")) return 0;
  110. if(!strcmp(token,"true") || !strcmp(token,"1")) return 1;
  111. throw(error("unknown token "%s" in read_bool",token));
  112. return 1;
  113. }
  114. return 0;
  115. }
  116. int Map::read_int() {
  117. const char *token = read_token();
  118. if(token) {
  119. if(!strchr("-01234567890",*token)) throw(error("unknown token "%s" in read_int",token));
  120. return atoi(token);
  121. }
  122. return 0;
  123. }
  124. float Map::read_float() {
  125. const char *token = read_token();
  126. if(token) {
  127. if(!strchr("-01234567890.",*token)) throw(error("unknown token "%s" in read_float",token));
  128. return atof(token);
  129. }
  130. return 0.0;
  131. }
  132. vec3 Map::read_vec3() {
  133. vec3 ret;
  134. ret.x = read_float();
  135. ret.y = read_float();
  136. ret.z = read_float();
  137. return ret;
  138. }
  139. vec4 Map::read_vec4() {
  140. vec4 ret;
  141. ret.x = read_float();
  142. ret.y = read_float();
  143. ret.z = read_float();
  144. ret.w = read_float();
  145. return ret;
  146. }
  147. const char *Map::read_string() {
  148. if(!*data) return NULL;
  149. while(*data && strchr(" tnr",*data)) data++;
  150. char *str = data;
  151. char *s = str;
  152. if(*str == '"') {
  153. while(*data && !strchr(" "",*data)) *s++ = *data++;
  154. if(*data) data++;
  155. *s = '';
  156. return str + 1;
  157. }
  158. while(*data && !strchr(" tnr",*data)) *s++ = *data++;
  159. if(*data) data++;
  160. *s = '';
  161. return str;
  162. }
  163. /*****************************************************************************/
  164. /*                                                                           */
  165. /*                                                                           */
  166. /*                                                                           */
  167. /*****************************************************************************/
  168. /*
  169.  */
  170. void Map::load_bsp() {
  171. read_token("{");
  172. Engine::bsp = new Bsp();
  173. while(1) {
  174. const char *token = read_token();
  175. if(!token || !strcmp(token,"}")) break;
  176. else if(!strcmp(token,"mesh")) Engine::bsp->load(Engine::findFile(read_string()));
  177. else if(!strcmp(token,"save")) Engine::bsp->save(read_string());
  178. else if(!strcmp(token,"material")) {
  179. const char *name = read_string();
  180. Engine::bsp->bindMaterial(name,Engine::loadMaterial(read_string()));
  181. }
  182. else throw(error("unknown token "%s" in bsp block",token));
  183. }
  184. }
  185. /*
  186.  */
  187. void Map::load_pos(Position &pos,mat4 &matrix) {
  188. read_token("{");
  189. const char *token = read_token();
  190. if(!strcmp(token,"spline")) {
  191. read_token("{");
  192. char name[1024];
  193. int close = 0;
  194. int follow = 0;
  195. float speed = 1;
  196. while(1) {
  197. const char *token = read_token();
  198. if(!token || !strcmp(token,"}")) break;
  199. else if(!strcmp(token,"path")) strcpy(name,read_string());
  200. else if(!strcmp(token,"speed")) speed = read_float();
  201. else if(!strcmp(token,"close")) close = read_bool();
  202. else if(!strcmp(token,"follow")) follow = read_bool();
  203. else throw(error("unknown token "%s" in spline block",token));
  204. }
  205. Spline *spline = new Spline(Engine::findFile(name),speed,close,follow);
  206. pos.setSpline(spline);
  207. matrix = spline->to_matrix(0.0);
  208. read_token("}");
  209. } else if(!strcmp(token,"exp")) {
  210. read_token("{");
  211. char str[1024];
  212. char *d = str;
  213. if(!*data) return;
  214. while(*data && *data != '}') *d++ = *data++;
  215. if(*data) data++;
  216. *d = '';
  217. Expression *expression = new Expression(str);
  218. pos.setExpression(expression);
  219. matrix = expression->to_matrix(0.0);
  220. read_token("}");
  221. } else {
  222. float m[16];
  223. m[0] = atof(token);
  224. m[1] = read_float();
  225. m[2] = read_float();
  226. const char *token = read_token();
  227. if(!strcmp(token,"}")) {
  228. matrix.translate(vec3(m[0],m[1],m[2]));
  229. } else {
  230. m[3] = atof(token);
  231. m[4] = read_float();
  232. m[5] = read_float();
  233. m[6] = read_float();
  234. const char *token = read_token();
  235. if(!strcmp(token,"}")) {
  236. quat rot(m[3],m[4],m[5],m[6]);
  237. mat4 translate;
  238. translate.translate(vec3(m[0],m[1],m[2]));
  239. matrix = translate * rot.to_matrix();
  240. } else {
  241. m[7] = atof(token);
  242. for(int i = 8; i < 16; i++) m[i] = read_float();
  243. matrix = mat4(m);
  244. read_token("}");
  245. }
  246. }
  247. pos = matrix * vec3(0,0,0);
  248. }
  249. }
  250. /*
  251.  */
  252. void Map::load_light() {
  253. read_token("{");
  254. Position pos;
  255. mat4 matrix;
  256. float radius = 0.0;
  257. vec4 color(1.0,1.0,1.0,1.0);
  258. int shadows = 1;
  259. Material *material = NULL;
  260. while(1) {
  261. const char *token = read_token();
  262. if(!token || !strcmp(token,"}")) break;
  263. else if(!strcmp(token,"pos")) load_pos(pos,matrix);
  264. else if(!strcmp(token,"radius")) radius = read_float();
  265. else if(!strcmp(token,"color")) color = read_vec4();
  266. else if(!strcmp(token,"shadows")) shadows = read_bool();
  267. else if(!strcmp(token,"material")) {
  268. read_string();
  269. material = Engine::loadMaterial(read_string());
  270. }
  271. else throw(error("unknown token "%s" in light block",token));
  272. }
  273. Light *light = new Light(vec3(0,0,0),radius,color,shadows);
  274. if(material) light->bindMaterial("*",material);
  275. light->pos = pos;
  276. light->pos.radius = radius;
  277. light->set(matrix);
  278. Engine::addLight(light);
  279. }
  280. /*
  281.  */
  282. void Map::load_fog() {
  283. read_token("{");
  284. Mesh *mesh = NULL;
  285. vec4 color(1.0,1.0,1.0,1.0);
  286. while(1) {
  287. const char *token = read_token();
  288. if(!token || !strcmp(token,"}")) break;
  289. else if(!strcmp(token,"mesh")) mesh = Engine::loadMesh(read_string());
  290. else if(!strcmp(token,"color")) color = read_vec4();
  291. else throw(error("unknown token "%s" in fog block",token));
  292. }
  293. if(mesh) Engine::addFog(new Fog(mesh,color));
  294. else fprintf(stderr,"Map::load_fog(): can`t find meshn");
  295. }
  296. /*
  297.  */
  298. void Map::load_mirror() {
  299. read_token("{");
  300. Mirror *mirror = NULL;
  301. while(1) {
  302. const char *token = read_token();
  303. if(!token || !strcmp(token,"}")) break;
  304. else if(!strcmp(token,"mesh")) mirror = new Mirror(Engine::loadMesh(read_string()));
  305. else if(mirror && !strcmp(token,"material")) {
  306. const char *name = read_string();
  307. mirror->bindMaterial(name,Engine::loadMaterial(read_string()));
  308. }
  309. else throw(error("unknown token "%s" in mirror block",token));
  310. }
  311. if(mirror) Engine::addMirror(mirror);
  312. else fprintf(stderr,"Map::load_mirror(): can`t find meshn");
  313. }
  314. /*
  315.  */
  316. void Map::load_mesh() {
  317. read_token("{");
  318. ObjectMesh *mesh = NULL;
  319. int shadows = 1;
  320. while(1) {
  321. const char *token = read_token();
  322. if(!token || !strcmp(token,"}")) break;
  323. else if(!strcmp(token,"mesh")) mesh = new ObjectMesh(read_string());
  324. else if(!strcmp(token,"shadows")) shadows = read_bool();
  325. else if(mesh && !strcmp(token,"material")) {
  326. const char *name = read_string();
  327. mesh->bindMaterial(name,Engine::loadMaterial(read_string()));
  328. }
  329. else if(mesh && !strcmp(token,"pos")) {
  330. mat4 matrix;
  331. load_pos(mesh->pos,matrix);
  332. mesh->set(matrix);
  333. }
  334. else if(mesh && !strcmp(token,"rigidbody")) {
  335. read_token("{");
  336. mat4 matrix;
  337. float mass = 0;
  338. float restitution = 0;
  339. float friction = 0;
  340. int flag = 0;
  341. while(1) {
  342. const char *token = read_token();
  343. if(!token || !strcmp(token,"}")) break;
  344. else if(!strcmp(token,"pos")) load_pos(mesh->pos,matrix);
  345. else if(!strcmp(token,"mass")) mass = read_float();
  346. else if(!strcmp(token,"restitution")) friction = read_float();
  347. else if(!strcmp(token,"friction")) friction = read_float();
  348. else if(!strcmp(token,"collide")) {
  349. const char *collide = read_string();
  350. if(!strcmp(collide,"mesh")) flag |= RigidBody::COLLIDE_MESH;
  351. else if(!strcmp(collide,"sphere")) flag |= RigidBody::COLLIDE_SPHERE;
  352. else throw(error("unknown collide "%s" in rigidbody block",collide));
  353. } else if(!strcmp(token,"body")) {
  354. const char *body = read_string();
  355. if(!strcmp(body,"box")) flag |= RigidBody::BODY_BOX;
  356. else if(!strcmp(body,"sphere")) flag |= RigidBody::BODY_SPHERE;
  357. else if(!strcmp(body,"cylinder")) flag |= RigidBody::BODY_CYLINDER;
  358. else throw(error("unknown body "%s" in rigidbody block",body));
  359. } else throw(error("unknown token "%s" in rigidbody block",token));
  360. }
  361. mesh->setRigidBody(new RigidBody(mesh,mass,restitution,friction,flag));
  362. mesh->set(matrix);
  363. }
  364. else throw(error("unknown token "%s" in mesh block",token));
  365. }
  366. if(mesh) {
  367. mesh->setShadows(shadows);
  368. Engine::addObject(mesh);
  369. }
  370. else fprintf(stderr,"Map::load_mesh(): can`t find meshn");
  371. }
  372. /*
  373.  */
  374. void Map::load_particles() {
  375. read_token("{");
  376. Position pos;
  377. mat4 matrix;
  378. int num = 0;
  379. float speed = 0.0;
  380. float rotation = 0.0;
  381. vec3 force(0.0,0.0,0.0);
  382. float time = 0.0;
  383. float radius = 0.0;
  384. vec4 color(1.0,1.0,1.0,1.0);
  385. Material *material = NULL;
  386. while(1) {
  387. const char *token = read_token();
  388. if(!token || !strcmp(token,"}")) break;
  389. else if(!strcmp(token,"pos")) load_pos(pos,matrix);
  390. else if(!strcmp(token,"num")) num = read_int();
  391. else if(!strcmp(token,"speed")) speed = read_float();
  392. else if(!strcmp(token,"rotation")) rotation = read_float();
  393. else if(!strcmp(token,"force")) force = read_vec3();
  394. else if(!strcmp(token,"time")) time = read_float();
  395. else if(!strcmp(token,"radius")) radius = read_float();
  396. else if(!strcmp(token,"color")) color = read_vec4();
  397. else if(!strcmp(token,"material")) {
  398. read_string();
  399. material = Engine::loadMaterial(read_string());
  400. } else throw(error("unknown token "%s" in particles block",token));
  401. }
  402. ObjectParticles *particles = new ObjectParticles(new Particles(num,vec3(0,0,0),speed,rotation,force,time,radius,color));
  403. if(material) particles->bindMaterial("*",material);
  404. particles->pos = pos;
  405. particles->set(matrix);
  406. Engine::addObject(particles);
  407. }