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

游戏引擎

开发平台:

Visual C++

  1. /* RagDoll
  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 "mesh.h"
  21. #include "meshvbo.h"
  22. #include "object.h"
  23. #include "objectmesh.h"
  24. #include "rigidbody.h"
  25. #include "joint.h"
  26. #include "parser.h"
  27. #include "ragdoll.h"
  28. RagDoll::RagDoll(SkinnedMesh *skinnedmesh,const char *name) : skinnedmesh(skinnedmesh), num_bones(0), root(-1) {
  29. Parser *parser = new Parser(Engine::findFile(name));
  30. if(!parser->get("mesh")) {
  31. fprintf(stderr,"RagDoll::RagDoll(): can`t find mesh in "%s" filen",name);
  32. return;
  33. }
  34. if(!parser->get("rigidbodies")) {
  35. fprintf(stderr,"RagDoll::RagDoll(): can`t find rigidbodies in "%s" filen",name);
  36. return;
  37. }
  38. if(!parser->get("joints")) {
  39. fprintf(stderr,"RagDoll::RagDoll(): can`t find joints in "%s" filen",name);
  40. return;
  41. }
  42. num_bones = skinnedmesh->getNumBones();
  43. bones = skinnedmesh->getBones();
  44. meshes = new Object*[num_bones];
  45. memset(meshes,0,sizeof(Object*) * num_bones);
  46. rigidbodies = new RigidBody*[num_bones];
  47. offsets = new mat4[num_bones];
  48. ioffsets = new mat4[num_bones];
  49. char buf[1024];
  50. sscanf(parser->get("mesh"),"%s",buf);
  51. Mesh *mesh = new Mesh(Engine::findFile(buf));
  52. // scale objects
  53. if(parser->get("scale")) {
  54. vec3 v;
  55. sscanf(parser->get("scale"),"%f %f %f",&v.x,&v.y,&v.z);
  56. mat4 scale;
  57. scale.scale(v);
  58. skinnedmesh->transform(scale);
  59. mesh->transform(scale);
  60. }
  61. // create bones
  62. for(int i = 0; i < num_bones; i++) {
  63. char bone_name[1024];
  64. float mass = 1.0f;
  65. float restitution = 0.3f;
  66. float friction = 0.3f;
  67. int flag = 0;
  68. bone_name[0] = '';
  69. // find bone description in rigidbodies section
  70. char *s = parser->get("rigidbodies");
  71. while(*s) {
  72. char *d = buf; // get line
  73. while(*s && *s != 'n') *d++ = *s++;
  74. while(*s && strchr("nr",*s)) s++;
  75. *d = '';
  76. d = buf;
  77. d += Parser::read_string(d,bone_name);
  78. if(!strcmp(bone_name,bones[i].name)) {
  79. char body[1024];
  80. sscanf(d,"%s %f %f %f",body,&mass,&restitution,&friction);
  81. if(!strcmp(body,"box")) flag = RigidBody::BODY_BOX;
  82. else if(!strcmp(body,"sphere")) flag = RigidBody::BODY_SPHERE;
  83. else if(!strcmp(body,"cylinder")) flag = RigidBody::BODY_CYLINDER;
  84. break;
  85. }
  86. }
  87. if(flag == 0) {
  88. fprintf(stderr,"RigidBody::RigidBody(): can`t find attributes for "%s" bone in "%s" filen",bones[i].name,name);
  89. return;
  90. }
  91. int surface = mesh->getSurface(bones[i].name);
  92. if(surface < 0) {
  93. fprintf(stderr,"RagDoll::RagDoll(): can`t find mesh for "%s" bone in "%s" filen",bones[i].name,name);
  94. return;
  95. }
  96. // create new mesh
  97. Mesh *m = new Mesh;
  98. m->addSurface(mesh,surface);
  99. vec3 center = (m->getMax() + m->getMin()) / 2.0f;
  100. offsets[i].translate(-center);
  101. m->transform(offsets[i]);
  102. meshes[i] = new ObjectMesh(new MeshVBO(m));
  103. delete m;
  104. //meshes[i]->bindMaterial("*",Engine::loadMaterial("default.mat"));
  105. rigidbodies[i] = new RigidBody(meshes[i],mass,restitution,friction,RigidBody::COLLIDE_MESH | flag);
  106. meshes[i]->setRigidBody(rigidbodies[i]);
  107. offsets[i] = bones[i].transform.inverse() * offsets[i].inverse();
  108. ioffsets[i] = offsets[i].inverse();
  109. meshes[i]->set(bones[i].transform * offsets[i]);
  110. Engine::addObject(meshes[i]);
  111. if(bones[i].parent == -1) {
  112. if(root == -1) root = i;
  113. else fprintf(stderr,"RagDoll::RagDoll(): many roots bones in "%s" filen",name);
  114. }
  115. }
  116. // create joints
  117. char *s = parser->get("joints");
  118. while(*s) {
  119. char bone_0_name[1024];
  120. char bone_1_name[1024];
  121. int bone_0 = -1;
  122. int bone_1 = -1;
  123. char *d = buf; // get line
  124. while(*s && *s != 'n') *d++ = *s++;
  125. while(*s && strchr("nr",*s)) s++;
  126. *d = '';
  127. d = buf;
  128. d += Parser::read_string(d,bone_0_name);
  129. d += Parser::read_string(d,bone_1_name);
  130. for(int i = 0; i < num_bones; i++) {
  131. if(!strcmp(bone_0_name,bones[i].name)) {
  132. bone_0 = i;
  133. break;
  134. }
  135. }
  136. if(bone_0 == -1) {
  137. fprintf(stderr,"RagDoll::RagDoll(): unknown bone "%s" in "%s" filen",bone_0_name,name);
  138. continue;
  139. }
  140. for(int i = 0; i < num_bones; i++) {
  141. if(!strcmp(bone_1_name,bones[i].name)) {
  142. bone_1 = i;
  143. break;
  144. }
  145. }
  146. if(bone_1 == -1) {
  147. fprintf(stderr,"RagDoll::RagDoll(): unknown bone "%s" in "%s" filen",bone_1_name,name);
  148. continue;
  149. }
  150. if(bones[bone_1].parent == bone_0) {
  151. // bone_0 - parent
  152. // bone_1 - child
  153. } else if(bones[bone_0].parent == bone_1) {
  154. int i = bone_0;
  155. bone_0 = bone_1;
  156. bone_1 = i;
  157. } else {
  158. fprintf(stderr,"RagDoll::RagDoll(): can`t joint "%s" and "%s" bones in "%s" filen",bone_0_name,bone_1_name,name);
  159. continue;
  160. }
  161. char type[1024];
  162. d += Parser::read_string(d,type);
  163. if(!strcmp(type,"ball")) { // ball - socket joint
  164. vec3 restriction_axis_0,restriction_axis_1;
  165. float restriction_angle;
  166. int num = sscanf(d,"%f %f %f %f %f %f %f",
  167. &restriction_axis_0.x,&restriction_axis_0.y,&restriction_axis_0.z,
  168. &restriction_axis_1.x,&restriction_axis_1.y,&restriction_axis_1.z,
  169. &restriction_angle);
  170. if(num == 7) new JointBall(rigidbodies[bone_0],rigidbodies[bone_1],bones[bone_1].transform * vec3(0,0,0),restriction_axis_0,restriction_axis_1,restriction_angle);
  171. else if(num == 0) new JointBall(rigidbodies[bone_0],rigidbodies[bone_1],bones[bone_1].transform * vec3(0,0,0));
  172. else fprintf(stderr,"RagDoll::RagDoll(): bad arguments for "%s" "%s" bones in "%s" filen",bone_0_name,bone_1_name,name);
  173. } else if(!strcmp(type,"hinge")) { // hinge joint
  174. vec3 axis,restriction_axis_0,restriction_axis_1;
  175. float restriction_angle;
  176. int num = sscanf(d,"%f %f %f %f %f %f %f %f %f %f",
  177. &axis.x,&axis.y,&axis.z,
  178. &restriction_axis_0.x,&restriction_axis_0.y,&restriction_axis_0.z,
  179. &restriction_axis_1.x,&restriction_axis_1.y,&restriction_axis_1.z,
  180. &restriction_angle);
  181. if(num == 10) new JointHinge(rigidbodies[bone_0],rigidbodies[bone_1],bones[bone_1].transform * vec3(0,0,0),axis,restriction_axis_0,restriction_axis_1,restriction_angle);
  182. else if(num == 3) new JointHinge(rigidbodies[bone_0],rigidbodies[bone_1],bones[bone_1].transform * vec3(0,0,0),axis);
  183. else fprintf(stderr,"RagDoll::RagDoll(): bad arguments for "%s" "%s" bones in "%s" filen",bone_0_name,bone_1_name,name);
  184. } else if(!strcmp(type,"universal")) { // universal joint
  185. vec3 axis_0,axis_1,restriction_axis_0,restriction_axis_1;
  186. float restriction_angle;
  187. int num = sscanf(d,"%f %f %f %f %f %f %f %f %f %f %f %f %f",
  188. &axis_0.x,&axis_0.y,&axis_0.z,&axis_1.x,&axis_1.y,&axis_1.z,
  189. &restriction_axis_0.x,&restriction_axis_0.y,&restriction_axis_0.z,
  190. &restriction_axis_1.x,&restriction_axis_1.y,&restriction_axis_1.z,
  191. &restriction_angle);
  192. if(num == 13) new JointUniversal(rigidbodies[bone_0],rigidbodies[bone_1],bones[bone_1].transform * vec3(0,0,0),axis_0,axis_1,restriction_axis_0,restriction_axis_1,restriction_angle);
  193. else if(num == 6) new JointUniversal(rigidbodies[bone_0],rigidbodies[bone_1],bones[bone_1].transform * vec3(0,0,0),axis_0,axis_1);
  194. else fprintf(stderr,"RagDoll::RagDoll(): bad arguments for "%s" "%s" bones in "%s" filen",bone_0_name,bone_1_name,name);
  195. } else {
  196. fprintf(stderr,"RagDoll::RagDoll(): unknown joint type "%s" in "%s" filen",type,name);
  197. continue;
  198. }
  199. }
  200. delete mesh;
  201. delete parser;
  202. }
  203. RagDoll::~RagDoll() {
  204. for(int i = 0; i < num_bones; i++) {
  205. if(meshes[i]) {
  206. delete meshes[i];
  207. }
  208. }
  209. delete meshes;
  210. delete offsets;
  211. delete ioffsets;
  212. }
  213. /*
  214.  */
  215. void RagDoll::update() {
  216. for(int i = 0; i < num_bones; i++) {
  217. if(meshes[i]) {
  218. bones[i].transform = itransform * meshes[i]->transform * ioffsets[i];
  219. bones[i].rotation = bones[i].transform.rotation();
  220. }
  221. }
  222. }
  223. /*
  224.  */
  225. void RagDoll::setTransform(const mat4 &m) {
  226. transform = m;
  227. itransform = transform.inverse();
  228. for(int i = 0; i < num_bones; i++) {
  229. if(meshes[i]) {
  230. meshes[i]->set(m * bones[i].transform * offsets[i]);
  231. }
  232. }
  233. }
  234. /*
  235.  */
  236. void RagDoll::set(const mat4 &m) {
  237. if(root == -1) return;
  238. meshes[root]->set(m);
  239. }