00001 #include "Horde3D.h"
00002 #include "Horde3DUtils.h"
00003 #include <btBulletDynamicsCommon.h>
00004
00005 #include "Physics.h"
00006 #include "Game.h"
00007 #include "World.h"
00008 #include "Explosive.h"
00009 #include "Vec3.h"
00010 #include "CharacterCollisionCallback.h"
00011 #include "IShootable.h"
00012
00019 Explosive::Explosive(Game* game, H3DNode parent, Physics* physics, const int id, H3DRes modelRes, const Vec3 position, const Vec3 rotation, const float scale)
00020 : IShootable(game, parent, physics, id, "barrel") {
00021 _doExplode = false;
00022 _health = 3;
00023 _scale = scale;
00024
00025
00026 _cylinderRadius = 0.30f;
00027 float bodyHeight = 1.0f;
00028 _cylinderHeight = bodyHeight - _levelBelowCylinder;
00029 btVector3 halfExtent(_cylinderRadius, bodyHeight / 2, _cylinderRadius);
00030 _cylinder = new btCylinderShape(halfExtent);
00031
00032
00033 _groundMotionState = new btDefaultMotionState(btTransform(
00034 btQuaternion(0,0,0,1),
00035 btVector3(position.x, position.y, position.z))
00036 );
00037
00038
00039 _body = new btRigidBody(150, _groundMotionState, _cylinder);
00040 _body->setFriction(2.0f);
00041 _body->setDamping(0.5f, 0.5f);
00042
00043 _body->setActivationState(DISABLE_DEACTIVATION);
00044 _physics->addShootable(this);
00045
00046 H3DRes particleSysRes = h3dAddResource(H3DResTypes::SceneGraph, "particles/explosiveExplosion/explosiveExplosion.scene.xml", 0);
00047 bool loaded = h3dutLoadResourcesFromDisk(::Values::CONTENT_DIR);
00048 if(! loaded) std::cout << "could not load explosive ressources" << std::endl;
00049
00050
00051 _emitter = h3dAddNodes(parent, particleSysRes);
00052 h3dSetNodeTransform(_emitter, position.x, position.y, position.z,
00053 90, 0, 0,
00054 1, 1, 1);
00055 h3dSetNodeActivation(_emitter, false);
00056
00057
00058 _model = h3dAddNodes(parent, modelRes);
00059 h3dSetNodeTransform(_model, position.x, position.y, position.z,
00060 rotation.x, rotation.y, rotation.z,
00061 scale, scale, scale);
00062 }
00063
00064 Explosive::~Explosive() {
00065
00066 }
00067
00072 void Explosive::update(const float timeStep) {
00073
00074 if(_doExplode) {
00075
00076
00077
00078
00079 Game::advanceEmitter(_emitter, timeStep);
00080 }
00081 else {
00082
00083 Vec3 currentPosition = getPosition();
00084 Vec3 rollbackPosition;
00085 Vec3 collisionPoint;
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 btTransform trans;
00116 _body->getMotionState()->getWorldTransform(trans);
00117 float explosiveOffset = ((btCapsuleShape*)_body->getCollisionShape())->getHalfHeight();
00118
00119 h3dSetNodeTransform(_model,
00120 trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z(),
00121 0 ,0, 0,
00122 _scale, _scale, _scale);
00123
00124 h3dSetNodeTransform(_emitter,
00125 trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z(),
00126 90, 0, 0,
00127 1, 1, 1);
00128 }
00129 }
00130
00135 void Explosive::setPosition(Vec3 newPosition) {
00136 btTransform transform;
00137 transform = _body->getCenterOfMassTransform();
00138 transform.setOrigin(btVector3(newPosition.x, newPosition.y, newPosition.z));
00139 _body->setCenterOfMassTransform(transform);
00140 }
00141
00146 Vec3 Explosive::getPosition() {
00147 btTransform transform;
00148 transform = _body->getCenterOfMassTransform();
00149 btVector3 pos = transform.getOrigin();
00150 return Vec3(pos.x(), pos.y(), pos.z());
00151 }
00152
00157 void Explosive::hit() {
00158 _health--;
00159 if(_health <= 0) {
00160 _doExplode = true;
00161
00162
00163 h3dSetNodeActivation(_model, false);
00164 h3dSetNodeActivation(_emitter, true);
00165
00166
00167 _body->setActivationState(WANTS_DEACTIVATION);
00168 setPosition(Vec3(-100,-100,-100));
00169 }
00170 }
00171
00178 bool Explosive::castRayAndCorrectPosition(Vec3& calculatedCurrentPosition, Vec3& collisionPoint) {
00179 float cylinderBottom = (-_cylinderHeight / 2) - _cylinderRadius;
00180
00181
00182 Vec3 from = calculatedCurrentPosition;
00183 Vec3 to = calculatedCurrentPosition;
00184 from.y += cylinderBottom + 0.5f;
00185 to.y += cylinderBottom - 0.5f;
00186
00187 bool onground = _physics->castRay(from, to, collisionPoint, _body);
00188
00189
00190 if (onground) {
00191 calculatedCurrentPosition = Vec3(
00192 calculatedCurrentPosition.x,
00193 (_cylinderHeight / 2)+ collisionPoint.y,
00194 calculatedCurrentPosition.z);
00195 }
00196 return onground;
00197 }