- merged in willvarfar's particle patch

This commit is contained in:
Mark Vejvoda
2011-07-06 22:23:51 +00:00
parent 9ef8c82441
commit 1b2d4fddea
19 changed files with 624 additions and 218 deletions

View File

@@ -223,7 +223,7 @@ void ParticleRendererGl::renderSystemLineAlpha(ParticleSystem *ps){
assertGl();
}
void ParticleRendererGl::renderModel(AttackParticleSystem *ps, ModelRenderer *mr){
void ParticleRendererGl::renderModel(GameParticleSystem *ps, ModelRenderer *mr){
//render model
Model *model = ps->getModel();
if(model != NULL) {
@@ -262,7 +262,9 @@ void ParticleRendererGl::renderModel(AttackParticleSystem *ps, ModelRenderer *mr
//render
mr->begin(true, true, false);
model->updateInterpolationData(ps->getTween(), false);
float t = ps->getTween();
assert(t >= 0.0f && t <= 1.0f);
model->updateInterpolationData(t, false);
mr->render(model);
mr->end();

View File

@@ -135,7 +135,7 @@ ParticleSystem::BlendMode ParticleSystem::strToBlendMode(const string &str){
return bmOneMinusAlpha;
}
else{
throw "Unknown particle mode: " + str;
throw runtime_error("Unknown particle mode: " + str);
}
}
@@ -143,6 +143,8 @@ ParticleSystem::BlendMode ParticleSystem::strToBlendMode(const string &str){
void ParticleSystem::setState(State state){
this->state= state;
for(int i=getChildCount()-1; i>=0; i--)
getChild(i)->setState(state);
}
void ParticleSystem::setTexture(Texture *texture){
@@ -151,6 +153,8 @@ void ParticleSystem::setTexture(Texture *texture){
void ParticleSystem::setPos(Vec3f pos){
this->pos= pos;
for(int i=getChildCount()-1; i>=0; i--)
getChild(i)->setPos(pos);
}
void ParticleSystem::setColor(Vec4f color){
@@ -183,14 +187,22 @@ void ParticleSystem::setSpeed(float speed){
void ParticleSystem::setActive(bool active){
this->active= active;
for(int i=getChildCount()-1; i>=0; i--)
getChild(i)->setActive(active);
}
void ParticleSystem::setObserver(ParticleObserver *particleObserver){
this->particleObserver= particleObserver;
}
ParticleSystem* ParticleSystem::getChild(int i){
throw std::out_of_range("ParticleSystem::getChild bad");
}
void ParticleSystem::setVisible(bool visible){
this->visible= visible;
for(int i=getChildCount()-1; i>=0; i--)
getChild(i)->setVisible(visible);
}
// =============== MISC =========================
@@ -209,6 +221,8 @@ void ParticleSystem::fade(){
if(particleObserver != NULL){
particleObserver->update(this);
}
for(int i=getChildCount()-1; i>=0; i--)
getChild(i)->fade();
}
int ParticleSystem::isEmpty() const{
@@ -297,6 +311,8 @@ void ParticleSystem::setFactionColor(Vec3f factionColor){
if(teamcolorNoEnergy){
this->colorNoEnergy= Vec4f(factionColor.x, factionColor.y, factionColor.z, this->colorNoEnergy.w);
}
for(int i=getChildCount()-1; i>=0; i--)
getChild(i)->setFactionColor(factionColor);
}
// ===========================================================================
@@ -378,13 +394,132 @@ void FireParticleSystem::setWind(float windAngle, float windSpeed){
#endif
}
// ===========================================================================
// GameParticleSystem
// ===========================================================================
GameParticleSystem::GameParticleSystem(int particleCount):
ParticleSystem(particleCount),
primitive(pQuad),
model(NULL),
modelCycle(0.0f),
tween(0.0f),
offset(0.0f),
direction(0.0f, 1.0f, 0.0f)
{}
GameParticleSystem::~GameParticleSystem(){
for(Children::iterator it= children.begin(); it != children.end(); it++){
(*it)->setParent(NULL);
(*it)->fade();
}
}
GameParticleSystem::Primitive GameParticleSystem::strToPrimitive(const string &str){
if(str == "quad"){
return pQuad;
}
else if(str == "line"){
return pLine;
}
else{
throw runtime_error("Unknown particle primitive: " + str);
}
}
int GameParticleSystem::getChildCount(){
return children.size();
}
ParticleSystem* GameParticleSystem::getChild(int i){
return children.at(i); // does bounds checking
}
void GameParticleSystem::addChild(UnitParticleSystem* child) {
assert(!child->getParent());
child->setParent(this);
children.push_back(child);
}
void GameParticleSystem::removeChild(UnitParticleSystem* child){
assert(this == child->getParent());
Children::iterator it = std::find(children.begin(),children.end(),child);
assert(it != children.end());
children.erase(it);
}
void GameParticleSystem::setPos(Vec3f pos){
this->pos= pos;
positionChildren();
}
void GameParticleSystem::positionChildren() {
Vec3f child_pos = pos - offset;
for(int i=getChildCount()-1; i>=0; i--)
getChild(i)->setPos(child_pos);
}
void GameParticleSystem::setOffset(Vec3f offset){
this->offset= offset;
positionChildren();
}
void GameParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
if(active){
if(model != NULL){
pr->renderModel(this, mr);
}
switch(primitive){
case pQuad:
pr->renderSystem(this);
break;
case pLine:
pr->renderSystemLine(this);
break;
default:
assert(false);
}
}
}
void GameParticleSystem::setTween(float relative,float absolute) {
if(model){
// animation?
if(modelCycle == 0.0f) {
tween= relative;
}
else {
#ifdef USE_STREFLOP
if(streflop::fabs(absolute) <= 0.00001f){
#else
if(fabs(absolute) <= 0.00001f){
#endif
tween = 0.0f;
}
else {
#ifdef USE_STREFLOP
tween= streflop::fmod(absolute, modelCycle);
#else
tween= fmod(absolute, modelCycle);
#endif
tween /= modelCycle;
}
}
assert(tween >= 0.0f && tween <= 1.0f);
tween= clamp(tween, 0.0f, 1.0f);
}
for(Children::iterator it= children.begin(); it != children.end(); it++)
(*it)->setTween(relative,absolute);
}
// ===========================================================================
// UnitParticleSystem
// ===========================================================================
bool UnitParticleSystem::isNight= false;
UnitParticleSystem::UnitParticleSystem(int particleCount) :
ParticleSystem(particleCount){
UnitParticleSystem::UnitParticleSystem(int particleCount):
GameParticleSystem(particleCount),
parent(NULL){
radius= 0.5f;
speed= 0.01f;
windSpeed= Vec3f(0.0f);
@@ -393,8 +528,6 @@ UnitParticleSystem::UnitParticleSystem(int particleCount) :
setColorNoEnergy(Vec4f(1.0f, 0.5f, 0.0f, 1.0f));
primitive= pQuad;
offset= Vec3f(0.0f);
direction= Vec3f(0.0f, 1.0f, 0.0f);
gravity= 0.0f;
fixed= false;
@@ -413,6 +546,15 @@ UnitParticleSystem::UnitParticleSystem(int particleCount) :
emissionState= (float) staticParticleCount;
}
energyUp= false;
delay = 0; // none
lifetime = -1; // forever
}
UnitParticleSystem::~UnitParticleSystem(){
if(parent){
parent->removeChild(this);
}
}
bool UnitParticleSystem::getVisible() const{
@@ -425,54 +567,48 @@ bool UnitParticleSystem::getVisible() const{
else return false;
}
void UnitParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
//if(active){
switch(primitive){
case pQuad:
pr->renderSystem(this);
break;
case pLine:
pr->renderSystemLine(this);
break;
default:
assert(false);
}
//}
void UnitParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr) {
GameParticleSystem::render(pr,mr);
}
UnitParticleSystem::Primitive UnitParticleSystem::strToPrimitive(const string &str){
if(str == "quad"){
return pQuad;
void UnitParticleSystem::setRotation(float rotation){
this->rotation= rotation;
for(Children::iterator it= children.begin(); it != children.end(); it++)
(*it)->setRotation(rotation);
}
void UnitParticleSystem::fade(){
if(!parent || (lifetime<=0 && !(emissionRateFade && emissionRate > 0))){ // particle has its own lifetime?
GameParticleSystem::fade();
}
else if(str == "line"){
return pLine;
}
UnitParticleSystem::Shape UnitParticleSystem::strToShape(const string& str){
if(str == "spherical"){
return sSpherical;
}
else if(str == "conical"){
return sConical;
}
else if(str == "linear"){
return sLinear;
}
else{
throw "Unknown particle primitive: " + str;
throw runtime_error("Unkown particle shape: " + str);
}
}
void UnitParticleSystem::initParticle(Particle *p, int particleIndex){
ParticleSystem::initParticle(p, particleIndex);
float ang= random.randRange(-2.0f * pi, 2.0f * pi);
#ifdef USE_STREFLOP
float mod= streflop::fabsf(random.randRange(-radius, radius));
float x= streflop::sinf(ang)*mod;
float y= streflop::cosf(ang)*mod;
float radRatio= streflop::sqrtf(streflop::sqrtf(mod/radius));
const float ang= random.randRange(-2.0f * pi, 2.0f * pi);
#ifdef USE_STREFLOP
const float mod= streflop::fabsf(random.randRange(-radius, radius));
const float radRatio= streflop::sqrtf(streflop::sqrtf(mod/radius));
#else
float mod= fabsf(random.randRange(-radius, radius));
float x= sinf(ang) * mod;
float y= cosf(ang) * mod;
float radRatio= sqrtf(sqrtf(mod / radius));
const float mod= fabsf(random.randRange(-radius, radius));
const float radRatio= sqrtf(sqrtf(mod / radius));
#endif
//p->color= color*0.5f + color*0.5f*radRatio;
p->color= color;
if(radiusBasedStartenergy == true){
p->energy= static_cast<int> (maxParticleEnergy * radRatio) + random.randRange(-varParticleEnergy,
@@ -485,36 +621,72 @@ void UnitParticleSystem::initParticle(Particle *p, int particleIndex){
p->lastPos= pos;
oldPosition= pos;
p->size= particleSize;
p->speed= Vec3f(direction.x + direction.x * random.randRange(-0.5f, 0.5f), direction.y + direction.y
* random.randRange(-0.5f, 0.5f), direction.z + direction.z * random.randRange(-0.5f, 0.5f));
p->speed= p->speed * speed;
p->accel= Vec3f(0.0f, -gravity, 0.0f);
if(relative == false){
p->pos= Vec3f(pos.x + x + offset.x, pos.y + random.randRange(-radius / 2, radius / 2) + offset.y, pos.z + y
+ offset.z);
}
else{// rotate it according to rotation
float rad= degToRad(rotation);
#ifdef USE_STREFLOP
p->pos= Vec3f(pos.x+x+offset.z*streflop::sinf(rad)+offset.x*streflop::cosf(rad), pos.y+random.randRange(-radius/2, radius/2)+offset.y, pos.z+y+(offset.z*streflop::cosf(rad)-offset.x*streflop::sinf(rad)));
if(relativeDirection){
// work out where we start for our shape (set speed and pos)
switch(shape){
case sSpherical:
angle = random.randRange(0,360);
// fall through
case sConical:{
Vec2f horiz = Vec2f(1,0).rotate(ang);
Vec2f vert = Vec2f(1,0).rotate(degToRad(angle));
Vec3f start = Vec3f(horiz.x*vert.y,vert.x,horiz.y).getNormalized(); // close enough
p->speed = start * speed;
start = start * random.randRange(minRadius,radius);
p->pos = pos + offset + start;
} break;
case sLinear:{
#ifdef USE_STREFLOP
float x= streflop::sinf(ang)*mod;
float y= streflop::cosf(ang)*mod;
#else
float x= sinf(ang) * mod;
float y= cosf(ang) * mod;
#endif
const float rad= degToRad(rotation);
if(!relative){
p->pos= Vec3f(pos.x + x + offset.x, pos.y + random.randRange(-radius / 2, radius / 2) + offset.y, pos.z + y
+ offset.z);
}
else{// rotate it according to rotation
#ifdef USE_STREFLOP
p->pos= Vec3f(pos.x+x+offset.z*streflop::sinf(rad)+offset.x*streflop::cosf(rad), pos.y+random.randRange(-radius/2, radius/2)+offset.y, pos.z+y+(offset.z*streflop::cosf(rad)-offset.x*streflop::sinf(rad)));
#else
p->pos= Vec3f(pos.x + x + offset.z * sinf(rad) + offset.x * cosf(rad), pos.y + random.randRange(-radius / 2,
radius / 2) + offset.y, pos.z + y + (offset.z * cosf(rad) - offset.x * sinf(rad)));
#endif
}
p->speed= Vec3f(direction.x + direction.x * random.randRange(-0.5f, 0.5f), direction.y + direction.y
* random.randRange(-0.5f, 0.5f), direction.z + direction.z * random.randRange(-0.5f, 0.5f));
p->speed= p->speed * speed;
if(relative && relativeDirection){
#ifdef USE_STREFLOP
p->speed=Vec3f(p->speed.z*streflop::sinf(rad)+p->speed.x*streflop::cosf(rad),p->speed.y,(p->speed.z*streflop::cosf(rad)-p->speed.x*streflop::sinf(rad)));
}
#else
p->pos= Vec3f(pos.x + x + offset.z * sinf(rad) + offset.x * cosf(rad), pos.y + random.randRange(-radius / 2,
radius / 2) + offset.y, pos.z + y + (offset.z * cosf(rad) - offset.x * sinf(rad)));
if(relativeDirection){
#else
p->speed= Vec3f(p->speed.z * sinf(rad) + p->speed.x * cosf(rad), p->speed.y, (p->speed.z * cosf(rad)
- p->speed.x * sinf(rad)));
- p->speed.x * sinf(rad)));
#endif
}
#endif
} break;
default: throw runtime_error("bad shape");
}
}
void UnitParticleSystem::update(){
// delay and timeline are only applicable for child particles
if(parent && delay>0 && delay--){
return;
}
if(parent && lifetime>0 && !--lifetime) {
fade();
}
if(state != sPause) {
emissionRate-= emissionRateFade;
if(parent && emissionRate < 0.0f) {
fade();
}
}
if(fixed){
fixedAddition= Vec3f(pos.x - oldPosition.x, pos.y - oldPosition.y, pos.z - oldPosition.z);
oldPosition= pos;
@@ -573,10 +745,6 @@ void UnitParticleSystem::updateParticle(Particle *p){
// ================= SET PARAMS ====================
void UnitParticleSystem::setRadius(float radius){
this->radius= radius;
}
void UnitParticleSystem::setWind(float windAngle, float windSpeed){
#ifdef USE_STREFLOP
this->windSpeed.x= streflop::sinf(degToRad(windAngle))*windSpeed;
@@ -700,43 +868,9 @@ void SnowParticleSystem::setWind(float windAngle, float windSpeed){
// ===========================================================================
AttackParticleSystem::AttackParticleSystem(int particleCount) :
ParticleSystem(particleCount){
model= NULL;
GameParticleSystem(particleCount){
primitive= pQuad;
offset= Vec3f(0.0f);
gravity= 0.0f;
tween= 0.0f;
direction= Vec3f(1.0f, 0.0f, 0.0f);
}
void AttackParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
if(active){
if(model != NULL){
pr->renderModel(this, mr);
}
switch(primitive){
case pQuad:
pr->renderSystem(this);
break;
case pLine:
pr->renderSystemLine(this);
break;
default:
assert(false);
}
}
}
AttackParticleSystem::Primitive AttackParticleSystem::strToPrimitive(const string &str){
if(str == "quad"){
return pQuad;
}
else if(str == "line"){
return pLine;
}
else{
throw "Unknown particle primitive: " + str;
}
}
// ===========================================================================
@@ -775,7 +909,6 @@ void ProjectileParticleSystem::link(SplashParticleSystem *particleSystem){
}
void ProjectileParticleSystem::update(){
if(state == sPlay){
lastPos= pos;
@@ -785,19 +918,7 @@ void ProjectileParticleSystem::update(){
// ratio
float t= clamp(currentVector.length() / targetVector.length(), 0.0f, 1.0f);
// animation?
if(modelCycle == 0.0f) {
tween= t;
}
else {
#ifdef USE_STREFLOP
tween= streflop::fmod(currentVector.length(), modelCycle);
#else
tween= fmod(currentVector.length(), modelCycle);
#endif
tween= clamp(tween / currentVector.length(), 0.0f, 1.0f);
}
setTween(t,currentVector.length());
// trajectory
switch(trajectory) {
@@ -833,10 +954,13 @@ void ProjectileParticleSystem::update(){
direction= pos - lastPos;
direction.normalize();
// trigger update of child particles
positionChildren();
rotateChildren();
//arrive destination
if(flatPos.dist(endPos) < 0.5f){
state= sFade;
fade();
model= NULL;
if(particleObserver != NULL){
@@ -854,6 +978,18 @@ void ProjectileParticleSystem::update(){
ParticleSystem::update();
}
void ProjectileParticleSystem::rotateChildren() {
//### only on horizontal plane :(
#ifdef USE_STREFLOP
float rotation = streflop::atan2(direction.x, direction.z);
#else
float rotation = atan2(direction.x, direction.z);
#endif
rotation = radToDeg(rotation);
for(Children::iterator it = children.begin(); it != children.end(); it++)
(*it)->setRotation(rotation);
}
void ProjectileParticleSystem::initParticle(Particle *p, int particleIndex){
ParticleSystem::initParticle(p, particleIndex);
@@ -906,6 +1042,11 @@ void ProjectileParticleSystem::setPath(Vec3f startPos, Vec3f endPos){
// set members
this->startPos= startPos;
this->endPos= endPos;
// direction
direction = (endPos - lastPos);
direction.normalize();
rotateChildren();
}
ProjectileParticleSystem::Trajectory ProjectileParticleSystem::strToTrajectory(const string &str){
@@ -919,7 +1060,7 @@ ProjectileParticleSystem::Trajectory ProjectileParticleSystem::strToTrajectory(c
return tSpiral;
}
else{
throw "Unknown particle system trajectory: " + str;
throw runtime_error("Unknown particle system trajectory: " + str);
}
}
@@ -959,8 +1100,9 @@ void SplashParticleSystem::update() {
if(state != sPause) {
emissionRate-= emissionRateFade;
tween= 1.0f - ((emissionRate + startEmissionRate) / (startEmissionRate * 2.0f));
tween= clamp(tween, 0.0f, 1.0f);
float t= 1.0f - ((emissionRate + startEmissionRate) / (startEmissionRate * 2.0f));
t= clamp(t, 0.0f, 1.0f);
setTween(t,t);
if(emissionRate < 0.0f) {//otherwise this system lives forever!
fade();
@@ -1132,7 +1274,10 @@ void ParticleManager::cleanupUnitParticleSystems(vector<UnitParticleSystem *> &p
}
void ParticleManager::manage(ParticleSystem *ps){
assert((std::find(particleSystems.begin(),particleSystems.end(),ps) == particleSystems.end()) && "particle cannot be added twice");
particleSystems.push_back(ps);
for(int i=ps->getChildCount()-1; i>=0; i--)
manage(ps->getChild(i));
}
void ParticleManager::end(){

View File

@@ -13,7 +13,7 @@
namespace Shared { namespace PlatformCommon {
Mutex CacheManager::mutexCache;
//Mutex CacheManager::mutexCache;
const char *CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey1 = "CRC_Cache_FileTree1";
const char *CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey2 = "CRC_Cache_FileTree2";
const char *CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey1 = "CRC_Cache_FileTreeList1";

View File

@@ -13,6 +13,8 @@
#include <fstream>
#include <stdexcept>
#include <vector>
#include <algorithm>
#include "conversion.h"
#include <xercesc/dom/DOM.hpp>
@@ -23,6 +25,7 @@
#include "properties.h"
#include "platform_common.h"
#include "platform_util.h"
#include "cache_manager.h"
#include "leak_dumper.h"
@@ -172,7 +175,26 @@ void XmlTree::init(const string &name){
this->rootNode= new XmlNode(name);
}
typedef std::vector<XmlTree*> LoadStack;
static LoadStack loadStack;
//static string loadStackCacheName = string(__FILE__) + string("_loadStackCacheName");
void XmlTree::load(const string &path, std::map<string,string> mapTagReplacementValues) {
//printf("XmlTree::load p [%p]\n",this);
assert(!loadPath.size());
//LoadStack &loadStack = CacheManager::getCachedItem<LoadStack>(loadStackCacheName);
//Mutex &mutex = CacheManager::getMutexForItem<LoadStack>(loadStackCacheName);
//MutexSafeWrapper safeMutex(&mutex);
for(LoadStack::iterator it= loadStack.begin(); it!= loadStack.end(); it++){
if((*it)->loadPath == path){
throw runtime_error(path + " recursively included");
}
}
loadStack.push_back(this);
loadPath = path;
this->rootNode= XmlIo::getInstance().load(path, mapTagReplacementValues);
}
@@ -180,7 +202,17 @@ void XmlTree::save(const string &path){
XmlIo::getInstance().save(path, rootNode);
}
XmlTree::~XmlTree(){
XmlTree::~XmlTree() {
//printf("XmlTree::~XmlTree p [%p]\n",this);
//LoadStack &loadStack = CacheManager::getCachedItem<LoadStack>(loadStackCacheName);
//Mutex &mutex = CacheManager::getMutexForItem<LoadStack>(loadStackCacheName);
//MutexSafeWrapper safeMutex(&mutex);
LoadStack::iterator it= find(loadStack.begin(),loadStack.end(),this);
if(it != loadStack.end()) {
loadStack.erase(it);
}
delete rootNode;
}
@@ -188,7 +220,7 @@ XmlTree::~XmlTree(){
// class XmlNode
// =====================================================
XmlNode::XmlNode(DOMNode *node, std::map<string,string> mapTagReplacementValues) {
XmlNode::XmlNode(DOMNode *node, std::map<string,string> mapTagReplacementValues): superNode(NULL) {
if(node == NULL || node->getNodeName() == NULL) {
throw runtime_error("XML structure seems to be corrupt!");
}
@@ -235,7 +267,7 @@ XmlNode::XmlNode(DOMNode *node, std::map<string,string> mapTagReplacementValues)
}
}
XmlNode::XmlNode(const string &name) {
XmlNode::XmlNode(const string &name): superNode(NULL) {
this->name= name;
}
@@ -269,6 +301,7 @@ XmlAttribute *XmlNode::getAttribute(const string &name,bool mustExist) const {
}
XmlNode *XmlNode::getChild(unsigned int i) const {
assert(!superNode);
if(i >= children.size()) {
throw runtime_error("\"" + getName()+"\" node doesn't have "+intToStr(i+1)+" children");
}
@@ -287,6 +320,8 @@ vector<XmlNode *> XmlNode::getChildList(const string &childName) const {
}
XmlNode *XmlNode::getChild(const string &childName, unsigned int i) const{
if(superNode && !hasChildNoSuper(childName))
return superNode->getChild(childName,i);
if(i>=children.size()){
throw runtime_error("\"" + name + "\" node doesn't have "+intToStr(i+1)+" children named \"" + childName + "\"\n\nTree: "+getTreeString());
}
@@ -305,6 +340,8 @@ XmlNode *XmlNode::getChild(const string &childName, unsigned int i) const{
}
bool XmlNode::hasChildAtIndex(const string &childName, int i) const {
if(superNode && !hasChildNoSuper(childName))
return superNode->hasChildAtIndex(childName,i);
int count= 0;
for(unsigned int j = 0; j < children.size(); ++j) {
if(children[j]->getName()==childName) {
@@ -318,19 +355,22 @@ bool XmlNode::hasChildAtIndex(const string &childName, int i) const {
return false;
}
bool XmlNode::hasChild(const string &childName) const {
return hasChildNoSuper(childName) || (superNode && superNode->hasChild(childName));
}
bool XmlNode::hasChildNoSuper(const string &childName) const {
int count= 0;
for(unsigned int j = 0; j < children.size(); ++j) {
if(children[j]->getName() == childName) {
return true;
}
}
return false;
}
XmlNode *XmlNode::addChild(const string &name){
assert(!superNode);
XmlNode *node= new XmlNode(name);
children.push_back(node);
return node;