add sparkle explosions
This commit is contained in:
3
libs/spark/src/Core/.directory
Normal file
3
libs/spark/src/Core/.directory
Normal file
@@ -0,0 +1,3 @@
|
||||
[Dolphin]
|
||||
Timestamp=2011,1,5,19,24,26
|
||||
ViewMode=1
|
53
libs/spark/src/Core/SPK_BufferHandler.cpp
Normal file
53
libs/spark/src/Core/SPK_BufferHandler.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_BufferHandler.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
bool BufferHandler::bufferCreation = true;
|
||||
|
||||
void BufferHandler::enableBuffersCreation(bool creation)
|
||||
{
|
||||
bufferCreation = creation;
|
||||
}
|
||||
|
||||
bool BufferHandler::isBuffersCreationEnabled()
|
||||
{
|
||||
return bufferCreation;
|
||||
}
|
||||
|
||||
bool BufferHandler::prepareBuffers(const Group& group)
|
||||
{
|
||||
if (!checkBuffers(group))
|
||||
{
|
||||
if (isBuffersCreationEnabled())
|
||||
{
|
||||
destroyBuffers(group);
|
||||
createBuffers(group);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
28
libs/spark/src/Core/SPK_DEF.cpp
Normal file
28
libs/spark/src/Core/SPK_DEF.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
unsigned int randomSeed = 1;
|
||||
}
|
131
libs/spark/src/Core/SPK_Emitter.cpp
Normal file
131
libs/spark/src/Core/SPK_Emitter.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Emitter.h"
|
||||
#include "Extensions/Zones/SPK_Point.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Emitter::Emitter() :
|
||||
Registerable(),
|
||||
Transformable(),
|
||||
zone(&getDefaultZone()),
|
||||
full(true),
|
||||
tank(-1),
|
||||
flow(0.0f),
|
||||
forceMin(0.0f),
|
||||
forceMax(0.0f),
|
||||
fraction(random(0.0f,1.0f)),
|
||||
active(true)
|
||||
{}
|
||||
|
||||
void Emitter::registerChildren(bool registerAll)
|
||||
{
|
||||
Registerable::registerChildren(registerAll);
|
||||
registerChild(zone,registerAll);
|
||||
}
|
||||
|
||||
void Emitter::copyChildren(const Emitter& emitter,bool createBase)
|
||||
{
|
||||
Registerable::copyChildren(emitter,createBase);
|
||||
zone = dynamic_cast<Zone*>(copyChild(emitter.zone,createBase));
|
||||
}
|
||||
|
||||
void Emitter::destroyChildren(bool keepChildren)
|
||||
{
|
||||
destroyChild(zone,keepChildren);
|
||||
Registerable::destroyChildren(keepChildren);
|
||||
}
|
||||
|
||||
Registerable* Emitter::findByName(const std::string& name)
|
||||
{
|
||||
Registerable* object = Registerable::findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
|
||||
return zone->findByName(name);
|
||||
}
|
||||
|
||||
void Emitter::changeTank(int deltaTank)
|
||||
{
|
||||
if (tank >= 0)
|
||||
{
|
||||
tank += deltaTank;
|
||||
if (tank < 0)
|
||||
tank = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::changeFlow(float deltaFlow)
|
||||
{
|
||||
if (flow >= 0.0f)
|
||||
{
|
||||
flow += deltaFlow;
|
||||
if (flow < 0.0f)
|
||||
flow = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::setZone(Zone* zone,bool full)
|
||||
{
|
||||
decrementChildReference(this->zone);
|
||||
incrementChildReference(zone);
|
||||
|
||||
if (zone == NULL)
|
||||
zone = &getDefaultZone();
|
||||
|
||||
this->zone = zone;
|
||||
this->full = full;
|
||||
}
|
||||
|
||||
Zone& Emitter::getDefaultZone()
|
||||
{
|
||||
static Point defaultZone;
|
||||
return defaultZone;
|
||||
}
|
||||
|
||||
unsigned int Emitter::updateNumber(float deltaTime)
|
||||
{
|
||||
int nbBorn;
|
||||
if (flow < 0.0f)
|
||||
{
|
||||
nbBorn = std::max(0,tank);
|
||||
tank = 0;
|
||||
}
|
||||
else if (tank != 0)
|
||||
{
|
||||
fraction += flow * deltaTime;
|
||||
nbBorn = static_cast<int>(fraction);
|
||||
if (tank >= 0)
|
||||
{
|
||||
nbBorn = std::min(tank,nbBorn);
|
||||
tank -= nbBorn;
|
||||
}
|
||||
fraction -= nbBorn;
|
||||
}
|
||||
else
|
||||
nbBorn = 0;
|
||||
|
||||
return static_cast<unsigned int>(nbBorn);
|
||||
}
|
||||
}
|
214
libs/spark/src/Core/SPK_Factory.cpp
Normal file
214
libs/spark/src/Core/SPK_Factory.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Factory.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
SPKFactory* SPKFactory::instance = NULL;
|
||||
SPK_ID SPKFactory::currentID = NO_ID;
|
||||
|
||||
SPKFactory& SPKFactory::getInstance()
|
||||
{
|
||||
if (instance == NULL)
|
||||
instance = new SPKFactory;
|
||||
return *instance;
|
||||
}
|
||||
|
||||
void SPKFactory::destroyInstance()
|
||||
{
|
||||
if (instance != NULL)
|
||||
{
|
||||
delete instance;
|
||||
instance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SPK_ID SPKFactory::create(const Registerable& base)
|
||||
{
|
||||
// Clears the adresses set
|
||||
SPKAdresses.clear();
|
||||
|
||||
// clones the reference
|
||||
Registerable* innerBase = base.clone(true);
|
||||
|
||||
// registers the base
|
||||
registerObject(innerBase);
|
||||
|
||||
return innerBase->ID;
|
||||
}
|
||||
|
||||
Registerable* SPKFactory::get(SPK_ID ID)
|
||||
{
|
||||
std::map<SPK_ID,Registerable*>::iterator it = SPKRegister.find(ID);
|
||||
if (it != SPKRegister.end()) // the ID was found
|
||||
return it->second;
|
||||
return NULL; // the ID is not registered
|
||||
}
|
||||
|
||||
Registerable* SPKFactory::copy(SPK_ID ID)
|
||||
{
|
||||
// Clears the adresses set
|
||||
SPKAdresses.clear();
|
||||
|
||||
std::map<SPK_ID,Registerable*>::iterator it = SPKRegister.find(ID);
|
||||
if (it != SPKRegister.end()) // the ID was found
|
||||
return registerObject(it->second->clone(false)); // registers a copy
|
||||
return NULL; // the ID is not registered
|
||||
}
|
||||
|
||||
Registerable* SPKFactory::copy(const Registerable* registerable)
|
||||
{
|
||||
// Clears the adresses set
|
||||
SPKAdresses.clear();
|
||||
|
||||
if (registerable->isRegistered())
|
||||
return registerObject(registerable->clone(false)); // registers a copy
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool SPKFactory::destroy(SPK_ID ID,bool checkNbReferences)
|
||||
{
|
||||
std::map<SPK_ID,Registerable*>::iterator it = SPKRegister.find(ID);
|
||||
|
||||
if ((it != SPKRegister.end())&& // the ID was found
|
||||
((!checkNbReferences)||
|
||||
(it->second->getNbReferences() == 0)))
|
||||
{
|
||||
unregisterObject(it,false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // the ID is not registered
|
||||
}
|
||||
|
||||
bool SPKFactory::destroy(Registerable* object,bool checkNbReferences)
|
||||
{
|
||||
if (object == NULL)
|
||||
return false;
|
||||
|
||||
return destroy(object->getSPKID(),checkNbReferences);
|
||||
}
|
||||
|
||||
void SPKFactory::destroyAll()
|
||||
{
|
||||
std::map<SPK_ID,Registerable*>::iterator it;
|
||||
while((it = SPKRegister.begin()) != SPKRegister.end())
|
||||
unregisterObject(it,true);
|
||||
}
|
||||
|
||||
Registerable* SPKFactory::findByName(const std::string& name)
|
||||
{
|
||||
for (std::map<SPK_ID,Registerable*>::const_iterator it = SPKRegister.begin(); it != SPKRegister.end(); ++it)
|
||||
if (it->second->getName().compare(name) == 0)
|
||||
return it->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SPKFactory::trace(SPK_ID ID)
|
||||
{
|
||||
std::map<SPK_ID,Registerable*>::iterator it = SPKRegister.find(ID);
|
||||
if (it != SPKRegister.end()) // the ID was found
|
||||
traceObject(it,true);
|
||||
else // the ID is not registered
|
||||
std::cout << "No object registered in the SPKFactory with this ID";
|
||||
}
|
||||
|
||||
void SPKFactory::trace(const Registerable* registerable)
|
||||
{
|
||||
trace(registerable->getSPKID());
|
||||
}
|
||||
|
||||
void SPKFactory::traceAll()
|
||||
{
|
||||
std::cout << "Nb of objects in the SPKFactory : " << getNbObjects() << std::endl;
|
||||
for (std::map<SPK_ID,Registerable*>::iterator it = SPKRegister.begin(); it != SPKRegister.end(); ++it)
|
||||
traceObject(it,true);
|
||||
}
|
||||
|
||||
void SPKFactory::traceObject(const std::map<SPK_ID,Registerable*>::iterator& it,bool nextLine)
|
||||
{
|
||||
SPK_ID ID = it->first;
|
||||
Registerable* object = it->second;
|
||||
std::cout << object
|
||||
<< " ID:" << ID
|
||||
<< " type:" << object->getClassName().c_str()
|
||||
<< " nbRef:" << object->getNbReferences()
|
||||
<< " flag:";
|
||||
if (object->isShared()) std::cout << "S";
|
||||
if (object->isDestroyable()) std::cout << "D";
|
||||
if (object->getName().length() > 0) std::cout << " \"" << object->getName() << "\"";
|
||||
if (nextLine) std::cout << std::endl;
|
||||
}
|
||||
|
||||
Registerable* SPKFactory::registerObject(Registerable* object)
|
||||
{
|
||||
object->onRegister();
|
||||
object->ID = ++currentID;
|
||||
|
||||
// optimisation at the insertion to get an amortized constant complexity instead of a logarithmic complexity
|
||||
SPKRegister.insert(SPKRegister.size() != 0 ? --SPKRegister.end() : SPKRegister.begin(),
|
||||
std::pair<SPK_ID,Registerable*>(object->ID,object));
|
||||
|
||||
// Traces allocations
|
||||
#ifdef SPK_DEBUG
|
||||
++nbAlloc;
|
||||
std::cout << "REGISTER ";
|
||||
traceObject(SPKRegister.find(object->ID),false);
|
||||
std::cout << " nbAlloc:" << nbAlloc << " nbObj:" << getNbObjects() << std::endl;
|
||||
#endif
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void SPKFactory::unregisterObject(std::map<SPK_ID,Registerable*>::iterator& it,bool keepChildren)
|
||||
{
|
||||
Registerable* object = it->second;
|
||||
object->onUnregister();
|
||||
|
||||
// traces desallocations
|
||||
#ifdef SPK_DEBUG
|
||||
++nbDesalloc;
|
||||
std::cout << "UNREGISTER ";
|
||||
traceObject(it,false);
|
||||
std::cout << " nbDesalloc:" << nbDesalloc << " nbObj:" << getNbObjects() - 1 << std::endl;
|
||||
#endif
|
||||
|
||||
SPKRegister.erase(it); // unregister object
|
||||
object->ID = NO_ID;
|
||||
object->destroyChildren(keepChildren); // unregister and destroy registered children
|
||||
delete object; // destroy object
|
||||
}
|
||||
|
||||
bool SPKFactory::unregisterObject(SPK_ID ID,bool keepChildren)
|
||||
{
|
||||
std::map<SPK_ID,Registerable*>::iterator it = SPKRegister.find(ID);
|
||||
if (it != SPKRegister.end()) // the ID was found
|
||||
{
|
||||
unregisterObject(it,keepChildren);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
746
libs/spark/src/Core/SPK_Group.cpp
Normal file
746
libs/spark/src/Core/SPK_Group.cpp
Normal file
@@ -0,0 +1,746 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Group.h"
|
||||
#include "Core/SPK_Emitter.h"
|
||||
#include "Core/SPK_Modifier.h"
|
||||
#include "Core/SPK_Renderer.h"
|
||||
#include "Core/SPK_Factory.h"
|
||||
#include "Core/SPK_Buffer.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
bool Group::bufferManagement = true;
|
||||
|
||||
Group::Group(Model* m,size_t capacity) :
|
||||
Registerable(),
|
||||
Transformable(),
|
||||
model(m != NULL ? m : &getDefaultModel()),
|
||||
renderer(NULL),
|
||||
friction(0.0f),
|
||||
gravity(Vector3D()),
|
||||
pool(Pool<Particle>(capacity)),
|
||||
particleData(new Particle::ParticleData[capacity]),
|
||||
particleCurrentParams(new float[capacity * model->getSizeOfParticleCurrentArray()]),
|
||||
particleExtendedParams(new float[capacity * model->getSizeOfParticleExtendedArray()]),
|
||||
sortingEnabled(false),
|
||||
distanceComputationEnabled(false),
|
||||
creationBuffer(),
|
||||
nbBufferedParticles(0),
|
||||
fupdate(NULL),
|
||||
fbirth(NULL),
|
||||
fdeath(NULL),
|
||||
boundingBoxEnabled(false),
|
||||
emitters(),
|
||||
modifiers(),
|
||||
activeModifiers(),
|
||||
additionalBuffers(),
|
||||
swappableBuffers()
|
||||
{}
|
||||
|
||||
Group::Group(const Group& group) :
|
||||
Registerable(group),
|
||||
Transformable(group),
|
||||
model(group.model),
|
||||
renderer(group.renderer),
|
||||
friction(group.friction),
|
||||
gravity(group.gravity),
|
||||
pool(group.pool),
|
||||
sortingEnabled(group.sortingEnabled),
|
||||
distanceComputationEnabled(group.distanceComputationEnabled),
|
||||
creationBuffer(group.creationBuffer),
|
||||
nbBufferedParticles(group.nbBufferedParticles),
|
||||
fupdate(group.fupdate),
|
||||
fbirth(group.fbirth),
|
||||
fdeath(group.fdeath),
|
||||
boundingBoxEnabled(group.boundingBoxEnabled),
|
||||
emitters(group.emitters),
|
||||
modifiers(group.modifiers),
|
||||
activeModifiers(group.activeModifiers.capacity()),
|
||||
additionalBuffers(),
|
||||
swappableBuffers()
|
||||
{
|
||||
particleData = new Particle::ParticleData[pool.getNbReserved()];
|
||||
particleCurrentParams = new float[pool.getNbReserved() * model->getSizeOfParticleCurrentArray()];
|
||||
particleExtendedParams = new float[pool.getNbReserved() * model->getSizeOfParticleExtendedArray()];
|
||||
|
||||
memcpy(particleData,group.particleData,pool.getNbTotal() * sizeof(Particle::ParticleData));
|
||||
memcpy(particleCurrentParams,group.particleCurrentParams,pool.getNbTotal() * sizeof(float) * model->getSizeOfParticleCurrentArray());
|
||||
memcpy(particleExtendedParams,group.particleExtendedParams,pool.getNbTotal() * sizeof(float) * model->getSizeOfParticleExtendedArray());
|
||||
|
||||
for (Pool<Particle>::iterator it = pool.begin(); it != pool.endInactive(); ++it)
|
||||
{
|
||||
it->group = this;
|
||||
it->data = particleData + it->index;
|
||||
it->currentParams = particleCurrentParams + it->index * model->getSizeOfParticleCurrentArray();
|
||||
it->extendedParams = particleExtendedParams + it->index * model->getSizeOfParticleExtendedArray();
|
||||
}
|
||||
}
|
||||
|
||||
Group::~Group()
|
||||
{
|
||||
delete[] particleData;
|
||||
delete[] particleCurrentParams;
|
||||
delete[] particleExtendedParams;
|
||||
|
||||
// destroys additional buffers
|
||||
destroyAllBuffers();
|
||||
}
|
||||
|
||||
void Group::registerChildren(bool registerAll)
|
||||
{
|
||||
Registerable::registerChildren(registerAll);
|
||||
|
||||
registerChild(model,registerAll);
|
||||
registerChild(renderer,registerAll);
|
||||
|
||||
for (std::vector<Emitter*>::const_iterator it = emitters.begin(); it != emitters.end(); ++it)
|
||||
registerChild(*it,registerAll);
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
registerChild(*it,registerAll);
|
||||
}
|
||||
|
||||
void Group::copyChildren(const Group& group,bool createBase)
|
||||
{
|
||||
Registerable::copyChildren(group,createBase);
|
||||
|
||||
model = dynamic_cast<Model*>(copyChild(group.model,createBase));
|
||||
renderer = dynamic_cast<Renderer*>(copyChild(group.renderer,createBase));
|
||||
|
||||
// we clear the copies of pointers pushed in the vectors by the copy constructor
|
||||
emitters.clear();
|
||||
modifiers.clear();
|
||||
|
||||
for (std::vector<Emitter*>::const_iterator it = group.emitters.begin(); it != group.emitters.end(); ++it)
|
||||
emitters.push_back(dynamic_cast<Emitter*>(copyChild(*it,createBase)));
|
||||
for (std::vector<Modifier*>::const_iterator it = group.modifiers.begin(); it != group.modifiers.end(); ++it)
|
||||
modifiers.push_back(dynamic_cast<Modifier*>(copyChild(*it,createBase)));
|
||||
}
|
||||
|
||||
void Group::destroyChildren(bool keepChildren)
|
||||
{
|
||||
destroyChild(model,keepChildren);
|
||||
destroyChild(renderer,keepChildren);
|
||||
|
||||
for (std::vector<Emitter*>::const_iterator it = emitters.begin(); it != emitters.end(); ++it)
|
||||
destroyChild(*it,keepChildren);
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
destroyChild(*it,keepChildren);
|
||||
|
||||
Registerable::destroyChildren(keepChildren);
|
||||
}
|
||||
|
||||
Registerable* Group::findByName(const std::string& name)
|
||||
{
|
||||
Registerable* object = Registerable::findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
|
||||
object = model->findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
|
||||
if (renderer != NULL)
|
||||
{
|
||||
object = renderer->findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
}
|
||||
|
||||
for (std::vector<Emitter*>::const_iterator it = emitters.begin(); it != emitters.end(); ++it)
|
||||
{
|
||||
object = (*it)->findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
}
|
||||
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
{
|
||||
object = (*it)->findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Group::setModel(Model* newmodel)
|
||||
{
|
||||
if(!newmodel) newmodel = &getDefaultModel();
|
||||
if(model == newmodel) return;
|
||||
|
||||
// empty and change model
|
||||
empty();
|
||||
|
||||
decrementChildReference(model);
|
||||
incrementChildReference(newmodel);
|
||||
model = newmodel;
|
||||
|
||||
// recreate data
|
||||
delete[] particleData;
|
||||
delete[] particleCurrentParams;
|
||||
delete[] particleExtendedParams;
|
||||
|
||||
particleData = new Particle::ParticleData[pool.getNbReserved()];
|
||||
particleCurrentParams = new float[pool.getNbReserved() * model->getSizeOfParticleCurrentArray()];
|
||||
particleExtendedParams = new float[pool.getNbReserved() * model->getSizeOfParticleExtendedArray()];
|
||||
|
||||
pool.clear();
|
||||
|
||||
// Destroys all the buffers
|
||||
destroyAllBuffers();
|
||||
}
|
||||
|
||||
void Group::setRenderer(Renderer* renderer)
|
||||
{
|
||||
decrementChildReference(this->renderer);
|
||||
incrementChildReference(renderer);
|
||||
|
||||
if ((bufferManagement)&&(renderer != this->renderer))
|
||||
{
|
||||
if (this->renderer != NULL) this->renderer->destroyBuffers(*this);
|
||||
if (renderer != NULL) renderer->createBuffers(*this);
|
||||
}
|
||||
|
||||
this->renderer = renderer;
|
||||
}
|
||||
|
||||
void Group::addEmitter(Emitter* emitter)
|
||||
{
|
||||
if (emitter == NULL)
|
||||
return;
|
||||
|
||||
// Checks if the emitter is already in the group (since 1.03.03)
|
||||
std::vector<Emitter*>::const_iterator it = std::find(emitters.begin(),emitters.end(),emitter);
|
||||
if (it != emitters.end())
|
||||
return;
|
||||
|
||||
incrementChildReference(emitter);
|
||||
emitters.push_back(emitter);
|
||||
}
|
||||
|
||||
void Group::removeEmitter(Emitter* emitter)
|
||||
{
|
||||
std::vector<Emitter*>::iterator it = std::find(emitters.begin(),emitters.end(),emitter);
|
||||
if (it != emitters.end())
|
||||
{
|
||||
decrementChildReference(emitter);
|
||||
emitters.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void Group::addModifier(Modifier* modifier)
|
||||
{
|
||||
if (modifier == NULL)
|
||||
return;
|
||||
|
||||
incrementChildReference(modifier);
|
||||
|
||||
if (bufferManagement)
|
||||
modifier->createBuffers(*this);
|
||||
|
||||
modifiers.push_back(modifier);
|
||||
}
|
||||
|
||||
void Group::removeModifier(Modifier* modifier)
|
||||
{
|
||||
std::vector<Modifier*>::iterator it = std::find(modifiers.begin(),modifiers.end(),modifier);
|
||||
if (it != modifiers.end())
|
||||
{
|
||||
decrementChildReference(modifier);
|
||||
|
||||
if (bufferManagement)
|
||||
(*it)->createBuffers(*this);
|
||||
|
||||
modifiers.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
bool Group::update(float deltaTime)
|
||||
{
|
||||
unsigned int nbManualBorn = nbBufferedParticles;
|
||||
unsigned int nbAutoBorn = 0;
|
||||
|
||||
bool hasActiveEmitters = false;
|
||||
|
||||
// Updates emitters
|
||||
activeEmitters.clear();
|
||||
std::vector<Emitter*>::const_iterator endIt = emitters.end();
|
||||
for (std::vector<Emitter*>::const_iterator it = emitters.begin(); it != endIt; ++it)
|
||||
{
|
||||
if ((*it)->isActive())
|
||||
{
|
||||
int nb = (*it)->updateNumber(deltaTime);
|
||||
if (nb > 0)
|
||||
{
|
||||
EmitterData data = {*it,nb};
|
||||
activeEmitters.push_back(data);
|
||||
nbAutoBorn += nb;
|
||||
}
|
||||
}
|
||||
|
||||
hasActiveEmitters |= !((*it)->isSleeping());
|
||||
}
|
||||
std::vector<EmitterData>::iterator emitterIt = activeEmitters.begin();
|
||||
|
||||
unsigned int nbBorn = nbAutoBorn + nbManualBorn;
|
||||
|
||||
// Inits bounding box
|
||||
if (boundingBoxEnabled)
|
||||
{
|
||||
const float maxFloat = std::numeric_limits<float>::max();
|
||||
AABBMin.set(maxFloat,maxFloat,maxFloat);
|
||||
AABBMax.set(-maxFloat,-maxFloat,-maxFloat);
|
||||
}
|
||||
|
||||
// Prepare modifiers for processing
|
||||
activeModifiers.clear();
|
||||
for (std::vector<Modifier*>::iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
{
|
||||
(*it)->beginProcess(*this);
|
||||
if ((*it)->isActive())
|
||||
activeModifiers.push_back(*it);
|
||||
}
|
||||
|
||||
// Updates particles
|
||||
for (size_t i = 0; i < pool.getNbActive(); ++i)
|
||||
{
|
||||
if ((pool[i].update(deltaTime))||((fupdate != NULL)&&((*fupdate)(pool[i],deltaTime))))
|
||||
{
|
||||
if (fdeath != NULL)
|
||||
(*fdeath)(pool[i]);
|
||||
|
||||
if (nbBorn > 0)
|
||||
{
|
||||
pool[i].init();
|
||||
launchParticle(pool[i],emitterIt,nbManualBorn);
|
||||
--nbBorn;
|
||||
}
|
||||
else
|
||||
{
|
||||
particleData[i].sqrDist = 0.0f;
|
||||
pool.makeInactive(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (boundingBoxEnabled)
|
||||
updateAABB(pool[i]);
|
||||
|
||||
if (distanceComputationEnabled)
|
||||
pool[i].computeSqrDist();
|
||||
}
|
||||
}
|
||||
|
||||
// Terminates modifiers processing
|
||||
for (std::vector<Modifier*>::iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
(*it)->endProcess(*this);
|
||||
|
||||
// Emits new particles if some left
|
||||
for (int i = nbBorn; i > 0; --i)
|
||||
pushParticle(emitterIt,nbManualBorn);
|
||||
|
||||
// Sorts particles if enabled
|
||||
if ((sortingEnabled)&&(pool.getNbActive() > 1))
|
||||
sortParticles(0,pool.getNbActive() - 1);
|
||||
|
||||
if ((!boundingBoxEnabled)||(pool.getNbActive() == 0))
|
||||
{
|
||||
AABBMin.set(0.0f,0.0f,0.0f);
|
||||
AABBMax.set(0.0f,0.0f,0.0f);
|
||||
}
|
||||
|
||||
return (hasActiveEmitters)||(pool.getNbActive() > 0);
|
||||
}
|
||||
|
||||
void Group::pushParticle(std::vector<EmitterData>::iterator& emitterIt,unsigned int& nbManualBorn)
|
||||
{
|
||||
Particle* ptr = pool.makeActive();
|
||||
if (ptr == NULL)
|
||||
{
|
||||
if (pool.getNbEmpty() > 0)
|
||||
{
|
||||
Particle p(this,pool.getNbActive());
|
||||
launchParticle(p,emitterIt,nbManualBorn);
|
||||
pool.pushActive(p);
|
||||
}
|
||||
else if (nbManualBorn > 0)
|
||||
popNextManualAdding(nbManualBorn);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr->init();
|
||||
launchParticle(*ptr,emitterIt,nbManualBorn);
|
||||
}
|
||||
}
|
||||
|
||||
void Group::launchParticle(Particle& p,std::vector<EmitterData>::iterator& emitterIt,unsigned int& nbManualBorn)
|
||||
{
|
||||
if (nbManualBorn == 0)
|
||||
{
|
||||
emitterIt->emitter->emit(p);
|
||||
if (--emitterIt->nbParticles == 0)
|
||||
++emitterIt;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreationData creationData = creationBuffer.front();
|
||||
|
||||
if (creationData.zone != NULL)
|
||||
creationData.zone->generatePosition(p,creationData.full);
|
||||
else
|
||||
p.position() = creationData.position;
|
||||
|
||||
if (creationData.emitter != NULL)
|
||||
creationData.emitter->generateVelocity(p);
|
||||
else
|
||||
p.velocity() = creationData.velocity;
|
||||
|
||||
popNextManualAdding(nbManualBorn);
|
||||
}
|
||||
|
||||
// Resets old position (fix 1.04.00)
|
||||
p.oldPosition() = p.position();
|
||||
|
||||
// first parameter interpolation
|
||||
// must be here so that the velocity has already been initialized
|
||||
p.interpolateParameters();
|
||||
|
||||
if (fbirth != NULL)
|
||||
(*fbirth)(p);
|
||||
|
||||
if (boundingBoxEnabled)
|
||||
updateAABB(p);
|
||||
|
||||
if (distanceComputationEnabled)
|
||||
p.computeSqrDist();
|
||||
}
|
||||
|
||||
void Group::render()
|
||||
{
|
||||
if ((renderer == NULL)||(!renderer->isActive()))
|
||||
return;
|
||||
|
||||
renderer->render(*this);
|
||||
}
|
||||
|
||||
void Group::empty()
|
||||
{
|
||||
for (size_t i = 0; i < pool.getNbActive(); ++i)
|
||||
particleData[i].sqrDist = 0.0f;
|
||||
|
||||
pool.makeAllInactive();
|
||||
creationBuffer.clear();
|
||||
nbBufferedParticles = 0;
|
||||
}
|
||||
|
||||
void Group::flushAddedParticles()
|
||||
{
|
||||
unsigned int nbManualBorn = nbBufferedParticles;
|
||||
std::vector<EmitterData>::iterator emitterIt; // dummy emitterIt because we dont care
|
||||
while(nbManualBorn > 0)
|
||||
pushParticle(emitterIt,nbManualBorn);
|
||||
}
|
||||
|
||||
float Group::addParticles(const Vector3D& start,const Vector3D& end,Emitter* emitter,float step,float offset)
|
||||
{
|
||||
if ((step <= 0.0f)||(offset < 0.0f))
|
||||
return 0.0f;
|
||||
|
||||
Vector3D displacement = end - start;
|
||||
float totalDist = displacement.getNorm();
|
||||
|
||||
while(offset < totalDist)
|
||||
{
|
||||
Vector3D position = start;
|
||||
position += displacement * offset / totalDist;
|
||||
addParticles(1,position,Vector3D(),NULL,emitter);
|
||||
offset += step;
|
||||
}
|
||||
|
||||
return offset - totalDist;
|
||||
}
|
||||
|
||||
float Group::addParticles(const Vector3D& start,const Vector3D& end,const Vector3D& velocity,float step,float offset)
|
||||
{
|
||||
if ((step <= 0.0f)||(offset < 0.0f))
|
||||
return 0.0f;
|
||||
|
||||
Vector3D displacement = end - start;
|
||||
float totalDist = displacement.getNorm();
|
||||
|
||||
while(offset < totalDist)
|
||||
{
|
||||
Vector3D position = start;
|
||||
position += displacement * (offset / totalDist);
|
||||
addParticles(1,position,velocity,NULL,NULL);
|
||||
offset += step;
|
||||
}
|
||||
|
||||
return offset - totalDist;
|
||||
}
|
||||
|
||||
void Group::addParticles(unsigned int nb,const Vector3D& position,const Vector3D& velocity,const Zone* zone,Emitter* emitter,bool full)
|
||||
{
|
||||
if (nb == 0)
|
||||
return;
|
||||
|
||||
CreationData data = {nb,position,velocity,zone,emitter,full};
|
||||
creationBuffer.push_back(data);
|
||||
nbBufferedParticles += nb;
|
||||
}
|
||||
|
||||
void Group::addParticles(unsigned int nb,Emitter* emitter)
|
||||
{
|
||||
addParticles(nb,Vector3D(),Vector3D(),emitter->getZone(),emitter,emitter->isFullZone());
|
||||
}
|
||||
|
||||
void Group::addParticles(const Zone* zone,Emitter* emitter,float deltaTime,bool full)
|
||||
{
|
||||
addParticles(emitter->updateNumber(deltaTime),Vector3D(),Vector3D(),zone,emitter,full);
|
||||
}
|
||||
|
||||
void Group::addParticles(const Vector3D& position,Emitter* emitter,float deltaTime)
|
||||
{
|
||||
addParticles(emitter->updateNumber(deltaTime),position,Vector3D(),NULL,emitter);
|
||||
}
|
||||
|
||||
void Group::addParticles(Emitter* emitter,float deltaTime)
|
||||
{
|
||||
addParticles(emitter->updateNumber(deltaTime),Vector3D(),Vector3D(),emitter->getZone(),emitter,emitter->isFullZone());
|
||||
}
|
||||
|
||||
void Group::sortParticles()
|
||||
{
|
||||
computeDistances();
|
||||
|
||||
if (sortingEnabled)
|
||||
sortParticles(0,pool.getNbActive() - 1);
|
||||
}
|
||||
|
||||
void Group::computeDistances()
|
||||
{
|
||||
if (!distanceComputationEnabled)
|
||||
return;
|
||||
|
||||
Pool<Particle>::const_iterator endIt = pool.end();
|
||||
for (Pool<Particle>::iterator it = pool.begin(); it != endIt; ++it)
|
||||
it->computeSqrDist();
|
||||
}
|
||||
|
||||
void Group::computeAABB()
|
||||
{
|
||||
if ((!boundingBoxEnabled)||(pool.getNbActive() == 0))
|
||||
{
|
||||
AABBMin.set(0.0f,0.0f,0.0f);
|
||||
AABBMax.set(0.0f,0.0f,0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
const float maxFloat = std::numeric_limits<float>::max();
|
||||
AABBMin.set(maxFloat,maxFloat,maxFloat);
|
||||
AABBMax.set(-maxFloat,-maxFloat,-maxFloat);
|
||||
|
||||
Pool<Particle>::iterator endIt = pool.end();
|
||||
for (Pool<Particle>::iterator it = pool.begin(); it != endIt; ++it)
|
||||
updateAABB(*it);
|
||||
}
|
||||
|
||||
void Group::reallocate(size_t capacity)
|
||||
{
|
||||
if (capacity > pool.getNbReserved())
|
||||
{
|
||||
pool.reallocate(capacity);
|
||||
|
||||
Particle::ParticleData* newData = new Particle::ParticleData[pool.getNbReserved()];
|
||||
float* newCurrentParams = new float[pool.getNbReserved() * model->getSizeOfParticleCurrentArray()];
|
||||
float* newExtendedParams = new float[pool.getNbReserved() * model->getSizeOfParticleExtendedArray()];
|
||||
|
||||
memcpy(newData,particleData,pool.getNbTotal() * sizeof(Particle::ParticleData));
|
||||
memcpy(newCurrentParams,particleCurrentParams,pool.getNbTotal() * sizeof(float) * model->getSizeOfParticleCurrentArray());
|
||||
memcpy(newExtendedParams,particleExtendedParams,pool.getNbTotal() * sizeof(float) * model->getSizeOfParticleExtendedArray());
|
||||
|
||||
delete[] particleData;
|
||||
delete[] particleCurrentParams;
|
||||
delete[] particleExtendedParams;
|
||||
|
||||
particleData = newData;
|
||||
particleCurrentParams = newCurrentParams;
|
||||
particleExtendedParams = newExtendedParams;
|
||||
|
||||
for (Pool<Particle>::iterator it = pool.begin(); it != pool.endInactive(); ++it)
|
||||
{
|
||||
it->group = this;
|
||||
it->data = particleData + it->index;
|
||||
it->currentParams = particleCurrentParams + it->index * model->getSizeOfParticleCurrentArray();
|
||||
it->extendedParams = particleExtendedParams + it->index * model->getSizeOfParticleExtendedArray();
|
||||
}
|
||||
|
||||
// Destroys all the buffers
|
||||
destroyAllBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
void Group::popNextManualAdding(unsigned int& nbManualBorn)
|
||||
{
|
||||
--creationBuffer.front().nb;
|
||||
--nbManualBorn;
|
||||
--nbBufferedParticles;
|
||||
if (creationBuffer.front().nb <= 0)
|
||||
creationBuffer.pop_front();
|
||||
}
|
||||
|
||||
void Group::updateAABB(const Particle& particle)
|
||||
{
|
||||
const Vector3D& position = particle.position();
|
||||
if (AABBMin.x > position.x)
|
||||
AABBMin.x = position.x;
|
||||
if (AABBMin.y > position.y)
|
||||
AABBMin.y = position.y;
|
||||
if (AABBMin.z > position.z)
|
||||
AABBMin.z = position.z;
|
||||
if (AABBMax.x < position.x)
|
||||
AABBMax.x = position.x;
|
||||
if (AABBMax.y < position.y)
|
||||
AABBMax.y = position.y;
|
||||
if (AABBMax.z < position.z)
|
||||
AABBMax.z = position.z;
|
||||
}
|
||||
|
||||
const void* Group::getParamAddress(ModelParam param) const
|
||||
{
|
||||
return particleCurrentParams + model->getParameterOffset(param);
|
||||
}
|
||||
|
||||
size_t Group::getParamStride() const
|
||||
{
|
||||
return model->getSizeOfParticleCurrentArray() * sizeof(float);
|
||||
}
|
||||
|
||||
Buffer* Group::createBuffer(const std::string& ID,const BufferCreator& creator,unsigned int flag,bool swapEnabled) const
|
||||
{
|
||||
destroyBuffer(ID);
|
||||
|
||||
Buffer* buffer = creator.createBuffer(pool.getNbReserved(),*this);
|
||||
|
||||
buffer->flag = flag;
|
||||
buffer->swapEnabled = swapEnabled;
|
||||
|
||||
additionalBuffers.insert(std::pair<std::string,Buffer*>(ID,buffer));
|
||||
if (swapEnabled)
|
||||
swappableBuffers.insert(buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void Group::destroyBuffer(const std::string& ID) const
|
||||
{
|
||||
std::map<std::string,Buffer*>::iterator it = additionalBuffers.find(ID);
|
||||
|
||||
if (it != additionalBuffers.end())
|
||||
{
|
||||
if (it->second->isSwapEnabled())
|
||||
swappableBuffers.erase(it->second);
|
||||
delete it->second;
|
||||
additionalBuffers.erase(it);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Group::destroyAllBuffers() const
|
||||
{
|
||||
for (std::map<std::string,Buffer*>::const_iterator it = additionalBuffers.begin(); it != additionalBuffers.end(); ++it)
|
||||
delete it->second;
|
||||
additionalBuffers.clear();
|
||||
swappableBuffers.clear();
|
||||
}
|
||||
|
||||
Buffer* Group::getBuffer(const std::string& ID,unsigned int flag) const
|
||||
{
|
||||
Buffer* buffer = getBuffer(ID);
|
||||
|
||||
if ((buffer != NULL)&&(buffer->flag == flag))
|
||||
return buffer;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Buffer* Group::getBuffer(const std::string& ID) const
|
||||
{
|
||||
std::map<std::string,Buffer*>::const_iterator it = additionalBuffers.find(ID);
|
||||
|
||||
if (it != additionalBuffers.end())
|
||||
return it->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Group::enableBuffersManagement(bool manage)
|
||||
{
|
||||
bufferManagement = manage;
|
||||
}
|
||||
|
||||
bool Group::isBuffersManagementEnabled()
|
||||
{
|
||||
return bufferManagement;
|
||||
}
|
||||
|
||||
void Group::sortParticles(int start,int end)
|
||||
{
|
||||
if (start < end)
|
||||
{
|
||||
int i = start - 1;
|
||||
int j = end + 1;
|
||||
float pivot = particleData[(start + end) >> 1].sqrDist;
|
||||
while (true)
|
||||
{
|
||||
do ++i;
|
||||
while (particleData[i].sqrDist > pivot);
|
||||
do --j;
|
||||
while (particleData[j].sqrDist < pivot);
|
||||
if (i < j)
|
||||
swapParticles(pool[i],pool[j]);
|
||||
else break;
|
||||
}
|
||||
|
||||
sortParticles(start,j);
|
||||
sortParticles(j + 1,end);
|
||||
}
|
||||
}
|
||||
|
||||
void Group::propagateUpdateTransform()
|
||||
{
|
||||
for (std::vector<Emitter*>::const_iterator emitterIt = emitters.begin(); emitterIt != emitters.end(); ++emitterIt)
|
||||
(*emitterIt)->updateTransform(this);
|
||||
for (std::vector<Modifier*>::const_iterator modifierIt = modifiers.begin(); modifierIt != modifiers.end(); ++modifierIt)
|
||||
if ((*modifierIt)->isLocalToSystem())
|
||||
(*modifierIt)->updateTransform(this);
|
||||
}
|
||||
|
||||
Model& Group::getDefaultModel()
|
||||
{
|
||||
static Model defaultModel;
|
||||
return defaultModel;
|
||||
}
|
||||
}
|
148
libs/spark/src/Core/SPK_Interpolator.cpp
Normal file
148
libs/spark/src/Core/SPK_Interpolator.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Interpolator.h"
|
||||
#include "Core/SPK_Model.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Interpolator::computeXFn Interpolator::COMPUTE_X_FN[4] =
|
||||
{
|
||||
&Interpolator::computeXLifeTime,
|
||||
&Interpolator::computeXAge,
|
||||
&Interpolator::computeXParam,
|
||||
&Interpolator::computeXVelocity,
|
||||
};
|
||||
|
||||
Interpolator::Interpolator() :
|
||||
graph(),
|
||||
type(INTERPOLATOR_LIFETIME),
|
||||
param(PARAM_SIZE),
|
||||
scaleXVariation(0.0f),
|
||||
offsetXVariation(0.0f),
|
||||
loopingEnabled(false)
|
||||
{}
|
||||
|
||||
float Interpolator::computeXLifeTime(const Particle& particle) const
|
||||
{
|
||||
return particle.getAge() / (particle.getAge() + particle.getLifeLeft());
|
||||
}
|
||||
|
||||
float Interpolator::computeXAge(const Particle& particle) const
|
||||
{
|
||||
return particle.getAge();
|
||||
}
|
||||
|
||||
float Interpolator::computeXParam(const Particle& particle) const
|
||||
{
|
||||
return particle.getParamCurrentValue(param);
|
||||
}
|
||||
|
||||
float Interpolator::computeXVelocity(const Particle& particle) const
|
||||
{
|
||||
return particle.velocity().getSqrNorm();
|
||||
}
|
||||
|
||||
float Interpolator::interpolate(const Particle& particle,ModelParam interpolatedParam,float ratioY,float offsetX,float scaleX)
|
||||
{
|
||||
// First finds the current X of the particle
|
||||
InterpolatorEntry currentKey((this->*Interpolator::COMPUTE_X_FN[type])(particle));
|
||||
currentKey.x += offsetX; // Offsets it
|
||||
currentKey.x *= scaleX; // Scales it
|
||||
|
||||
if (loopingEnabled)
|
||||
{
|
||||
// If the graph has les than 2 entries, we cannot loop
|
||||
if (graph.size() < 2)
|
||||
{
|
||||
if (graph.empty())
|
||||
return Model::getDefaultValue(interpolatedParam);
|
||||
else
|
||||
return interpolateY(*(graph.begin()),ratioY);
|
||||
}
|
||||
|
||||
// Else finds the current X in the range
|
||||
float newX = (currentKey.x - graph.begin()->x) / (graph.rbegin()->x - graph.begin()->x);
|
||||
newX -= static_cast<int>(newX);
|
||||
if (newX < 0.0f)
|
||||
newX = 1.0f + newX;
|
||||
currentKey.x = graph.begin()->x + newX * (graph.rbegin()->x - graph.begin()->x);
|
||||
}
|
||||
|
||||
// Gets the entry that is immediatly after the current X
|
||||
std::set<InterpolatorEntry>::const_iterator nextIt = graph.upper_bound(currentKey);
|
||||
|
||||
// If the current X is higher than the one of the last entry
|
||||
if (nextIt == graph.end())
|
||||
{
|
||||
if (graph.empty()) // If the graph has no entry, sets the default value
|
||||
return Model::getDefaultValue(interpolatedParam);
|
||||
else // Else sets the value of the last entry
|
||||
return interpolateY(*(--nextIt),ratioY);
|
||||
}
|
||||
else if (nextIt == graph.begin()) // If the current X is lower than the first entry, sets the value to the first entry
|
||||
{
|
||||
return interpolateY(*nextIt,ratioY);
|
||||
}
|
||||
else // Else interpolated between the entries before and after the current X
|
||||
{
|
||||
const InterpolatorEntry& nextEntry = *nextIt;
|
||||
const InterpolatorEntry& previousEntry = *(--nextIt);
|
||||
float y0 = interpolateY(previousEntry,ratioY);
|
||||
float y1 = interpolateY(nextEntry,ratioY);
|
||||
|
||||
float ratioX = (currentKey.x - previousEntry.x) / (nextEntry.x - previousEntry.x);
|
||||
return y0 + ratioX * (y1 - y0);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpolator::generateSinCurve(float period,float amplitudeMin,float amplitudeMax,float offsetX,float offsetY,float startX,unsigned int length,unsigned int nbSamples)
|
||||
{
|
||||
// First clear any previous entry
|
||||
clearGraph();
|
||||
|
||||
const float PI = 3.1415926535897932384626433832795f;
|
||||
|
||||
for (size_t i = 0; i < nbSamples; ++i)
|
||||
{
|
||||
float x = startX + i * period * length / (nbSamples - 1);
|
||||
float sin = std::sin((x + offsetX) * 2 * PI / period);
|
||||
addEntry(x,amplitudeMin * sin + offsetY,amplitudeMax * sin + offsetY);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpolator::generatePolyCurve(float constant,float linear,float quadratic,float cubic,float startX,float endX,unsigned int nbSamples)
|
||||
{
|
||||
// First clear any previous entry
|
||||
clearGraph();
|
||||
|
||||
for (size_t i = 0; i < nbSamples; ++i)
|
||||
{
|
||||
float x = startX + i * (endX - startX) / (nbSamples - 1);
|
||||
float x2 = x * x;
|
||||
float x3 = x2 * x;
|
||||
addEntry(x,constant + x * linear + x2 * quadratic + x3 * cubic);
|
||||
}
|
||||
}
|
||||
}
|
299
libs/spark/src/Core/SPK_Model.cpp
Normal file
299
libs/spark/src/Core/SPK_Model.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Model.h"
|
||||
#include "Core/SPK_Interpolator.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
const float Model::DEFAULT_VALUES[NB_PARAMS] =
|
||||
{
|
||||
1.0f, // RED
|
||||
1.0f, // GREEN
|
||||
1.0f, // BLUE
|
||||
1.0f, // ALPHA
|
||||
1.0f, // SIZE
|
||||
1.0f, // MASS
|
||||
0.0f, // ANGLE
|
||||
0.0f, // TEXTURE_INDEX
|
||||
0.0f, // ROTATION_SPEED
|
||||
0.0f, // CUSTOM_0
|
||||
0.0f, // CUSTOM_1
|
||||
0.0f, // CUSTOM_2
|
||||
};
|
||||
|
||||
Model::Model(int enableFlag,int mutableFlag,int randomFlag,int interpolatedFlag) :
|
||||
Registerable(),
|
||||
lifeTimeMin(1.0f),
|
||||
lifeTimeMax(1.0f),
|
||||
immortal(false),
|
||||
paramsSize(0),
|
||||
nbEnableParams(0),
|
||||
nbMutableParams(0),
|
||||
nbRandomParams(0),
|
||||
nbInterpolatedParams(0)
|
||||
{
|
||||
enableFlag |= FLAG_RED | FLAG_GREEN | FLAG_BLUE; // Adds the color parameters to the enable flag
|
||||
this->enableFlag = enableFlag & ((1 << (NB_PARAMS + 1)) - 1); // masks the enable flag with the existing parameters
|
||||
this->interpolatedFlag = interpolatedFlag & this->enableFlag; // masks the interpolated flag with the enable flag
|
||||
this->mutableFlag = mutableFlag & this->enableFlag; // masks the mutable flag with the enable flag
|
||||
this->mutableFlag &= ~this->interpolatedFlag; // a param cannot be both interpolated and mutable
|
||||
this->randomFlag = randomFlag & this->enableFlag; // masks the random flag with the enable flag
|
||||
this->randomFlag &= ~this->interpolatedFlag; // a param cannot be both interpolated and random
|
||||
|
||||
int particleEnableParamsSize = 0;
|
||||
int particleMutableParamsSize = 0;
|
||||
for (size_t i = 0; i < NB_PARAMS; ++i)
|
||||
{
|
||||
ModelParam param = static_cast<ModelParam>(i);
|
||||
|
||||
int paramSize = 0;
|
||||
if (isEnabled(param))
|
||||
{
|
||||
++nbEnableParams;
|
||||
if (!isInterpolated(param))
|
||||
{
|
||||
interpolators[i] = NULL;
|
||||
paramSize = 1;
|
||||
if (isMutable(param))
|
||||
{
|
||||
paramSize = 2;
|
||||
++nbMutableParams;
|
||||
}
|
||||
if (isRandom(param))
|
||||
{
|
||||
paramSize <<= 1;
|
||||
++nbRandomParams;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
interpolators[i] = new Interpolator(); // Creates the interpolator
|
||||
++nbInterpolatedParams;
|
||||
}
|
||||
}
|
||||
else
|
||||
interpolators[i] = NULL;
|
||||
|
||||
particleEnableIndices[i] = particleEnableParamsSize;
|
||||
particleMutableIndices[i] = particleMutableParamsSize;
|
||||
particleEnableParamsSize += isEnabled(param) >> i;
|
||||
particleMutableParamsSize += isMutable(param) >> i;
|
||||
|
||||
indices[i] = paramsSize;
|
||||
paramsSize += paramSize;
|
||||
}
|
||||
|
||||
// creates the array of params for this model
|
||||
if (paramsSize > 0)
|
||||
{
|
||||
params = new float[paramsSize];
|
||||
unsigned int currentParamIndex = 0;
|
||||
unsigned int currentIndex = 0;
|
||||
while (currentIndex < paramsSize)
|
||||
{
|
||||
unsigned int nbValues = getNbValues(static_cast<ModelParam>(currentParamIndex));
|
||||
for (size_t i = 0; i < nbValues; ++i)
|
||||
params[currentIndex + i] = DEFAULT_VALUES[currentParamIndex];
|
||||
++currentParamIndex;
|
||||
currentIndex += nbValues;
|
||||
}
|
||||
}
|
||||
else
|
||||
params = NULL;
|
||||
|
||||
if (nbEnableParams > 0)
|
||||
{
|
||||
enableParams = new int[nbEnableParams];
|
||||
size_t index = 0;
|
||||
for (size_t i = 0; i < NB_PARAMS; ++i)
|
||||
if (isEnabled(static_cast<ModelParam>(i)))
|
||||
enableParams[index++] = i;
|
||||
}
|
||||
else
|
||||
enableParams = NULL;
|
||||
|
||||
if (nbMutableParams > 0)
|
||||
{
|
||||
mutableParams = new int[nbMutableParams];
|
||||
size_t index = 0;
|
||||
for (size_t i = 0; i < NB_PARAMS; ++i)
|
||||
if (isMutable(static_cast<ModelParam>(i)))
|
||||
mutableParams[index++] = i;
|
||||
}
|
||||
else
|
||||
mutableParams = NULL;
|
||||
|
||||
if (nbInterpolatedParams > 0)
|
||||
{
|
||||
interpolatedParams = new int[nbInterpolatedParams];
|
||||
size_t index = 0;
|
||||
for (size_t i = 0; i < NB_PARAMS; ++i)
|
||||
if (isInterpolated(static_cast<ModelParam>(i)))
|
||||
interpolatedParams[index++] = i;
|
||||
}
|
||||
else
|
||||
interpolatedParams = NULL;
|
||||
}
|
||||
|
||||
Model::Model(const Model& model) :
|
||||
Registerable(model),
|
||||
lifeTimeMin(model.lifeTimeMin),
|
||||
lifeTimeMax(model.lifeTimeMax),
|
||||
immortal(model.immortal),
|
||||
paramsSize(model.paramsSize),
|
||||
nbEnableParams(model.nbEnableParams),
|
||||
nbMutableParams(model.nbMutableParams),
|
||||
nbRandomParams(model.nbRandomParams),
|
||||
nbInterpolatedParams(model.nbInterpolatedParams),
|
||||
enableFlag(model.enableFlag),
|
||||
mutableFlag(model.mutableFlag),
|
||||
randomFlag(model.randomFlag),
|
||||
interpolatedFlag(model.interpolatedFlag),
|
||||
params(NULL),
|
||||
enableParams(NULL),
|
||||
mutableParams(NULL),
|
||||
interpolatedParams(NULL)
|
||||
{
|
||||
if (paramsSize > 0)
|
||||
{
|
||||
params = new float[paramsSize];
|
||||
for (size_t i = 0; i < paramsSize; ++i)
|
||||
params[i] = model.params[i];
|
||||
}
|
||||
|
||||
if (nbEnableParams > 0)
|
||||
{
|
||||
enableParams = new int[nbEnableParams];
|
||||
for (size_t i = 0; i < nbEnableParams; ++i)
|
||||
enableParams[i] = model.enableParams[i];
|
||||
}
|
||||
|
||||
if (nbMutableParams > 0)
|
||||
{
|
||||
mutableParams = new int[nbMutableParams];
|
||||
for (size_t i = 0; i < nbMutableParams; ++i)
|
||||
mutableParams[i] = model.mutableParams[i];
|
||||
}
|
||||
|
||||
if (nbInterpolatedParams > 0)
|
||||
{
|
||||
interpolatedParams = new int[nbMutableParams];
|
||||
for (size_t i = 0; i < nbInterpolatedParams; ++i)
|
||||
interpolatedParams[i] = model.interpolatedParams[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < NB_PARAMS; ++i)
|
||||
{
|
||||
indices[i] = model.indices[i];
|
||||
particleEnableIndices[i] = model.particleEnableIndices[i];
|
||||
particleMutableIndices[i] = model.particleMutableIndices[i];
|
||||
if (model.interpolators[i] != NULL)
|
||||
interpolators[i] = new Interpolator(*model.interpolators[i]);
|
||||
else
|
||||
interpolators[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Model::~Model()
|
||||
{
|
||||
delete[] enableParams;
|
||||
delete[] mutableParams;
|
||||
delete[] interpolatedParams;
|
||||
delete[] params;
|
||||
|
||||
for (size_t i = 0; i < NB_PARAMS; ++i)
|
||||
delete interpolators[i];
|
||||
}
|
||||
|
||||
bool Model::setParam(ModelParam type,float startMin,float startMax,float endMin,float endMax)
|
||||
{
|
||||
// if the given param doesnt have 4 values, return
|
||||
if (getNbValues(type) != 4)
|
||||
return false;
|
||||
|
||||
// Sets the values at the right position in params
|
||||
float* ptr = params + indices[type];
|
||||
*ptr++ = startMin;
|
||||
*ptr++ = startMax;
|
||||
*ptr++ = endMin;
|
||||
*ptr = endMax;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Model::setParam(ModelParam type,float value0,float value1)
|
||||
{
|
||||
// if the given param doesnt have 2 values, return
|
||||
if (getNbValues(type) != 2)
|
||||
return false;
|
||||
|
||||
// Sets the values at the right position in params
|
||||
float* ptr = params + indices[type];
|
||||
*ptr++ = value0;
|
||||
*ptr = value1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Model::setParam(ModelParam type,float value)
|
||||
{
|
||||
// if the given param doesnt have 1 value, return
|
||||
if (getNbValues(type) != 1)
|
||||
return false;
|
||||
|
||||
// Sets the value at the right position in params
|
||||
params[indices[type]] = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float Model::getParamValue(ModelParam type,size_t index) const
|
||||
{
|
||||
unsigned int nbValues = getNbValues(type);
|
||||
|
||||
if (index < nbValues)
|
||||
return params[indices[type] + index];
|
||||
|
||||
return DEFAULT_VALUES[type];
|
||||
}
|
||||
|
||||
unsigned int Model::getNbValues(ModelParam type) const
|
||||
{
|
||||
int value = 1 << type;
|
||||
if (!(enableFlag & value) || (interpolatedFlag & value))
|
||||
return 0;
|
||||
|
||||
if (!(mutableFlag & value) && !(randomFlag & value))
|
||||
return 1;
|
||||
|
||||
if ((mutableFlag & value) && (randomFlag & value))
|
||||
return 4;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
float Model::getDefaultValue(ModelParam param)
|
||||
{
|
||||
return DEFAULT_VALUES[param];
|
||||
}
|
||||
}
|
100
libs/spark/src/Core/SPK_Modifier.cpp
Normal file
100
libs/spark/src/Core/SPK_Modifier.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Core/SPK_Modifier.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Vector3D Modifier::intersection;
|
||||
Vector3D Modifier::normal;
|
||||
|
||||
Modifier::Modifier(int availableTriggers,ModifierTrigger trigger,bool needsIntersection,bool needsNormal,Zone* zone) :
|
||||
Registerable(),
|
||||
Transformable(),
|
||||
BufferHandler(),
|
||||
availableTriggers(availableTriggers),
|
||||
trigger(trigger),
|
||||
zone(zone),
|
||||
needsIntersection(needsIntersection),
|
||||
needsNormal(needsNormal),
|
||||
full(false),
|
||||
active(true),
|
||||
local(false)
|
||||
{}
|
||||
|
||||
void Modifier::registerChildren(bool registerAll)
|
||||
{
|
||||
Registerable::registerChildren(registerAll);
|
||||
registerChild(zone,registerAll);
|
||||
}
|
||||
|
||||
void Modifier::copyChildren(const Modifier& modifier,bool createBase)
|
||||
{
|
||||
Registerable::copyChildren(modifier,createBase);
|
||||
zone = dynamic_cast<Zone*>(copyChild(modifier.zone,createBase));
|
||||
}
|
||||
|
||||
void Modifier::destroyChildren(bool keepChildren)
|
||||
{
|
||||
destroyChild(zone,keepChildren);
|
||||
Registerable::destroyChildren(keepChildren);
|
||||
}
|
||||
|
||||
Registerable* Modifier::findByName(const std::string& name)
|
||||
{
|
||||
Registerable* object = Registerable::findByName(name);
|
||||
if ((object != NULL)||(zone == NULL))
|
||||
return object;
|
||||
|
||||
return zone->findByName(name);
|
||||
}
|
||||
|
||||
void Modifier::setZone(Zone* zone,bool full)
|
||||
{
|
||||
decrementChildReference(this->zone);
|
||||
incrementChildReference(zone);
|
||||
|
||||
this->zone = zone;
|
||||
this->full = full;
|
||||
}
|
||||
|
||||
bool Modifier::setTrigger(ModifierTrigger trigger)
|
||||
{
|
||||
if ((trigger & availableTriggers) != 0)
|
||||
{
|
||||
this->trigger = trigger;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Modifier::beginProcess(Group& group)
|
||||
{
|
||||
savedActive = active;
|
||||
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
if (!prepareBuffers(group))
|
||||
active = false; // if buffers of the modifier in the group are not ready, the modifier is made incative for the frame
|
||||
}
|
||||
}
|
237
libs/spark/src/Core/SPK_Particle.cpp
Normal file
237
libs/spark/src/Core/SPK_Particle.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Particle.h"
|
||||
#include "Core/SPK_Group.h"
|
||||
#include "Core/SPK_Modifier.h"
|
||||
#include "Core/SPK_System.h"
|
||||
#include "Core/SPK_Buffer.h"
|
||||
#include "Core/SPK_Interpolator.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Particle::Particle(Group* group,size_t index) :
|
||||
group(group),
|
||||
index(index),
|
||||
data(group->particleData + index),
|
||||
currentParams(group->particleCurrentParams + index * group->model->getSizeOfParticleCurrentArray()),
|
||||
extendedParams(group->particleExtendedParams + index * group->model->getSizeOfParticleExtendedArray())
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void Particle::init()
|
||||
{
|
||||
const Model* model = group->getModel();
|
||||
data->age = 0.0f;
|
||||
data->life = random(model->lifeTimeMin,model->lifeTimeMax);
|
||||
|
||||
// creates pseudo-iterators to parse arrays
|
||||
float* particleCurrentIt = currentParams;
|
||||
float* particleMutableIt = extendedParams;
|
||||
float* particleInterpolatedIt = extendedParams + model->nbMutableParams;
|
||||
const int* paramIt = model->enableParams;
|
||||
|
||||
// initializes params
|
||||
for (size_t i = model->nbEnableParams; i != 0; --i)
|
||||
{
|
||||
ModelParam param = static_cast<ModelParam>(*paramIt);
|
||||
const float* templateIt = &model->params[model->indices[param]];
|
||||
|
||||
if (model->isInterpolated(param))
|
||||
{
|
||||
*particleCurrentIt++ = Model::DEFAULT_VALUES[param];
|
||||
*particleInterpolatedIt++ = random(0.0f,1.0f); // ratioY
|
||||
|
||||
Interpolator* interpolator = model->interpolators[param];
|
||||
float offsetVariation = interpolator->getOffsetXVariation();
|
||||
float scaleVariation = interpolator->getScaleXVariation();
|
||||
|
||||
*particleInterpolatedIt++ = random(-offsetVariation,offsetVariation); // offsetX
|
||||
*particleInterpolatedIt++ = 1.0f + random(-scaleVariation,scaleVariation); // scaleX
|
||||
}
|
||||
else if (model->isRandom(param))
|
||||
{
|
||||
*particleCurrentIt++ = random(*templateIt,*(templateIt + 1));
|
||||
if (model->isMutable(param))
|
||||
*particleMutableIt++ = random(*(templateIt + 2),*(templateIt + 3));
|
||||
}
|
||||
else
|
||||
{
|
||||
*particleCurrentIt++ = *templateIt;
|
||||
if (model->isMutable(param))
|
||||
*particleMutableIt++ = *(templateIt + 1);
|
||||
}
|
||||
|
||||
++paramIt;
|
||||
}
|
||||
}
|
||||
|
||||
void Particle::interpolateParameters()
|
||||
{
|
||||
const Model* model = group->getModel();
|
||||
|
||||
float* interpolatedIt = extendedParams + model->nbMutableParams;
|
||||
for (size_t i = 0; i < model->nbInterpolatedParams; ++i)
|
||||
{
|
||||
size_t index = model->interpolatedParams[i];
|
||||
size_t enableIndex = model->particleEnableIndices[index];
|
||||
currentParams[enableIndex] = model->interpolators[index]->interpolate(*this,static_cast<ModelParam>(index),interpolatedIt[0],interpolatedIt[1],interpolatedIt[2]);
|
||||
interpolatedIt += 3;
|
||||
}
|
||||
}
|
||||
|
||||
bool Particle::update(float deltaTime)
|
||||
{
|
||||
const Model* model = group->getModel();
|
||||
data->age += deltaTime;
|
||||
|
||||
if (!model->immortal)
|
||||
{
|
||||
// computes the ratio between the life of the particle and its lifetime
|
||||
float ratio = std::min(1.0f,deltaTime / data->life);
|
||||
data->life -= deltaTime;
|
||||
|
||||
// updates mutable parameters
|
||||
for (size_t i = 0; i < model->nbMutableParams; ++i)
|
||||
{
|
||||
size_t index = model->mutableParams[i];
|
||||
size_t enableIndex = model->particleEnableIndices[index];
|
||||
currentParams[enableIndex] += (extendedParams[i] - currentParams[enableIndex]) * ratio;
|
||||
}
|
||||
}
|
||||
|
||||
// updates interpolated parameters
|
||||
interpolateParameters();
|
||||
|
||||
// updates position
|
||||
oldPosition() = position();
|
||||
position() += velocity() * deltaTime;
|
||||
|
||||
// updates velocity
|
||||
velocity() += group->getGravity() * deltaTime;
|
||||
|
||||
std::vector<Modifier*>::const_iterator end = group->activeModifiers.end();
|
||||
for (std::vector<Modifier*>::const_iterator it = group->activeModifiers.begin(); it != end; ++it)
|
||||
(*it)->process(*this,deltaTime);
|
||||
|
||||
if (group->getFriction() != 0.0f)
|
||||
velocity() *= 1.0f - std::min(1.0f,group->getFriction() * deltaTime / getParamCurrentValue(PARAM_MASS));
|
||||
|
||||
return data->life <= 0.0f;
|
||||
}
|
||||
|
||||
bool Particle::setParamCurrentValue(ModelParam type,float value)
|
||||
{
|
||||
const Model* const model = group->getModel();
|
||||
if (model->isEnabled(type))
|
||||
{
|
||||
currentParams[model->particleEnableIndices[type]] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Particle::setParamFinalValue(ModelParam type,float value)
|
||||
{
|
||||
const Model* const model = group->getModel();
|
||||
if (model->isMutable(type))
|
||||
{
|
||||
extendedParams[model->particleMutableIndices[type]] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Particle::changeParamCurrentValue(ModelParam type,float delta)
|
||||
{
|
||||
const Model* const model = group->getModel();
|
||||
if (model->isEnabled(type))
|
||||
{
|
||||
currentParams[model->particleEnableIndices[type]] += delta;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Particle::changeParamFinalValue(ModelParam type,float delta)
|
||||
{
|
||||
const Model* const model = group->getModel();
|
||||
if (model->isMutable(type))
|
||||
{
|
||||
extendedParams[model->particleMutableIndices[type]] += delta;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float Particle::getParamCurrentValue(ModelParam type) const
|
||||
{
|
||||
const Model* const model = group->getModel();
|
||||
if (model->isEnabled(type))
|
||||
return currentParams[model->particleEnableIndices[type]];
|
||||
|
||||
return Model::DEFAULT_VALUES[type];
|
||||
}
|
||||
|
||||
float Particle::getParamFinalValue(ModelParam type) const
|
||||
{
|
||||
const Model* const model = group->getModel();
|
||||
if (model->isEnabled(type))
|
||||
{
|
||||
if (model->isMutable(type))
|
||||
return extendedParams[model->particleMutableIndices[type] + 1];
|
||||
return currentParams[model->particleEnableIndices[type]];
|
||||
}
|
||||
|
||||
return Model::DEFAULT_VALUES[type];
|
||||
}
|
||||
|
||||
Model* Particle::getModel() const
|
||||
{
|
||||
return group->getModel();
|
||||
}
|
||||
|
||||
void Particle::computeSqrDist()
|
||||
{
|
||||
data->sqrDist = getSqrDist(position(),System::getCameraPosition());
|
||||
}
|
||||
|
||||
extern void swapParticles(Particle& a,Particle& b)
|
||||
{
|
||||
//std::swap(a.index,b.index);
|
||||
std::swap(*a.data,*b.data);
|
||||
for (size_t i = 0; i < a.getModel()->getSizeOfParticleCurrentArray(); ++i)
|
||||
std::swap(a.currentParams[i],b.currentParams[i]);
|
||||
for (size_t i = 0; i < a.getModel()->getSizeOfParticleExtendedArray(); ++i)
|
||||
std::swap(a.extendedParams[i],b.extendedParams[i]);
|
||||
|
||||
// swap additional data (groups are assumed to be the same)
|
||||
for (std::set<Buffer*>::iterator it = a.group->swappableBuffers.begin(); it != a.group->swappableBuffers.end(); ++it)
|
||||
(*it)->swap(a.index,b.index);
|
||||
}
|
||||
}
|
118
libs/spark/src/Core/SPK_Registerable.cpp
Normal file
118
libs/spark/src/Core/SPK_Registerable.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Registerable.h"
|
||||
#include "Core/SPK_Factory.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
const SPK_ID NO_ID(0);
|
||||
const std::string NO_NAME;
|
||||
|
||||
Registerable::Registerable() :
|
||||
ID(NO_ID),
|
||||
nbReferences(0),
|
||||
shared(false),
|
||||
destroyable(true),
|
||||
name(NO_NAME)
|
||||
{}
|
||||
|
||||
Registerable::Registerable(const Registerable& registerable) :
|
||||
ID(NO_ID),
|
||||
nbReferences(0),
|
||||
shared(registerable.shared),
|
||||
destroyable(registerable.destroyable),
|
||||
name(registerable.name)
|
||||
{}
|
||||
|
||||
Registerable::~Registerable(){}
|
||||
|
||||
Registerable* Registerable::copyChild(Registerable* child,bool createBase)
|
||||
{
|
||||
if (child == NULL)
|
||||
return NULL;
|
||||
|
||||
if (((child->isRegistered())&&(!child->isShared()))||(createBase))
|
||||
{
|
||||
if (SPKFactory::getInstance().isAlreadyProcessed(child))
|
||||
{
|
||||
Registerable* processedClone = SPKFactory::getInstance().getProcessedObject(child);
|
||||
processedClone->incrementReference();
|
||||
return processedClone;
|
||||
}
|
||||
|
||||
Registerable* cloneChild = child->clone(createBase);
|
||||
SPKFactory::getInstance().registerObject(cloneChild);
|
||||
cloneChild->incrementReference();
|
||||
SPKFactory::getInstance().markAsProcessed(child,cloneChild);
|
||||
return cloneChild;
|
||||
}
|
||||
|
||||
child->incrementReference();
|
||||
return child;
|
||||
}
|
||||
|
||||
bool Registerable::destroyChild(Registerable* child,bool keepChildren)
|
||||
{
|
||||
if ((child == NULL)||(keepChildren))
|
||||
return false;
|
||||
|
||||
child->decrementReference();
|
||||
|
||||
if ((child->isRegistered())&&
|
||||
(child->isDestroyable())&&
|
||||
(child->getNbReferences() == 0))
|
||||
{
|
||||
SPKFactory::getInstance().unregisterObject(child->getSPKID());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Registerable::registerChild(Registerable* child,bool registerAll)
|
||||
{
|
||||
if (child == NULL)
|
||||
return;
|
||||
|
||||
if (child->isRegistered())
|
||||
{
|
||||
child->incrementReference();
|
||||
child->registerChildren(registerAll);
|
||||
}
|
||||
else if (registerAll)
|
||||
{
|
||||
SPKFactory::getInstance().registerObject(child);
|
||||
child->incrementReference();
|
||||
child->registerChildren(registerAll);
|
||||
}
|
||||
}
|
||||
|
||||
void Registerable::registerObject(Registerable* obj,bool registerAll)
|
||||
{
|
||||
if ((obj != NULL)&&(!obj->isRegistered()))
|
||||
{
|
||||
SPKFactory::getInstance().registerObject(obj);
|
||||
obj->registerChildren(registerAll);
|
||||
}
|
||||
}
|
||||
}
|
37
libs/spark/src/Core/SPK_Renderer.cpp
Normal file
37
libs/spark/src/Core/SPK_Renderer.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Renderer.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Renderer::Renderer() :
|
||||
Registerable(),
|
||||
BufferHandler(),
|
||||
active(true),
|
||||
renderingHintsMask(DEPTH_TEST | DEPTH_WRITE),
|
||||
alphaThreshold(1.0f)
|
||||
{}
|
||||
|
||||
Renderer::~Renderer(){}
|
||||
}
|
330
libs/spark/src/Core/SPK_System.cpp
Normal file
330
libs/spark/src/Core/SPK_System.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_System.h"
|
||||
#include "Core/SPK_Group.h"
|
||||
#include "Core/SPK_Vector3D.h"
|
||||
#include "Core/SPK_Emitter.h"
|
||||
#include "Core/SPK_Modifier.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Vector3D System::cameraPosition;
|
||||
|
||||
StepMode System::stepMode(STEP_REAL);
|
||||
float System::constantStep(0.0f);
|
||||
float System::minStep(0.0f);
|
||||
float System::maxStep(0.0f);
|
||||
|
||||
bool System::clampStepEnabled(false);
|
||||
float System::clampStep(1.0f);
|
||||
|
||||
System::System() :
|
||||
Registerable(),
|
||||
Transformable(),
|
||||
groups(),
|
||||
nbParticles(0),
|
||||
boundingBoxEnabled(false),
|
||||
AABBMin(),
|
||||
AABBMax(),
|
||||
deltaStep(0.0f)
|
||||
{}
|
||||
|
||||
void System::registerChildren(bool registerAll)
|
||||
{
|
||||
Registerable::registerChildren(registerAll);
|
||||
|
||||
for (std::vector<Group*>::const_iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
registerChild(*it,registerAll);
|
||||
}
|
||||
|
||||
void System::copyChildren(const System& system,bool createBase)
|
||||
{
|
||||
Registerable::copyChildren(system,createBase);
|
||||
|
||||
// we clear the copies of pointers pushed in the vectors by the copy constructor
|
||||
groups.clear();
|
||||
|
||||
for (std::vector<Group*>::const_iterator it = system.groups.begin(); it != system.groups.end(); ++it)
|
||||
groups.push_back(dynamic_cast<Group*>(copyChild(*it,createBase)));
|
||||
}
|
||||
|
||||
void System::destroyChildren(bool keepChildren)
|
||||
{
|
||||
for (std::vector<Group*>::const_iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
destroyChild(*it,keepChildren);
|
||||
|
||||
Registerable::destroyChildren(keepChildren);
|
||||
}
|
||||
|
||||
void System::addGroup(Group* group)
|
||||
{
|
||||
incrementChildReference(group);
|
||||
groups.push_back(group);
|
||||
nbParticles += group->getNbParticles();
|
||||
}
|
||||
|
||||
void System::removeGroup(Group* group)
|
||||
{
|
||||
std::vector<Group*>::iterator it = std::find(groups.begin(),groups.end(),group);
|
||||
if (it != groups.end())
|
||||
{
|
||||
decrementChildReference(group);
|
||||
groups.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
size_t System::computeNbParticles()
|
||||
{
|
||||
nbParticles = 0;
|
||||
for (std::vector<Group*>::const_iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
nbParticles += (*it)->getNbParticles();
|
||||
return nbParticles;
|
||||
}
|
||||
|
||||
bool System::innerUpdate(float deltaTime)
|
||||
{
|
||||
nbParticles = 0;
|
||||
bool isAlive = false;
|
||||
|
||||
bool hasGroupsWithAABB = false;
|
||||
if (boundingBoxEnabled)
|
||||
{
|
||||
const float maxFloat = std::numeric_limits<float>::max();
|
||||
AABBMin.set(maxFloat,maxFloat,maxFloat);
|
||||
AABBMax.set(-maxFloat,-maxFloat,-maxFloat);
|
||||
}
|
||||
|
||||
for (std::vector<Group*>::iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
{
|
||||
isAlive |= (*it)->update(deltaTime);
|
||||
nbParticles += (*it)->getNbParticles();
|
||||
|
||||
if ((boundingBoxEnabled)&&((*it)->isAABBComputingEnabled()))
|
||||
{
|
||||
Vector3D groupMin = (*it)->getAABBMin();
|
||||
Vector3D groupMax = (*it)->getAABBMax();
|
||||
if (AABBMin.x > groupMin.x)
|
||||
AABBMin.x = groupMin.x;
|
||||
if (AABBMin.y > groupMin.y)
|
||||
AABBMin.y = groupMin.y;
|
||||
if (AABBMin.z > groupMin.z)
|
||||
AABBMin.z = groupMin.z;
|
||||
if (AABBMax.x < groupMax.x)
|
||||
AABBMax.x = groupMax.x;
|
||||
if (AABBMax.y < groupMax.y)
|
||||
AABBMax.y = groupMax.y;
|
||||
if (AABBMax.z < groupMax.z)
|
||||
AABBMax.z = groupMax.z;
|
||||
hasGroupsWithAABB = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!boundingBoxEnabled)||(!hasGroupsWithAABB))
|
||||
{
|
||||
AABBMin.set(0.0f,0.0f,0.0f);
|
||||
AABBMax.set(0.0f,0.0f,0.0f);
|
||||
}
|
||||
|
||||
return isAlive;
|
||||
}
|
||||
|
||||
bool System::update(float deltaTime)
|
||||
{
|
||||
if ((clampStepEnabled)&&(deltaTime > clampStep))
|
||||
deltaTime = clampStep;
|
||||
|
||||
if (stepMode != STEP_REAL)
|
||||
{
|
||||
deltaTime += deltaStep;
|
||||
|
||||
float updateStep;
|
||||
if (stepMode == STEP_ADAPTIVE)
|
||||
{
|
||||
if (deltaTime > maxStep)
|
||||
updateStep = maxStep;
|
||||
else if (deltaTime < minStep)
|
||||
updateStep = minStep;
|
||||
else
|
||||
{
|
||||
deltaStep = 0.0f;
|
||||
return innerUpdate(deltaTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
updateStep = constantStep;
|
||||
|
||||
bool isAlive = true;
|
||||
while(deltaTime >= updateStep)
|
||||
{
|
||||
if ((isAlive)&&(!innerUpdate(updateStep)))
|
||||
isAlive = false;
|
||||
deltaTime -= updateStep;
|
||||
}
|
||||
deltaStep = deltaTime;
|
||||
return isAlive;
|
||||
|
||||
}
|
||||
else
|
||||
return innerUpdate(deltaTime);
|
||||
}
|
||||
|
||||
void System::render() const
|
||||
{
|
||||
for (std::vector<Group*>::const_iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
(*it)->render();
|
||||
}
|
||||
|
||||
void System::grow(float time,float step)
|
||||
{
|
||||
if (step <= 0.0f)
|
||||
step = time;
|
||||
|
||||
while (time > 0.0f)
|
||||
{
|
||||
float currentStep = time > step ? step : time;
|
||||
update(currentStep);
|
||||
time -= currentStep;
|
||||
}
|
||||
}
|
||||
|
||||
void System::empty()
|
||||
{
|
||||
for (std::vector<Group*>::iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
(*it)->empty();
|
||||
nbParticles = 0;
|
||||
}
|
||||
|
||||
void System::setCameraPosition(const Vector3D& cameraPosition)
|
||||
{
|
||||
System::cameraPosition = cameraPosition;
|
||||
}
|
||||
|
||||
void System::setClampStep(bool enableClampStep,float clamp)
|
||||
{
|
||||
clampStepEnabled = enableClampStep;
|
||||
clampStep = clamp;
|
||||
}
|
||||
|
||||
void System::useConstantStep(float constantStep)
|
||||
{
|
||||
stepMode = STEP_CONSTANT;
|
||||
System::constantStep = constantStep;
|
||||
}
|
||||
|
||||
void System::useAdaptiveStep(float minStep,float maxStep)
|
||||
{
|
||||
stepMode = STEP_ADAPTIVE;
|
||||
System::minStep = minStep;
|
||||
System::maxStep = maxStep;
|
||||
}
|
||||
|
||||
void System::useRealStep()
|
||||
{
|
||||
stepMode = STEP_REAL;
|
||||
}
|
||||
|
||||
const Vector3D& System::getCameraPosition()
|
||||
{
|
||||
return cameraPosition;
|
||||
}
|
||||
|
||||
StepMode System::getStepMode()
|
||||
{
|
||||
return stepMode;
|
||||
}
|
||||
|
||||
void System::sortParticles()
|
||||
{
|
||||
for (std::vector<Group*>::iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
(*it)->sortParticles();
|
||||
}
|
||||
|
||||
void System::computeDistances()
|
||||
{
|
||||
for (std::vector<Group*>::iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
(*it)->computeDistances();
|
||||
}
|
||||
|
||||
void System::computeAABB()
|
||||
{
|
||||
if (boundingBoxEnabled)
|
||||
{
|
||||
const float maxFloat = std::numeric_limits<float>::max();
|
||||
AABBMin.set(maxFloat,maxFloat,maxFloat);
|
||||
AABBMax.set(-maxFloat,-maxFloat,-maxFloat);
|
||||
}
|
||||
|
||||
bool hasGroupsWithAABB = false;
|
||||
for (std::vector<Group*>::iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
{
|
||||
(*it)->computeAABB();
|
||||
|
||||
if ((boundingBoxEnabled)&&((*it)->isAABBComputingEnabled()))
|
||||
{
|
||||
Vector3D groupMin = (*it)->getAABBMin();
|
||||
Vector3D groupMax = (*it)->getAABBMax();
|
||||
if (AABBMin.x > groupMin.x)
|
||||
AABBMin.x = groupMin.x;
|
||||
if (AABBMin.y > groupMin.y)
|
||||
AABBMin.y = groupMin.y;
|
||||
if (AABBMin.z > groupMin.z)
|
||||
AABBMin.z = groupMin.z;
|
||||
if (AABBMax.x < groupMax.x)
|
||||
AABBMax.x = groupMax.x;
|
||||
if (AABBMax.y < groupMax.y)
|
||||
AABBMax.y = groupMax.y;
|
||||
if (AABBMax.z < groupMax.z)
|
||||
AABBMax.z = groupMax.z;
|
||||
hasGroupsWithAABB = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!boundingBoxEnabled)||(!hasGroupsWithAABB))
|
||||
{
|
||||
const Vector3D pos = getWorldTransformPos();
|
||||
AABBMin = AABBMax = pos;
|
||||
}
|
||||
}
|
||||
|
||||
Registerable* System::findByName(const std::string& name)
|
||||
{
|
||||
Registerable* object = Registerable::findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
|
||||
for (std::vector<Group*>::const_iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
{
|
||||
object = (*it)->findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void System::propagateUpdateTransform()
|
||||
{
|
||||
for (std::vector<Group*>::const_iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
(*it)->updateTransform(this);
|
||||
}
|
||||
}
|
239
libs/spark/src/Core/SPK_Transformable.cpp
Normal file
239
libs/spark/src/Core/SPK_Transformable.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Transformable.h"
|
||||
#include "Core/SPK_Zone.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
const float Transformable::IDENTITY[] =
|
||||
{
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
|
||||
Transformable::Transformable() :
|
||||
currentUpdate(0),
|
||||
lastUpdate(0),
|
||||
lastParentUpdate(0),
|
||||
parent(NULL),
|
||||
localIdentity(true)
|
||||
{
|
||||
memcpy(local,IDENTITY,sizeof(float) * TRANSFORM_LENGTH);
|
||||
memcpy(world,IDENTITY,sizeof(float) * TRANSFORM_LENGTH);
|
||||
}
|
||||
|
||||
Transformable::Transformable(const Transformable& transformable) :
|
||||
currentUpdate(0),
|
||||
lastUpdate(0),
|
||||
lastParentUpdate(0),
|
||||
parent(NULL),
|
||||
localIdentity(transformable.localIdentity)
|
||||
{
|
||||
memcpy(local,transformable.local,sizeof(float) * TRANSFORM_LENGTH);
|
||||
memcpy(world,transformable.world,sizeof(float) * TRANSFORM_LENGTH);
|
||||
}
|
||||
|
||||
void Transformable::setTransformNC(const float* transform)
|
||||
{
|
||||
for (size_t i = 0; i < TRANSFORM_LENGTH; ++i)
|
||||
local[i] = transform[(i >> 2) + ((i & 3) << 2)]; // conversion
|
||||
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void Transformable::setTransformPosition(const Vector3D& pos)
|
||||
{
|
||||
local[12] = pos.x;
|
||||
local[13] = pos.y;
|
||||
local[14] = pos.z;
|
||||
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void Transformable::setTransformOrientationRH(Vector3D look,Vector3D up)
|
||||
{
|
||||
look.normalize();
|
||||
up.normalize();
|
||||
|
||||
Vector3D side = crossProduct(look,up);
|
||||
side.normalize();
|
||||
|
||||
up = crossProduct(side,look);
|
||||
|
||||
local[0] = side.x;
|
||||
local[1] = side.y;
|
||||
local[2] = side.z;
|
||||
local[4] = up.x;
|
||||
local[5] = up.y;
|
||||
local[6] = up.z;
|
||||
local[8] = -look.x;
|
||||
local[9] = -look.y;
|
||||
local[10] = -look.z;
|
||||
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void Transformable::setTransformOrientationLH(Vector3D look,Vector3D up)
|
||||
{
|
||||
look.normalize();
|
||||
|
||||
Vector3D side = crossProduct(look,up);
|
||||
side.normalize();
|
||||
|
||||
up = crossProduct(side,look);
|
||||
|
||||
local[0] = side.x;
|
||||
local[1] = side.y;
|
||||
local[2] = side.z;
|
||||
local[4] = up.x;
|
||||
local[5] = up.y;
|
||||
local[6] = up.z;
|
||||
local[8] = look.x;
|
||||
local[9] = look.y;
|
||||
local[10] = look.z;
|
||||
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void Transformable::setTransformOrientation(Vector3D axis,float angle)
|
||||
{
|
||||
axis.normalize();
|
||||
float c = std::cos(angle);
|
||||
float s = std::sin(angle);
|
||||
float a = 1 - c;
|
||||
Vector3D axis2(axis.x * axis.x,axis.y * axis.y,axis.z * axis.z);
|
||||
|
||||
local[0] = axis2.x + (1 - axis2.x) * c;
|
||||
local[1] = axis.x * axis.y * a + axis.z * s;
|
||||
local[2] = axis.x * axis.z * a - axis.y * s;
|
||||
local[4] = axis.x * axis.y * a - axis.z * s;
|
||||
local[5] = axis2.y + (1 - axis2.y) * c;
|
||||
local[6] = axis.y * axis.z * a + axis.x * s;
|
||||
local[8] = axis.x * axis.z * a + axis.y * s;
|
||||
local[9] = axis.y * axis.z * a - axis.x * s;
|
||||
local[10] = axis2.z + (1 - axis2.z) * c;
|
||||
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void Transformable::setTransformOrientationX(float angle)
|
||||
{
|
||||
float cosA = std::cos(angle);
|
||||
float sinA = std::sin(angle);
|
||||
|
||||
local[0] = 1.0f;
|
||||
local[1] = 0.0f;
|
||||
local[2] = 0.0f;
|
||||
local[4] = 0.0f;
|
||||
local[5] = cosA;
|
||||
local[6] = sinA;
|
||||
local[8] = 0.0f;
|
||||
local[9] = -sinA;
|
||||
local[10] = cosA;
|
||||
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void Transformable::setTransformOrientationY(float angle)
|
||||
{
|
||||
float cosA = std::cos(angle);
|
||||
float sinA = std::sin(angle);
|
||||
|
||||
local[0] = cosA;
|
||||
local[1] = 0.0f;
|
||||
local[2] = -sinA;
|
||||
local[4] = 0.0f;
|
||||
local[5] = 1.0f;
|
||||
local[6] = 0.0f;
|
||||
local[8] = sinA;
|
||||
local[9] = 0.0f;
|
||||
local[10] = cosA;
|
||||
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void Transformable::setTransformOrientationZ(float angle)
|
||||
{
|
||||
float cosA = std::cos(angle);
|
||||
float sinA = std::sin(angle);
|
||||
|
||||
local[0] = cosA;
|
||||
local[1] = sinA;
|
||||
local[2] = 0.0f;
|
||||
local[4] = -sinA;
|
||||
local[5] = cosA;
|
||||
local[6] = 0.0f;
|
||||
local[8] = 0.0f;
|
||||
local[9] = 0.0f;
|
||||
local[10] = 1.0f;
|
||||
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void Transformable::updateTransform(const Transformable* parent)
|
||||
{
|
||||
if (isUpdateNotified() || // the local transform or instance param have been updated
|
||||
parent != this->parent || // the parent has changed
|
||||
(parent != NULL && lastParentUpdate != parent->currentUpdate)) // the parent transform has been modified
|
||||
{
|
||||
if (parent == NULL)
|
||||
memcpy(world,local,sizeof(float) * TRANSFORM_LENGTH);
|
||||
else if (isLocalIdentity())
|
||||
{
|
||||
memcpy(world,parent->world,sizeof(float) * TRANSFORM_LENGTH);
|
||||
lastParentUpdate = parent->lastUpdate;
|
||||
}
|
||||
else
|
||||
{
|
||||
multiply(world,parent->world,local);
|
||||
lastParentUpdate = parent->lastUpdate;
|
||||
}
|
||||
|
||||
this->parent = parent;
|
||||
lastUpdate = ++currentUpdate;
|
||||
innerUpdateTransform();
|
||||
}
|
||||
|
||||
propagateUpdateTransform();
|
||||
}
|
||||
|
||||
void Transformable::transformPos(Vector3D& tPos,const Vector3D& pos)
|
||||
{
|
||||
multiply(tPos,pos,world);
|
||||
}
|
||||
|
||||
void Transformable::transformDir(Vector3D& tDir,const Vector3D& dir)
|
||||
{
|
||||
rotate(tDir,dir,world); // To transform a direction, the translation is ignored
|
||||
}
|
||||
}
|
177
libs/spark/src/Core/SPK_Vector3D.cpp
Normal file
177
libs/spark/src/Core/SPK_Vector3D.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Vector3D.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Vector3D::Vector3D(float x,float y,float z) :
|
||||
x(x),
|
||||
y(y),
|
||||
z(z) {}
|
||||
|
||||
Vector3D& Vector3D::operator+=(const Vector3D& v)
|
||||
{
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
z += v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3D& Vector3D::operator-=(const Vector3D& v)
|
||||
{
|
||||
x -= v.x;
|
||||
y -= v.y;
|
||||
z -= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3D& Vector3D::operator+=(float f)
|
||||
{
|
||||
x += f;
|
||||
y += f;
|
||||
z += f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3D& Vector3D::operator-=(float f)
|
||||
{
|
||||
x -= f;
|
||||
y -= f;
|
||||
z -= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3D& Vector3D::operator*=(float f)
|
||||
{
|
||||
x *= f;
|
||||
y *= f;
|
||||
z *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3D& Vector3D::operator/=(float f)
|
||||
{
|
||||
f = 1.0f / f;
|
||||
x *= f;
|
||||
y *= f;
|
||||
z *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
float& Vector3D::operator[](size_t index)
|
||||
{
|
||||
switch(index)
|
||||
{
|
||||
case 0 : return x;
|
||||
case 1 : return y;
|
||||
default : return z;
|
||||
}
|
||||
}
|
||||
|
||||
const float& Vector3D::operator[](size_t index) const
|
||||
{
|
||||
switch(index)
|
||||
{
|
||||
case 0 : return x;
|
||||
case 1 : return y;
|
||||
default : return z;
|
||||
}
|
||||
}
|
||||
|
||||
void Vector3D::set(float x,float y,float z)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
bool Vector3D::normalize()
|
||||
{
|
||||
float norm = getNorm();
|
||||
if (norm != 0.0f)
|
||||
{
|
||||
x /= norm;
|
||||
y /= norm;
|
||||
z /= norm;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Vector3D::revert()
|
||||
{
|
||||
x = -x;
|
||||
y = -y;
|
||||
z = -z;
|
||||
}
|
||||
|
||||
void Vector3D::abs()
|
||||
{
|
||||
if (x < 0.0f) x = -x;
|
||||
if (y < 0.0f) y = -y;
|
||||
if (z < 0.0f) z = -z;
|
||||
}
|
||||
|
||||
void Vector3D::crossProduct(const Vector3D& v)
|
||||
{
|
||||
Vector3D result;
|
||||
|
||||
result.x = y * v.z - z * v.y;
|
||||
result.y = z * v.x - x * v.z;
|
||||
result.z = x * v.y - y * v.x;
|
||||
|
||||
*this = result;
|
||||
}
|
||||
|
||||
float getSqrDist(const Vector3D& v0,const Vector3D& v1)
|
||||
{
|
||||
float dx = v0.x - v1.x;
|
||||
float dy = v0.y - v1.y;
|
||||
float dz = v0.z - v1.z;
|
||||
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
float getDist(const Vector3D& v0,const Vector3D& v1)
|
||||
{
|
||||
return std::sqrt(getSqrDist(v0,v1));
|
||||
}
|
||||
|
||||
Vector3D crossProduct(const Vector3D& v0,const Vector3D& v1)
|
||||
{
|
||||
Vector3D result;
|
||||
|
||||
result.x = v0.y * v1.z - v0.z * v1.y;
|
||||
result.y = v0.z * v1.x - v0.x * v1.z;
|
||||
result.z = v0.x * v1.y - v0.y * v1.x;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void crossProduct(const Vector3D& v0,const Vector3D& v1,Vector3D& result)
|
||||
{
|
||||
result.x = v0.y * v1.z - v0.z * v1.y;
|
||||
result.y = v0.z * v1.x - v0.x * v1.z;
|
||||
result.z = v0.x * v1.y - v0.y * v1.x;
|
||||
}
|
||||
}
|
35
libs/spark/src/Core/SPK_Zone.cpp
Normal file
35
libs/spark/src/Core/SPK_Zone.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Core/SPK_Zone.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
const float Zone::APPROXIMATION_VALUE = 0.01f;
|
||||
|
||||
Zone::Zone(const Vector3D& position) :
|
||||
Registerable(),
|
||||
Transformable()
|
||||
{
|
||||
setPosition(position);
|
||||
}
|
||||
}
|
75
libs/spark/src/Extensions/Emitters/SPK_NormalEmitter.cpp
Normal file
75
libs/spark/src/Extensions/Emitters/SPK_NormalEmitter.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Emitters/SPK_NormalEmitter.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
NormalEmitter::NormalEmitter(Zone* normalZone,bool inverted) :
|
||||
Emitter(),
|
||||
normalZone(normalZone),
|
||||
inverted(inverted)
|
||||
{}
|
||||
|
||||
void NormalEmitter::registerChildren(bool registerAll)
|
||||
{
|
||||
Emitter::registerChildren(registerAll);
|
||||
registerChild(normalZone,registerAll);
|
||||
}
|
||||
|
||||
void NormalEmitter::copyChildren(const NormalEmitter& emitter,bool createBase)
|
||||
{
|
||||
Emitter::copyChildren(emitter,createBase);
|
||||
normalZone = dynamic_cast<Zone*>(copyChild(emitter.normalZone,createBase));
|
||||
}
|
||||
|
||||
void NormalEmitter::destroyChildren(bool keepChildren)
|
||||
{
|
||||
destroyChild(normalZone,keepChildren);
|
||||
Emitter::destroyChildren(keepChildren);
|
||||
}
|
||||
|
||||
Registerable* NormalEmitter::findByName(const std::string& name)
|
||||
{
|
||||
Registerable* object = Emitter::findByName(name);
|
||||
if ((object != NULL)||(normalZone == NULL))
|
||||
return object;
|
||||
|
||||
return normalZone->findByName(name);
|
||||
}
|
||||
|
||||
void NormalEmitter::setNormalZone(Zone* zone)
|
||||
{
|
||||
decrementChildReference(normalZone);
|
||||
incrementChildReference(zone);
|
||||
|
||||
normalZone = zone;
|
||||
}
|
||||
|
||||
void NormalEmitter::generateVelocity(Particle& particle,float speed) const
|
||||
{
|
||||
if (inverted) speed = -speed;
|
||||
const Zone* zone = (normalZone == NULL ? getZone() : normalZone);
|
||||
particle.velocity() = zone->computeNormal(particle.position()) * speed;
|
||||
}
|
||||
}
|
39
libs/spark/src/Extensions/Emitters/SPK_RandomEmitter.cpp
Normal file
39
libs/spark/src/Extensions/Emitters/SPK_RandomEmitter.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Emitters/SPK_RandomEmitter.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
void RandomEmitter::generateVelocity(Particle& particle,float speed) const
|
||||
{
|
||||
float norm;
|
||||
do
|
||||
{
|
||||
particle.velocity().set(random(-1.0f,1.0f),random(-1.0f,1.0f),random(-1.0f,1.0f));
|
||||
norm = particle.velocity().getNorm();
|
||||
}
|
||||
while((norm > 1.0f) || (norm == 0.0f));
|
||||
particle.velocity() *= speed / norm;
|
||||
}
|
||||
}
|
123
libs/spark/src/Extensions/Emitters/SPK_SphericEmitter.cpp
Normal file
123
libs/spark/src/Extensions/Emitters/SPK_SphericEmitter.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Emitters/SPK_SphericEmitter.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
const float SphericEmitter::PI = 3.1415926535897932384626433832795f;
|
||||
|
||||
SphericEmitter::SphericEmitter(const Vector3D& direction,float angleA,float angleB) :
|
||||
Emitter()
|
||||
{
|
||||
setDirection(direction);
|
||||
setAngles(angleA,angleB);
|
||||
}
|
||||
|
||||
void SphericEmitter::setDirection(const Vector3D& direction)
|
||||
{
|
||||
tDirection = direction;
|
||||
computeMatrix();
|
||||
this->direction = tDirection; // as tDirection was normalized in computeMatrix()
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void SphericEmitter::setAngles(float angleA,float angleB)
|
||||
{
|
||||
if (angleB < angleA)
|
||||
std::swap(angleA,angleB);
|
||||
|
||||
angleA = std::min(2.0f * PI,std::max(0.0f,angleA));
|
||||
angleB = std::min(2.0f * PI,std::max(0.0f,angleB));
|
||||
|
||||
angleMin = angleA;
|
||||
angleMax = angleB;
|
||||
|
||||
cosAngleMin = cos(angleMin * 0.5f);
|
||||
cosAngleMax = cos(angleMax * 0.5f);
|
||||
}
|
||||
|
||||
void SphericEmitter::computeMatrix()
|
||||
{
|
||||
tDirection.normalize();
|
||||
if ((tDirection.x == 0.0f)&&(tDirection.y == 0.0f))
|
||||
{
|
||||
|
||||
matrix[0] = tDirection.z;
|
||||
matrix[1] = 0.0f;
|
||||
matrix[2] = 0.0f;
|
||||
matrix[3] = 0.0f;
|
||||
matrix[4] = tDirection.z;
|
||||
matrix[5] = 0.0f;
|
||||
matrix[6] = 0.0f;
|
||||
matrix[7] = 0.0f;
|
||||
matrix[8] = tDirection.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3D axis;
|
||||
crossProduct(tDirection,Vector3D(0.0f,0.0f,1.0f),axis);
|
||||
|
||||
float cosA = tDirection.z;
|
||||
float sinA = -axis.getNorm();
|
||||
axis /= -sinA;
|
||||
|
||||
float x = axis.x;
|
||||
float y = axis.y;
|
||||
float z = axis.z;
|
||||
|
||||
matrix[0] = x * x + cosA * (1.0f - x * x);
|
||||
matrix[1] = x * y * (1.0f - cosA) - z * sinA;
|
||||
matrix[2] = tDirection.x;
|
||||
matrix[3] = x * y * (1.0f - cosA) + z * sinA;
|
||||
matrix[4] = y * y + cosA * (1.0f - y * y);
|
||||
matrix[5] = tDirection.y;
|
||||
matrix[6] = x * z * (1.0f - cosA) - y * sinA;
|
||||
matrix[7] = y * z * (1.0f - cosA) + x * sinA;
|
||||
matrix[8] = tDirection.z;
|
||||
}
|
||||
}
|
||||
|
||||
void SphericEmitter::generateVelocity(Particle& particle,float speed) const
|
||||
{
|
||||
float a = random(cosAngleMax,cosAngleMin);
|
||||
float theta = acos(a);
|
||||
float phi = random(0.0f,2.0f * PI);
|
||||
|
||||
float sinTheta = sin(theta);
|
||||
float x = sinTheta * cos(phi);
|
||||
float y = sinTheta * sin(phi);
|
||||
float z = cos(theta);
|
||||
|
||||
particle.velocity().x = speed * (matrix[0] * x + matrix[1] * y + matrix[2] * z);
|
||||
particle.velocity().y = speed * (matrix[3] * x + matrix[4] * y + matrix[5] * z);
|
||||
particle.velocity().z = speed * (matrix[6] * x + matrix[7] * y + matrix[8] * z);
|
||||
}
|
||||
|
||||
void SphericEmitter::innerUpdateTransform()
|
||||
{
|
||||
Emitter::innerUpdateTransform();
|
||||
transformDir(tDirection,direction);
|
||||
computeMatrix();
|
||||
}
|
||||
}
|
48
libs/spark/src/Extensions/Emitters/SPK_StraightEmitter.cpp
Normal file
48
libs/spark/src/Extensions/Emitters/SPK_StraightEmitter.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Emitters/SPK_StraightEmitter.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
StraightEmitter::StraightEmitter(const Vector3D& direction) :
|
||||
Emitter()
|
||||
{
|
||||
setDirection(direction);
|
||||
}
|
||||
|
||||
void StraightEmitter::setDirection(const Vector3D& direction)
|
||||
{
|
||||
this->direction = direction;
|
||||
this->direction.normalize();
|
||||
tDirection = this->direction;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
void StraightEmitter::innerUpdateTransform()
|
||||
{
|
||||
Emitter::innerUpdateTransform();
|
||||
transformDir(tDirection,direction);
|
||||
tDirection.normalize();
|
||||
}
|
||||
}
|
122
libs/spark/src/Extensions/Modifiers/SPK_Collision.cpp
Normal file
122
libs/spark/src/Extensions/Modifiers/SPK_Collision.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Modifiers/SPK_Collision.h"
|
||||
#include "Core/SPK_Group.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Collision::Collision(float scale,float elasticity) :
|
||||
Modifier(),
|
||||
scale(scale)
|
||||
{
|
||||
setElasticity(elasticity);
|
||||
}
|
||||
|
||||
void Collision::modify(Particle& particle,float deltaTime) const
|
||||
{
|
||||
size_t index = particle.getIndex();
|
||||
float radius1 = particle.getParamCurrentValue(PARAM_SIZE) * scale * 0.5f;
|
||||
float m1 = particle.getParamCurrentValue(PARAM_MASS);
|
||||
Group& group = *particle.getGroup();
|
||||
|
||||
// Tests collisions with all the particles that are stored before in the pool
|
||||
for (size_t i = 0; i < index; ++i)
|
||||
{
|
||||
Particle& particle2 = group.getParticle(i);
|
||||
float radius2 = particle2.getParamCurrentValue(PARAM_SIZE) * scale * 0.5f;
|
||||
|
||||
float sqrRadius = radius1 + radius2;
|
||||
sqrRadius *= sqrRadius;
|
||||
|
||||
// Gets the normal of the collision plane
|
||||
Vector3D normal = particle.position();
|
||||
normal -= particle2.position();
|
||||
float sqrDist = normal.getSqrNorm();
|
||||
|
||||
if (sqrDist < sqrRadius) // particles are intersecting each other
|
||||
{
|
||||
Vector3D delta = particle.velocity();
|
||||
delta -= particle2.velocity();
|
||||
|
||||
if (dotProduct(normal,delta) < 0.0f) // particles are moving towards each other
|
||||
{
|
||||
float oldSqrDist = getSqrDist(particle.oldPosition(),particle2.oldPosition());
|
||||
if (oldSqrDist > sqrDist)
|
||||
{
|
||||
// Disables the move from this frame
|
||||
particle.position() = particle.oldPosition();
|
||||
particle2.position() = particle2.oldPosition();
|
||||
|
||||
normal = particle.position();
|
||||
normal -= particle2.position();
|
||||
|
||||
if (dotProduct(normal,delta) >= 0.0f)
|
||||
continue;
|
||||
}
|
||||
|
||||
normal.normalize();
|
||||
|
||||
// Gets the normal components of the velocities
|
||||
Vector3D normal1(normal);
|
||||
Vector3D normal2(normal);
|
||||
normal1 *= dotProduct(normal,particle.velocity());
|
||||
normal2 *= dotProduct(normal,particle2.velocity());
|
||||
|
||||
// Resolves collision
|
||||
float m2 = particle2.getParamCurrentValue(PARAM_MASS);
|
||||
|
||||
if (oldSqrDist < sqrRadius && sqrDist < sqrRadius)
|
||||
{
|
||||
// Tweak to separate particles that intersects at both t - deltaTime and t
|
||||
// In that case the collision is no more considered as punctual
|
||||
if (dotProduct(normal,normal1) < 0.0f)
|
||||
{
|
||||
particle.velocity() -= normal1;
|
||||
particle2.velocity() += normal1;
|
||||
}
|
||||
|
||||
if (dotProduct(normal,normal2) > 0.0f)
|
||||
{
|
||||
particle2.velocity() -= normal2;
|
||||
particle.velocity() += normal2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else classic collision equations are applied
|
||||
// Tangent components of the velocities are left untouched
|
||||
particle.velocity() -= (1.0f + (elasticity * m2 - m1) / (m1 + m2)) * normal1;
|
||||
particle2.velocity() -= (1.0f + (elasticity * m1 - m2) / (m1 + m2)) * normal2;
|
||||
|
||||
normal1 *= ((1.0f + elasticity) * m1) / (m1 + m2);
|
||||
normal2 *= ((1.0f + elasticity) * m2) / (m1 + m2);
|
||||
|
||||
particle.velocity() += normal2;
|
||||
particle2.velocity() += normal1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
51
libs/spark/src/Extensions/Modifiers/SPK_Destroyer.cpp
Normal file
51
libs/spark/src/Extensions/Modifiers/SPK_Destroyer.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Modifiers/SPK_Destroyer.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
#include "Core/SPK_Zone.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Destroyer::Destroyer(Zone* zone,ModifierTrigger) :
|
||||
Modifier(INSIDE_ZONE | OUTSIDE_ZONE | INTERSECT_ZONE | ENTER_ZONE | EXIT_ZONE,INSIDE_ZONE,true,false,zone)
|
||||
{
|
||||
setTrigger(trigger);
|
||||
}
|
||||
|
||||
void Destroyer::modify(Particle& particle,float deltaTime) const
|
||||
{
|
||||
particle.kill();
|
||||
if ((trigger != INSIDE_ZONE)||(trigger != OUTSIDE_ZONE))
|
||||
particle.position() = intersection;
|
||||
}
|
||||
|
||||
void Destroyer::modifyWrongSide(Particle& particle,bool inside) const
|
||||
{
|
||||
if (isFullZone())
|
||||
{
|
||||
getZone()->moveAtBorder(particle.position(),inside);
|
||||
particle.kill();
|
||||
}
|
||||
}
|
||||
}
|
50
libs/spark/src/Extensions/Modifiers/SPK_LinearForce.cpp
Normal file
50
libs/spark/src/Extensions/Modifiers/SPK_LinearForce.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Modifiers/SPK_LinearForce.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
LinearForce::LinearForce(Zone* zone,ModifierTrigger trigger,const Vector3D& force,ForceFactor type,ModelParam param) :
|
||||
Modifier(ALWAYS | INSIDE_ZONE | OUTSIDE_ZONE,ALWAYS,false,false,zone),
|
||||
force(force),
|
||||
tForce(force),
|
||||
factorType(type),
|
||||
factorParam(param)
|
||||
{}
|
||||
|
||||
void LinearForce::modify(Particle& particle,float deltaTime) const
|
||||
{
|
||||
float factor = deltaTime / particle.getParamCurrentValue(PARAM_MASS);
|
||||
|
||||
if (factorType != FACTOR_NONE)
|
||||
{
|
||||
float param = particle.getParamCurrentValue(factorParam);
|
||||
factor *= param; // linearity function of the parameter
|
||||
if (factorType == FACTOR_SQUARE)
|
||||
factor *= param; // linearity function of the square of the parameter
|
||||
}
|
||||
|
||||
particle.velocity() += tForce * factor;
|
||||
}
|
||||
}
|
169
libs/spark/src/Extensions/Modifiers/SPK_ModifierGroup.cpp
Normal file
169
libs/spark/src/Extensions/Modifiers/SPK_ModifierGroup.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Modifiers/SPK_ModifierGroup.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
ModifierGroup::ModifierGroup(Zone* zone,ModifierTrigger trigger) :
|
||||
Modifier(INSIDE_ZONE | OUTSIDE_ZONE | INTERSECT_ZONE | ENTER_ZONE | EXIT_ZONE,trigger,false,false,zone),
|
||||
modifiers(),
|
||||
globalZone(false),
|
||||
handleWrongSide(false)
|
||||
{}
|
||||
|
||||
void ModifierGroup::registerChildren(bool registerAll)
|
||||
{
|
||||
Modifier::registerChildren(registerAll);
|
||||
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
registerChild(*it,registerAll);
|
||||
}
|
||||
|
||||
void ModifierGroup::copyChildren(const ModifierGroup& modifier,bool createBase)
|
||||
{
|
||||
Modifier::copyChildren(modifier,createBase);
|
||||
|
||||
// we clear the copies of pointers pushed in the vectors by the copy constructor
|
||||
modifiers.clear();
|
||||
|
||||
for (std::vector<Modifier*>::const_iterator it = modifier.modifiers.begin(); it != modifier.modifiers.end(); ++it)
|
||||
modifiers.push_back(dynamic_cast<Modifier*>(copyChild(*it,createBase)));
|
||||
}
|
||||
|
||||
void ModifierGroup::destroyChildren(bool keepChildren)
|
||||
{
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
destroyChild(*it,keepChildren);
|
||||
|
||||
Modifier::destroyChildren(keepChildren);
|
||||
}
|
||||
|
||||
Registerable* ModifierGroup::findByName(const std::string& name)
|
||||
{
|
||||
Registerable* object = Modifier::findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
{
|
||||
object = (*it)->findByName(name);
|
||||
if (object != NULL)
|
||||
return object;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ModifierGroup::addModifier(Modifier* modifier)
|
||||
{
|
||||
if (modifier == NULL)
|
||||
return;
|
||||
|
||||
incrementChildReference(modifier);
|
||||
modifiers.push_back(modifier);
|
||||
}
|
||||
|
||||
bool ModifierGroup::removeModifier(const Modifier* modifier)
|
||||
{
|
||||
std::vector<Modifier*>::iterator it = std::find<std::vector<Modifier*>::iterator,const Modifier*>(modifiers.begin(),modifiers.end(),modifier);
|
||||
if (it != modifiers.end())
|
||||
{
|
||||
decrementChildReference(*it);
|
||||
modifiers.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModifierGroup::clear()
|
||||
{
|
||||
for (std::vector<Modifier*>::iterator it = modifiers.begin(); it != modifiers.end(); ++it)
|
||||
decrementChildReference(*it);
|
||||
|
||||
modifiers.clear();
|
||||
}
|
||||
|
||||
void ModifierGroup::modify(Particle& particle,float deltaTime) const
|
||||
{
|
||||
std::vector<Modifier*>::const_iterator end = modifiers.end();
|
||||
|
||||
if (globalZone)
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != end; ++it)
|
||||
{
|
||||
Zone* oldZone = (*it)->getZone();
|
||||
(*it)->setZone(getZone());
|
||||
(*it)->modify(particle,deltaTime);
|
||||
(*it)->setZone(oldZone);
|
||||
}
|
||||
else
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != end; ++it)
|
||||
(*it)->process(particle,deltaTime);
|
||||
}
|
||||
|
||||
void ModifierGroup::modifyWrongSide(Particle& particle,bool inside) const
|
||||
{
|
||||
if (globalZone)
|
||||
{
|
||||
std::vector<Modifier*>::const_iterator end = modifiers.end();
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != end; ++it)
|
||||
{
|
||||
Zone* oldZone = (*it)->getZone();
|
||||
(*it)->setZone(getZone());
|
||||
(*it)->modifyWrongSide(particle,inside);
|
||||
(*it)->setZone(oldZone);
|
||||
}
|
||||
}
|
||||
else if (handleWrongSide)
|
||||
{
|
||||
std::vector<Modifier*>::const_iterator end = modifiers.end();
|
||||
for (std::vector<Modifier*>::const_iterator it = modifiers.begin(); it != end; ++it)
|
||||
if (((*it)->getZone() != NULL)&&((*it)->getTrigger() != INTERSECT_ZONE))
|
||||
modifyWrongSide(particle,true);
|
||||
}
|
||||
}
|
||||
|
||||
void ModifierGroup::createBuffers(const Group& group)
|
||||
{
|
||||
std::vector<Modifier*>::iterator end = modifiers.end();
|
||||
for (std::vector<Modifier*>::iterator it = modifiers.begin(); it != end; ++it)
|
||||
(*it)->createBuffers(group);
|
||||
}
|
||||
|
||||
void ModifierGroup::destroyBuffers(const Group& group)
|
||||
{
|
||||
std::vector<Modifier*>::iterator end = modifiers.end();
|
||||
for (std::vector<Modifier*>::iterator it = modifiers.begin(); it != end; ++it)
|
||||
(*it)->destroyBuffers(group);
|
||||
}
|
||||
|
||||
bool ModifierGroup::checkBuffers(const Group& group)
|
||||
{
|
||||
std::vector<Modifier*>::iterator end = modifiers.end();
|
||||
for (std::vector<Modifier*>::iterator it = modifiers.begin(); it != end; ++it)
|
||||
if (!(*it)->checkBuffers(group))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
57
libs/spark/src/Extensions/Modifiers/SPK_Obstacle.cpp
Normal file
57
libs/spark/src/Extensions/Modifiers/SPK_Obstacle.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Modifiers/SPK_Obstacle.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Obstacle::Obstacle(Zone* zone,ModifierTrigger trigger,float bouncingRatio,float friction) :
|
||||
Modifier(INTERSECT_ZONE | ENTER_ZONE | EXIT_ZONE,INTERSECT_ZONE,true,true,zone),
|
||||
bouncingRatio(bouncingRatio),
|
||||
friction(friction)
|
||||
{
|
||||
setTrigger(trigger);
|
||||
}
|
||||
|
||||
void Obstacle::modify(Particle& particle,float deltaTime) const
|
||||
{
|
||||
Vector3D& velocity = particle.velocity();
|
||||
velocity = particle.position();
|
||||
velocity -= particle.oldPosition();
|
||||
|
||||
if (deltaTime != 0.0f)
|
||||
velocity *= 1.0f / deltaTime;
|
||||
else
|
||||
velocity.set(0.0f,0.0f,0.0f);
|
||||
|
||||
float dist = dotProduct(velocity,normal);
|
||||
|
||||
normal *= dist;
|
||||
velocity -= normal; // tangent component
|
||||
velocity *= friction;
|
||||
normal *= bouncingRatio; // normal component
|
||||
velocity -= normal;
|
||||
|
||||
particle.position() = intersection;
|
||||
}
|
||||
}
|
49
libs/spark/src/Extensions/Modifiers/SPK_PointMass.cpp
Normal file
49
libs/spark/src/Extensions/Modifiers/SPK_PointMass.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Modifiers/SPK_PointMass.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
#include "Core/SPK_Zone.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
PointMass::PointMass(Zone* zone,ModifierTrigger trigger,float mass,float minDistance) :
|
||||
Modifier(ALWAYS | INSIDE_ZONE | OUTSIDE_ZONE,ALWAYS,false,false,zone),
|
||||
position(),
|
||||
tPosition(),
|
||||
mass(mass)
|
||||
{
|
||||
setTrigger(trigger);
|
||||
setMinDistance(minDistance);
|
||||
}
|
||||
|
||||
void PointMass::modify(Particle& particle,float deltaTime) const
|
||||
{
|
||||
Vector3D force = tPosition;
|
||||
if (getZone() != NULL)
|
||||
force += getZone()->getTransformedPosition();
|
||||
|
||||
force -= particle.position();
|
||||
force *= mass * deltaTime / std::max(sqrMinDistance,force.getSqrNorm());
|
||||
particle.velocity() += force;
|
||||
}
|
||||
}
|
84
libs/spark/src/Extensions/Modifiers/SPK_Vortex.cpp
Normal file
84
libs/spark/src/Extensions/Modifiers/SPK_Vortex.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Extensions/Modifiers/SPK_Vortex.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Vortex::Vortex(const Vector3D& position,const Vector3D& direction,float rotationSpeed,float attractionSpeed) :
|
||||
Modifier(ALWAYS | INSIDE_ZONE |OUTSIDE_ZONE,ALWAYS,false,false,NULL),
|
||||
rotationSpeed(rotationSpeed),
|
||||
attractionSpeed(attractionSpeed),
|
||||
angularSpeedEnabled(false),
|
||||
linearSpeedEnabled(false),
|
||||
killingParticleEnabled(false),
|
||||
eyeRadius(0.0f)
|
||||
{
|
||||
setPosition(position);
|
||||
setDirection(direction);
|
||||
}
|
||||
|
||||
void Vortex::modify(Particle& particle,float deltaTime) const
|
||||
{
|
||||
// Distance of the projection point from the position of the vortex
|
||||
float dist = dotProduct(tDirection,particle.position() - tPosition);
|
||||
|
||||
// Position of the rotation center (orthogonal projection of the particle)
|
||||
Vector3D rotationCenter = tDirection;
|
||||
rotationCenter *= dist;
|
||||
rotationCenter += tPosition;
|
||||
|
||||
// Distance of the particle from the eye of the vortex
|
||||
dist = getDist(rotationCenter,particle.position());
|
||||
|
||||
if (dist <= eyeRadius)
|
||||
{
|
||||
if (killingParticleEnabled)
|
||||
particle.kill();
|
||||
return;
|
||||
}
|
||||
|
||||
float angle = angularSpeedEnabled ? rotationSpeed * deltaTime : rotationSpeed * deltaTime / dist;
|
||||
|
||||
// Computes ortho base
|
||||
Vector3D normal = (particle.position() - rotationCenter) / dist;
|
||||
Vector3D tangent = crossProduct(tDirection,normal);
|
||||
|
||||
float endRadius = linearSpeedEnabled ? dist * (1.0f - attractionSpeed * deltaTime) : dist - attractionSpeed * deltaTime;
|
||||
if (endRadius <= eyeRadius)
|
||||
{
|
||||
endRadius = eyeRadius;
|
||||
if (killingParticleEnabled)
|
||||
particle.kill();
|
||||
}
|
||||
|
||||
particle.position() = rotationCenter + normal * endRadius * std::cos(angle) + tangent * endRadius * std::sin(angle);
|
||||
}
|
||||
|
||||
void Vortex::innerUpdateTransform()
|
||||
{
|
||||
Modifier::innerUpdateTransform();
|
||||
transformPos(tPosition,position);
|
||||
transformDir(tDirection,direction);
|
||||
tDirection.normalize();
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Extensions/Renderers/SPK_Oriented3DRendererInterface.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Oriented3DRendererInterface::Oriented3DRendererInterface() :
|
||||
lookOrientation(LOOK_CAMERA_PLANE),
|
||||
upOrientation(UP_CAMERA),
|
||||
lockedAxis(LOCK_UP)
|
||||
{
|
||||
lookVector.set(0.0f,0.0f,1.0f);
|
||||
upVector.set(0.0f,1.0f,0.0f);
|
||||
}
|
||||
|
||||
void Oriented3DRendererInterface::setOrientation(LookOrientation lookOrientation,UpOrientation upOrientation,LockedAxis lockedAxis)
|
||||
{
|
||||
this->lookOrientation = lookOrientation;
|
||||
this->upOrientation = upOrientation;
|
||||
this->lockedAxis = lockedAxis;
|
||||
}
|
||||
|
||||
void Oriented3DRendererInterface::setOrientation(OrientationPreset orientation)
|
||||
{
|
||||
this->lookOrientation = static_cast<LookOrientation>((orientation >> 0x8) & 0xFF);
|
||||
this->upOrientation = static_cast<UpOrientation>(orientation & 0xFF);
|
||||
this->lockedAxis = static_cast<LockedAxis>((orientation >> 0x10) & 0xFF);
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Extensions/Renderers/SPK_QuadRendererInterface.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
QuadRendererInterface::QuadRendererInterface(float scaleX,float scaleY) :
|
||||
scaleX(scaleX),
|
||||
scaleY(scaleY),
|
||||
texturingMode(TEXTURE_NONE),
|
||||
textureAtlasNbX(1),
|
||||
textureAtlasNbY(1),
|
||||
textureAtlasW(1.0f),
|
||||
textureAtlasH(1.0f)
|
||||
{}
|
||||
|
||||
void QuadRendererInterface::setAtlasDimensions(size_t nbX,size_t nbY)
|
||||
{
|
||||
textureAtlasNbX = nbX;
|
||||
textureAtlasNbY = nbY;
|
||||
textureAtlasW = 1.0f / nbX;
|
||||
textureAtlasH = 1.0f / nbY;
|
||||
}
|
||||
}
|
160
libs/spark/src/Extensions/Zones/SPK_AABox.cpp
Normal file
160
libs/spark/src/Extensions/Zones/SPK_AABox.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Zones/SPK_AABox.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
AABox::AABox(const Vector3D& position,const Vector3D& dimension) :
|
||||
Zone(position)
|
||||
{
|
||||
setDimension(dimension);
|
||||
}
|
||||
|
||||
void AABox::setDimension(const Vector3D& dimension)
|
||||
{
|
||||
this->dimension.set(std::max(0.0f,dimension.x),std::max(0.0f,dimension.y),std::max(0.0f,dimension.z));
|
||||
}
|
||||
|
||||
void AABox::generatePosition(Particle& particle,bool full) const
|
||||
{
|
||||
particle.position().x = getTransformedPosition().x + random(-dimension.x * 0.5f,dimension.x * 0.5f);
|
||||
particle.position().y = getTransformedPosition().y + random(-dimension.y * 0.5f,dimension.y * 0.5f);
|
||||
particle.position().z = getTransformedPosition().z + random(-dimension.z * 0.5f,dimension.z * 0.5f);
|
||||
|
||||
if (!full)
|
||||
{
|
||||
int axis = random(0,3);
|
||||
int sens = (random(0,2) << 1) - 1;
|
||||
|
||||
switch(axis)
|
||||
{
|
||||
case 0 :
|
||||
particle.position().x = getTransformedPosition().x + sens * dimension.x * 0.5f;
|
||||
break;
|
||||
case 1 :
|
||||
particle.position().y = getTransformedPosition().y + sens * dimension.y * 0.5f;
|
||||
break;
|
||||
default :
|
||||
particle.position().z = getTransformedPosition().z + sens * dimension.z * 0.5f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AABox::contains(const Vector3D& v) const
|
||||
{
|
||||
if ((v.x >= getTransformedPosition().x - dimension.x * 0.5f)&&(v.x <= getTransformedPosition().x + dimension.x * 0.5f)
|
||||
&&(v.y >= getTransformedPosition().y - dimension.y * 0.5f)&&(v.y <= getTransformedPosition().y + dimension.y * 0.5f)
|
||||
&&(v.z >= getTransformedPosition().z - dimension.z * 0.5f)&&(v.z <= getTransformedPosition().z + dimension.z * 0.5f))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AABox::intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const
|
||||
{
|
||||
float tEnter = 0.0f;
|
||||
float tExit = 1.0f;
|
||||
|
||||
int axis;
|
||||
|
||||
if (!slabIntersects(v0.x,v1.x,getTransformedPosition().x - dimension.x * 0.5f,getTransformedPosition().x + dimension.x * 0.5f,tEnter,tExit,axis,0))
|
||||
return false;
|
||||
|
||||
if (!slabIntersects(v0.y,v1.y,getTransformedPosition().y - dimension.y * 0.5f,getTransformedPosition().y + dimension.y * 0.5f,tEnter,tExit,axis,1))
|
||||
return false;
|
||||
|
||||
if (!slabIntersects(v0.z,v1.z,getTransformedPosition().z - dimension.z * 0.5f,getTransformedPosition().z + dimension.z * 0.5f,tEnter,tExit,axis,2))
|
||||
return false;
|
||||
|
||||
if ((tEnter <= 0.0f)&&(tExit >= 1.0f))
|
||||
return false;
|
||||
|
||||
if (intersection != NULL)
|
||||
{
|
||||
if (tEnter <= 0.0f)
|
||||
{
|
||||
tEnter = tExit;
|
||||
axis = (axis & 0xF0) >> 4;
|
||||
}
|
||||
else
|
||||
axis &= 0x0F;
|
||||
|
||||
Vector3D vDir = v1 - v0;
|
||||
float norm = vDir.getNorm() * tEnter;
|
||||
tEnter = norm < APPROXIMATION_VALUE ? 0.0f : tEnter * (norm - APPROXIMATION_VALUE) / norm;
|
||||
|
||||
vDir *= tEnter;
|
||||
*intersection = v0 + vDir;
|
||||
|
||||
if (normal != NULL)
|
||||
{
|
||||
switch(axis)
|
||||
{
|
||||
case 0 :
|
||||
*normal = Vector3D(-1.0f,0.0f,0.0f);
|
||||
break;
|
||||
case 1 :
|
||||
*normal = Vector3D(0.0f,-1.0f,0.0f);
|
||||
break;
|
||||
case 2 :
|
||||
*normal = Vector3D(0.0f,0.0f,-1.0f);
|
||||
break;
|
||||
case 3 :
|
||||
*normal = Vector3D(1.0f,0.0f,0.0f);
|
||||
break;
|
||||
case 4 :
|
||||
*normal = Vector3D(0.0f,1.0f,0.0f);
|
||||
break;
|
||||
case 5 :
|
||||
*normal = Vector3D(0.0f,0.0f,1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AABox::moveAtBorder(Vector3D& v,bool inside) const
|
||||
{
|
||||
if (inside)
|
||||
{
|
||||
Vector3D rayEnd(v - getTransformedPosition());
|
||||
float maxDim = getTransformedPosition().x + getTransformedPosition().y + getTransformedPosition().z;
|
||||
rayEnd *= maxDim * maxDim / rayEnd.getSqrNorm();
|
||||
intersects(getTransformedPosition() + rayEnd,getTransformedPosition(),&v,NULL);
|
||||
}
|
||||
else
|
||||
intersects(getTransformedPosition(),v,&v,NULL);
|
||||
}
|
||||
|
||||
Vector3D AABox::computeNormal(const Vector3D& point) const
|
||||
{
|
||||
// TO DO
|
||||
Vector3D normal(point - getTransformedPosition());
|
||||
normalizeOrRandomize(normal);
|
||||
return normal;
|
||||
}
|
||||
}
|
92
libs/spark/src/Extensions/Zones/SPK_Line.cpp
Normal file
92
libs/spark/src/Extensions/Zones/SPK_Line.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Zones/SPK_Line.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Line::Line(const Vector3D& p0,const Vector3D& p1) :
|
||||
Zone(Vector3D())
|
||||
{
|
||||
setBounds(p0,p1);
|
||||
}
|
||||
|
||||
void Line::setPosition(const Vector3D& v)
|
||||
{
|
||||
Vector3D displacement = v - getPosition();
|
||||
bounds[0] = tBounds[0] += displacement;
|
||||
bounds[1] = tBounds[1] += displacement;
|
||||
computeDist();
|
||||
Zone::setPosition(v);
|
||||
}
|
||||
|
||||
void Line::setBounds(const Vector3D& p0,const Vector3D& p1)
|
||||
{
|
||||
bounds[0] = tBounds[0] = p0;
|
||||
bounds[1] = tBounds[1] = p1;
|
||||
computeDist();
|
||||
computePosition();
|
||||
}
|
||||
|
||||
void Line::pushBound(const Vector3D& bound)
|
||||
{
|
||||
bounds[0] = tBounds[0] = bounds[1];
|
||||
bounds[1] = tBounds[1] = bound;
|
||||
computeDist();
|
||||
computePosition();
|
||||
}
|
||||
|
||||
void Line::generatePosition(Particle& particle,bool full) const
|
||||
{
|
||||
float ratio = random(0.0f,1.0f);
|
||||
particle.position() = tBounds[0] + tDist * ratio;
|
||||
}
|
||||
|
||||
Vector3D Line::computeNormal(const Vector3D& point) const
|
||||
{
|
||||
float d = -dotProduct(tDist,point);
|
||||
float sqrNorm = tDist.getSqrNorm();
|
||||
float t = 0.0f;
|
||||
if (sqrNorm > 0.0f)
|
||||
{
|
||||
t = -(dotProduct(tDist,tBounds[0]) + d) / sqrNorm;
|
||||
// t is clamped to the segment
|
||||
if (t < 0.0f) t = 0.0f;
|
||||
else if (t > 1.0f) t = 1.0f;
|
||||
}
|
||||
|
||||
Vector3D normal = point;
|
||||
normal -= tBounds[0] + t * tDist;
|
||||
|
||||
normalizeOrRandomize(normal);
|
||||
return normal;
|
||||
}
|
||||
|
||||
void Line::innerUpdateTransform()
|
||||
{
|
||||
Zone::innerUpdateTransform();
|
||||
transformPos(tBounds[0],bounds[0]);
|
||||
transformPos(tBounds[1],bounds[1]);
|
||||
computeDist();
|
||||
}
|
||||
}
|
84
libs/spark/src/Extensions/Zones/SPK_Plane.cpp
Normal file
84
libs/spark/src/Extensions/Zones/SPK_Plane.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Zones/SPK_Plane.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Plane::Plane(const Vector3D& position,const Vector3D& normal) :
|
||||
Zone(position)
|
||||
{
|
||||
setNormal(normal);
|
||||
}
|
||||
|
||||
bool Plane::intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const
|
||||
{
|
||||
float dist0 = dotProduct(tNormal,v0 - getTransformedPosition());
|
||||
float dist1 = dotProduct(tNormal,v1 - getTransformedPosition());
|
||||
|
||||
if ((dist0 <= 0.0f) == (dist1 <= 0.0f)) // both points are on the same side
|
||||
return false;
|
||||
|
||||
if (intersection != NULL)
|
||||
{
|
||||
if (dist0 <= 0.0f)
|
||||
dist0 = -dist0;
|
||||
else
|
||||
dist1 = -dist1;
|
||||
|
||||
if (normal != NULL)
|
||||
*normal = tNormal;
|
||||
|
||||
float ti = dist0 / (dist0 + dist1);
|
||||
|
||||
Vector3D vDir = v1 - v0;
|
||||
float norm = vDir.getNorm();
|
||||
|
||||
norm *= ti;
|
||||
ti = norm < APPROXIMATION_VALUE ? 0.0f : ti * (norm - APPROXIMATION_VALUE) / norm;
|
||||
|
||||
vDir *= ti;
|
||||
*intersection = v0 + vDir;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Plane::moveAtBorder(Vector3D& v,bool inside) const
|
||||
{
|
||||
float dist = dotProduct(tNormal,v - getTransformedPosition());
|
||||
|
||||
if ((dist <= 0.0f) == inside)
|
||||
inside ? dist += APPROXIMATION_VALUE : dist -= APPROXIMATION_VALUE;
|
||||
else
|
||||
inside ? dist -= APPROXIMATION_VALUE : dist += APPROXIMATION_VALUE;
|
||||
|
||||
v += tNormal * -dist;
|
||||
}
|
||||
|
||||
void Plane::innerUpdateTransform()
|
||||
{
|
||||
Zone::innerUpdateTransform();
|
||||
transformDir(tNormal,normal);
|
||||
tNormal.normalize();
|
||||
}
|
||||
}
|
38
libs/spark/src/Extensions/Zones/SPK_Point.cpp
Normal file
38
libs/spark/src/Extensions/Zones/SPK_Point.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Zones/SPK_Point.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Point::Point(const Vector3D& position) :
|
||||
Zone(position)
|
||||
{}
|
||||
|
||||
Vector3D Point::computeNormal(const Vector3D& point) const
|
||||
{
|
||||
Vector3D normal(point - getTransformedPosition());
|
||||
normalizeOrRandomize(normal);
|
||||
|
||||
return normal;
|
||||
}
|
||||
}
|
125
libs/spark/src/Extensions/Zones/SPK_Ring.cpp
Normal file
125
libs/spark/src/Extensions/Zones/SPK_Ring.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Extensions/Zones/SPK_Ring.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Ring::Ring(const Vector3D& position,const Vector3D& normal,float minRadius,float maxRadius) :
|
||||
Zone(position)
|
||||
{
|
||||
setNormal(normal);
|
||||
setRadius(minRadius,maxRadius);
|
||||
}
|
||||
|
||||
inline void Ring::setRadius(float minRadius,float maxRadius)
|
||||
{
|
||||
if (minRadius < 0.0f) minRadius = -minRadius;
|
||||
if (maxRadius < 0.0f) maxRadius = -maxRadius;
|
||||
if (minRadius > maxRadius) std::swap(minRadius,maxRadius);
|
||||
this->minRadius = minRadius;
|
||||
this->maxRadius = maxRadius;
|
||||
sqrMinRadius = minRadius * minRadius;
|
||||
sqrMaxRadius = maxRadius * maxRadius;
|
||||
}
|
||||
|
||||
void Ring::generatePosition(Particle& particle,bool full) const
|
||||
{
|
||||
Vector3D tmp;
|
||||
do tmp = Vector3D(random(-1.0f,1.0f),random(-1.0f,1.0f),random(-1.0f,1.0f));
|
||||
while (tmp.getSqrNorm() > 1.0f);
|
||||
|
||||
crossProduct(tNormal,tmp,particle.position());
|
||||
normalizeOrRandomize(particle.position());
|
||||
|
||||
particle.position() *= std::sqrt(random(sqrMinRadius,sqrMaxRadius)); // to have a uniform distribution
|
||||
particle.position() += getTransformedPosition();
|
||||
}
|
||||
|
||||
bool Ring::intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const
|
||||
{
|
||||
float dist0 = dotProduct(tNormal,v0 - getTransformedPosition());
|
||||
float dist1 = dotProduct(tNormal,v1 - getTransformedPosition());
|
||||
|
||||
if ((dist0 <= 0.0f) == (dist1 <= 0.0f)) // both points are on the same side
|
||||
return false;
|
||||
|
||||
if (dist0 <= 0.0f)
|
||||
dist0 = -dist0;
|
||||
else
|
||||
dist1 = -dist1;
|
||||
|
||||
float ti = dist0 / (dist0 + dist1);
|
||||
|
||||
Vector3D vDir(v1 - v0);
|
||||
float norm = vDir.getNorm();
|
||||
|
||||
norm *= ti;
|
||||
ti = norm < APPROXIMATION_VALUE ? 0.0f : ti * (norm - APPROXIMATION_VALUE) / norm;
|
||||
|
||||
vDir *= ti;
|
||||
Vector3D inter(v0 + vDir);
|
||||
|
||||
float distFromCenter = getSqrDist(inter,getTransformedPosition());
|
||||
if (distFromCenter > sqrMaxRadius || distFromCenter < sqrMinRadius) // intersection is not in the ring
|
||||
return false;
|
||||
|
||||
if (intersection != NULL)
|
||||
{
|
||||
*intersection = inter;
|
||||
if (normal != NULL)
|
||||
*normal = tNormal;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Ring::moveAtBorder(Vector3D& v,bool inside) const
|
||||
{
|
||||
float dist = dotProduct(tNormal,v - getTransformedPosition());
|
||||
v += tNormal * -dist;
|
||||
|
||||
float distFromCenter = getSqrDist(v,getTransformedPosition());
|
||||
|
||||
if (distFromCenter > sqrMaxRadius)
|
||||
{
|
||||
distFromCenter = std::sqrt(distFromCenter);
|
||||
Vector3D vDir(v - getTransformedPosition());
|
||||
vDir *= maxRadius / distFromCenter;
|
||||
v = getTransformedPosition() + vDir;
|
||||
}
|
||||
else if (distFromCenter < sqrMinRadius)
|
||||
{
|
||||
distFromCenter = std::sqrt(distFromCenter);
|
||||
Vector3D vDir(v - getTransformedPosition());
|
||||
vDir *= minRadius / distFromCenter;
|
||||
v = getTransformedPosition() + vDir;
|
||||
}
|
||||
}
|
||||
|
||||
void Ring::innerUpdateTransform()
|
||||
{
|
||||
Zone::innerUpdateTransform();
|
||||
transformDir(tNormal,normal);
|
||||
tNormal.normalize();
|
||||
}
|
||||
}
|
116
libs/spark/src/Extensions/Zones/SPK_Sphere.cpp
Normal file
116
libs/spark/src/Extensions/Zones/SPK_Sphere.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "Extensions/Zones/SPK_Sphere.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
Sphere::Sphere(const Vector3D& position,float radius) :
|
||||
Zone(position)
|
||||
{
|
||||
setRadius(radius);
|
||||
}
|
||||
|
||||
void Sphere::generatePosition(Particle& particle,bool full) const
|
||||
{
|
||||
do particle.position() = Vector3D(random(-radius,radius),random(-radius,radius),random(-radius,radius));
|
||||
while (particle.position().getSqrNorm() > radius * radius);
|
||||
|
||||
if ((!full)&&(radius > 0.0f))
|
||||
particle.position() *= radius / particle.position().getNorm();
|
||||
|
||||
particle.position() += getTransformedPosition();
|
||||
}
|
||||
|
||||
bool Sphere::contains(const Vector3D& v) const
|
||||
{
|
||||
return getSqrDist(getTransformedPosition(),v) <= radius * radius;
|
||||
}
|
||||
|
||||
bool Sphere::intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const
|
||||
{
|
||||
float r2 = radius * radius;
|
||||
float dist0 = getSqrDist(getTransformedPosition(),v0);
|
||||
float dist1 = getSqrDist(getTransformedPosition(),v1);
|
||||
|
||||
if ((dist0 <= r2) == (dist1 <= r2))
|
||||
return false;
|
||||
|
||||
if (intersection != NULL)
|
||||
{
|
||||
Vector3D vDir = v1 - v0;
|
||||
float norm = vDir.getNorm();
|
||||
|
||||
float d = dotProduct(vDir,getTransformedPosition() - v0) / norm;
|
||||
float a = std::sqrt(r2 - dist0 + d * d);
|
||||
|
||||
float ti;
|
||||
if (dist0 <= r2)
|
||||
ti = d - a;
|
||||
else
|
||||
ti = d + a;
|
||||
|
||||
ti /= norm;
|
||||
|
||||
if (ti < 0.0f) ti = 0.0f;
|
||||
if (ti > 1.0f) ti = 1.0f;
|
||||
|
||||
norm *= ti;
|
||||
ti = norm < APPROXIMATION_VALUE ? 0.0f : ti * (norm - APPROXIMATION_VALUE) / norm;
|
||||
|
||||
vDir *= ti;
|
||||
*intersection = v0 + vDir;
|
||||
|
||||
if (normal != NULL)
|
||||
{
|
||||
if (dist0 <= r2)
|
||||
*normal = getTransformedPosition() - *intersection;
|
||||
else
|
||||
*normal = *intersection - getTransformedPosition();
|
||||
normal->normalize();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sphere::moveAtBorder(Vector3D& v,bool inside) const
|
||||
{
|
||||
Vector3D vDir = v - getTransformedPosition();
|
||||
float norm = vDir.getNorm();
|
||||
|
||||
if (inside)
|
||||
vDir *= (radius + APPROXIMATION_VALUE) / norm;
|
||||
else
|
||||
vDir *= (radius - APPROXIMATION_VALUE) / norm;
|
||||
|
||||
v = getTransformedPosition() + vDir;
|
||||
}
|
||||
|
||||
Vector3D Sphere::computeNormal(const Vector3D& point) const
|
||||
{
|
||||
Vector3D normal(point - getTransformedPosition());
|
||||
normalizeOrRandomize(normal);
|
||||
return normal;
|
||||
}
|
||||
}
|
326
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLExtHandler.cpp
Normal file
326
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLExtHandler.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLExtHandler.h"
|
||||
|
||||
#if defined(__APPLE__) || defined(macintosh)
|
||||
// Necessary includes to get GL functions pointers from MAC
|
||||
#include <mach-o/dyld.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
namespace GL
|
||||
{
|
||||
GLExtHandler::GLExtension GLExtHandler::pointSpriteGLExt = UNCHECKED;
|
||||
GLExtHandler::GLExtension GLExtHandler::pointParameterGLExt = UNCHECKED;
|
||||
GLExtHandler::GLExtension GLExtHandler::texture3DGLExt = UNCHECKED;
|
||||
GLExtHandler::GLExtension GLExtHandler::shaderGLExt = UNCHECKED;
|
||||
|
||||
GLExtHandler::SPK_PFNGLPOINTPARAMETERFPROC GLExtHandler::SPK_glPointParameterf = NULL;
|
||||
GLExtHandler::SPK_PFNGLPOINTPARAMETERFVPROC GLExtHandler::SPK_glPointParameterfv = NULL;
|
||||
GLExtHandler::SPK_PFNGLTEXIMAGE3DPROC GLExtHandler::SPK_glTexImage3D = NULL;
|
||||
GLExtHandler::SPK_PFNGLCREATESHADERPROC GLExtHandler::SPK_glCreateShader = NULL;
|
||||
GLExtHandler::SPK_PFNGLDELETESHADERPROC GLExtHandler::SPK_glDeleteShader = NULL;
|
||||
GLExtHandler::SPK_PFNGLSHADERSOURCEPROC GLExtHandler::SPK_glShaderSource = NULL;
|
||||
GLExtHandler::SPK_PFNGLCOMPILESHADERPROC GLExtHandler::SPK_glCompileShader = NULL;
|
||||
GLExtHandler::SPK_PFNGLCREATEPROGRAMPROC GLExtHandler::SPK_glCreateProgram = NULL;
|
||||
GLExtHandler::SPK_PFNGLDELETEPROGRAMPROC GLExtHandler::SPK_glDeleteProgram = NULL;
|
||||
GLExtHandler::SPK_PFNGLATTACHSHADERPROC GLExtHandler::SPK_glAttachShader = NULL;
|
||||
GLExtHandler::SPK_PFNGLDETACHSHADERPROC GLExtHandler::SPK_glDetachShader = NULL;
|
||||
GLExtHandler::SPK_PFNGLLINKPROGRAMPROC GLExtHandler::SPK_glLinkProgram = NULL;
|
||||
GLExtHandler::SPK_PFNGLUSEPROGRAMPROC GLExtHandler::SPK_glUseProgram = NULL;
|
||||
|
||||
const float GLExtHandler::QUADRATIC_SCREEN[3] = {1.0f,0.0f,0.0f};
|
||||
|
||||
float GLExtHandler::pixelPerUnit = 1024.0f;
|
||||
|
||||
const float GLExtHandler::POINT_SIZE_CURRENT = 32.0f;
|
||||
const float GLExtHandler::POINT_SIZE_MIN = 1.0f;
|
||||
const float GLExtHandler::POINT_SIZE_MAX = 1024.0f;
|
||||
|
||||
#ifdef SPK_NO_GLEXT
|
||||
bool GLExtHandler::loadGLExtPointSprite()
|
||||
{
|
||||
pointSpriteGLExt = UNSUPPORTED;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GLExtHandler::loadGLExtPointParameter()
|
||||
{
|
||||
pointParameterGLExt = UNSUPPORTED;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GLExtHandler::loadGLExtTexture3D()
|
||||
{
|
||||
texture3DGLExt = UNSUPPORTED;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GLExtHandler::loadGLExtShader()
|
||||
{
|
||||
shaderGLExt = UNSUPPORTED;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
bool GLExtHandler::loadGLExtPointSprite()
|
||||
{
|
||||
if (pointSpriteGLExt == UNCHECKED)
|
||||
{
|
||||
pointSpriteGLExt = UNSUPPORTED;
|
||||
|
||||
std::string version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
// openGL 2.0 and higher
|
||||
if (int(version[0] - '0') >= 2)
|
||||
pointSpriteGLExt = SUPPORTED;
|
||||
else
|
||||
{
|
||||
std::string extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
if ((extensions.find("GL_ARB_point_sprites") != std::string::npos)
|
||||
||(extensions.find("GL_NV_point_sprites") != std::string::npos))
|
||||
pointSpriteGLExt = SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return pointSpriteGLExt == SUPPORTED;
|
||||
}
|
||||
|
||||
bool GLExtHandler::loadGLExtPointParameter()
|
||||
{
|
||||
if (pointParameterGLExt == UNCHECKED)
|
||||
{
|
||||
pointParameterGLExt = UNSUPPORTED;
|
||||
|
||||
std::string version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
std::string extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
|
||||
// openGL 1.4 and higher
|
||||
if (((int(version[0] - '0') == 1)&&(int(version[2] - '0') >= 4))
|
||||
||(int(version[0] - '0') > 1))
|
||||
{
|
||||
SPK_glPointParameterf = (SPK_PFNGLPOINTPARAMETERFPROC)glGetProcAddress("glPointParameterf");
|
||||
SPK_glPointParameterfv = (SPK_PFNGLPOINTPARAMETERFVPROC)glGetProcAddress("glPointParameterfv");
|
||||
}
|
||||
|
||||
// point parameter ARB
|
||||
if (((SPK_glPointParameterf == NULL)||(SPK_glPointParameterfv == NULL))
|
||||
&&(extensions.find("GL_ARB_point_parameters") != std::string::npos))
|
||||
{
|
||||
SPK_glPointParameterf = (SPK_PFNGLPOINTPARAMETERFPROC)glGetProcAddress("glPointParameterfARB");
|
||||
SPK_glPointParameterfv = (SPK_PFNGLPOINTPARAMETERFVPROC)glGetProcAddress("glPointParameterfvARB");
|
||||
}
|
||||
|
||||
// point parameter EXT
|
||||
if (((SPK_glPointParameterf == NULL)||(SPK_glPointParameterfv == NULL))
|
||||
&&(extensions.find("GL_EXT_point_parameters") != std::string::npos))
|
||||
{
|
||||
SPK_glPointParameterf = (SPK_PFNGLPOINTPARAMETERFPROC)glGetProcAddress("glPointParameterfEXT");
|
||||
SPK_glPointParameterfv = (SPK_PFNGLPOINTPARAMETERFVPROC)glGetProcAddress("glPointParameterfvEXT");
|
||||
}
|
||||
|
||||
// point parameter SGIS
|
||||
if (((SPK_glPointParameterf == NULL)||(SPK_glPointParameterfv == NULL))
|
||||
&&(extensions.find("GL_SGIS_point_parameters") != std::string::npos))
|
||||
{
|
||||
SPK_glPointParameterf = (SPK_PFNGLPOINTPARAMETERFPROC)glGetProcAddress("glPointParameterfSGIS");
|
||||
SPK_glPointParameterfv = (SPK_PFNGLPOINTPARAMETERFVPROC)glGetProcAddress("glPointParameterfvSGIS");
|
||||
}
|
||||
|
||||
if ((SPK_glPointParameterf != NULL)&&(SPK_glPointParameterfv != NULL))
|
||||
pointParameterGLExt = SUPPORTED;
|
||||
}
|
||||
|
||||
return pointParameterGLExt == SUPPORTED;
|
||||
}
|
||||
|
||||
bool GLExtHandler::loadGLExtTexture3D()
|
||||
{
|
||||
if (texture3DGLExt == UNCHECKED)
|
||||
{
|
||||
texture3DGLExt = UNSUPPORTED;
|
||||
|
||||
std::string version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
std::string extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
|
||||
// openGL 1.2 and higher
|
||||
if (((int(version[0] - '0') == 1)&&(int(version[2] - '0') >= 4))
|
||||
||(int(version[0] - '0') > 1))
|
||||
SPK_glTexImage3D = (SPK_PFNGLTEXIMAGE3DPROC)glGetProcAddress("glTexImage3D");
|
||||
|
||||
// texture 3D EXT
|
||||
if ((SPK_glTexImage3D == NULL)&&(extensions.find("GL_EXT_texture3D") != std::string::npos))
|
||||
SPK_glTexImage3D = (SPK_PFNGLTEXIMAGE3DPROC)glGetProcAddress("glTexImage3DEXT");
|
||||
|
||||
if (SPK_glTexImage3D != NULL)
|
||||
texture3DGLExt = SUPPORTED;
|
||||
}
|
||||
|
||||
return texture3DGLExt == SUPPORTED;
|
||||
}
|
||||
|
||||
bool GLExtHandler::loadGLExtShader()
|
||||
{
|
||||
if (shaderGLExt == UNCHECKED)
|
||||
{
|
||||
shaderGLExt = UNSUPPORTED;
|
||||
|
||||
std::string version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
|
||||
// openGL 2.0 and higher
|
||||
if (int(version[0] - '0') >= 2)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if (ok && ((SPK_glCreateShader = (SPK_PFNGLCREATESHADERPROC)glGetProcAddress("glCreateShader")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glDeleteShader = (SPK_PFNGLDELETESHADERPROC)glGetProcAddress("glDeleteShader")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glShaderSource = (SPK_PFNGLSHADERSOURCEPROC)glGetProcAddress("glShaderSource")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glCompileShader = (SPK_PFNGLCOMPILESHADERPROC)glGetProcAddress("glCompileShader")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glCreateProgram = (SPK_PFNGLCREATEPROGRAMPROC)glGetProcAddress("glCreateProgram")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glDeleteProgram = (SPK_PFNGLDELETEPROGRAMPROC)glGetProcAddress("glDeleteProgram")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glAttachShader = (SPK_PFNGLATTACHSHADERPROC)glGetProcAddress("glAttachShader")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glDetachShader = (SPK_PFNGLDETACHSHADERPROC)glGetProcAddress("glDetachShader")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glLinkProgram = (SPK_PFNGLLINKPROGRAMPROC)glGetProcAddress("glLinkProgram")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glUseProgram = (SPK_PFNGLUSEPROGRAMPROC)glGetProcAddress("glUseProgram")) == NULL)) ok = false;
|
||||
|
||||
if (ok) shaderGLExt = SUPPORTED;
|
||||
}
|
||||
|
||||
if (shaderGLExt == UNSUPPORTED)
|
||||
{
|
||||
std::string extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
|
||||
if ((extensions.find("GL_ARB_shading_language_100") != std::string::npos)&&
|
||||
(extensions.find("GL_ARB_shader_objects") != std::string::npos)&&
|
||||
(extensions.find("GL_ARB_vertex_shader") != std::string::npos)&&
|
||||
(extensions.find("GL_ARB_fragment_shader") != std::string::npos))
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if (ok && ((SPK_glCreateShader = (SPK_PFNGLCREATESHADERPROC)glGetProcAddress("glCreateShaderObjectARB")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glDeleteShader = SPK_glDeleteProgram = (SPK_PFNGLDELETESHADERPROC)glGetProcAddress("glDeleteObjectARB")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glShaderSource = (SPK_PFNGLSHADERSOURCEPROC)glGetProcAddress("glShaderSourceARB")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glCompileShader = (SPK_PFNGLCOMPILESHADERPROC)glGetProcAddress("glCompileShaderARB")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glCreateProgram = (SPK_PFNGLCREATEPROGRAMPROC)glGetProcAddress("glCreateProgramObjectARB")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glAttachShader = (SPK_PFNGLATTACHSHADERPROC)glGetProcAddress("glAttachObjectARB")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glDetachShader = (SPK_PFNGLDETACHSHADERPROC)glGetProcAddress("glDetachObjectARB")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glLinkProgram = (SPK_PFNGLLINKPROGRAMPROC)glGetProcAddress("glLinkProgramARB")) == NULL)) ok = false;
|
||||
if (ok && ((SPK_glUseProgram = (SPK_PFNGLUSEPROGRAMPROC)glGetProcAddress("glUseProgramObjectARB")) == NULL)) ok = false;
|
||||
|
||||
if (ok) shaderGLExt = SUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shaderGLExt == SUPPORTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(macintosh)
|
||||
void* GLExtHandler::SPK_NSGLGetProcAddress(const char* name)
|
||||
{
|
||||
NSSymbol symbol;
|
||||
char *symbolName;
|
||||
|
||||
symbolName = (char*)malloc (strlen (name) + 2);
|
||||
strcpy(symbolName + 1, name);
|
||||
symbolName[0] = '_';
|
||||
symbol = NULL;
|
||||
|
||||
if (NSIsSymbolNameDefined (symbolName))
|
||||
symbol = NSLookupAndBindSymbol (symbolName);
|
||||
|
||||
free (symbolName);
|
||||
|
||||
return symbol ? NSAddressOfSymbol (symbol) : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void GLExtHandler::setPixelPerUnit(float fovy,int screenHeight)
|
||||
{
|
||||
// the pixel per unit is computed for a distance from the camera of screenHeight
|
||||
pixelPerUnit = screenHeight / (2.0f * tan(fovy * 0.5f));
|
||||
}
|
||||
|
||||
void GLExtHandler::glTexImage3D(GLenum target,
|
||||
GLint level,
|
||||
GLenum internalFormat,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLsizei depth,
|
||||
GLint border,
|
||||
GLenum format,
|
||||
GLenum type,
|
||||
const GLvoid* pixels)
|
||||
{
|
||||
if (loadGLExtTexture3D())
|
||||
SPK_glTexImage3D(target,level,internalFormat,width,height,depth,border,format,type,pixels);
|
||||
}
|
||||
|
||||
GLExtHandler::GLExtension GLExtHandler::getPointSpriteGLExt()
|
||||
{
|
||||
return pointSpriteGLExt;
|
||||
}
|
||||
|
||||
GLExtHandler::GLExtension GLExtHandler::getPointParameterGLExt()
|
||||
{
|
||||
return pointParameterGLExt;
|
||||
}
|
||||
|
||||
void GLExtHandler::enablePointParameterGLExt(float size,bool distance)
|
||||
{
|
||||
// derived size = size * sqrt(1 / (A + B * distance + C * distance<63>))
|
||||
if (distance)
|
||||
{
|
||||
const float sqrtC = POINT_SIZE_CURRENT / (size * pixelPerUnit);
|
||||
const float QUADRATIC_WORLD[3] = {0.0f,0.0f,sqrtC * sqrtC}; // A = 0; B = 0; C = (POINT_SIZE_CURRENT / (size * pixelPerUnit))<29>
|
||||
SPK_glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION,QUADRATIC_WORLD);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float sqrtA = POINT_SIZE_CURRENT / size;
|
||||
const float QUADRATIC_WORLD[3] = {sqrtA * sqrtA,0.0f,0.0f}; // A = (POINT_SIZE_CURRENT / size)<29>; B = 0; C = 0
|
||||
SPK_glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION,QUADRATIC_WORLD);
|
||||
}
|
||||
|
||||
glPointSize(POINT_SIZE_CURRENT);
|
||||
SPK_glPointParameterf(GL_POINT_SIZE_MIN,POINT_SIZE_MIN);
|
||||
SPK_glPointParameterf(GL_POINT_SIZE_MAX,POINT_SIZE_MAX);
|
||||
}
|
||||
|
||||
void GLExtHandler::disablePointParameterGLExt()
|
||||
{
|
||||
SPK_glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION,QUADRATIC_SCREEN);
|
||||
}
|
||||
|
||||
GLExtHandler::GLExtension GLExtHandler::getTexture3DGLExt()
|
||||
{
|
||||
return texture3DGLExt;
|
||||
}
|
||||
|
||||
GLExtHandler::GLExtension GLExtHandler::getShaderGLExt()
|
||||
{
|
||||
return shaderGLExt;
|
||||
}
|
||||
}}
|
107
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLLineRenderer.cpp
Normal file
107
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLLineRenderer.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLLineRenderer.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
#include "Core/SPK_Group.h"
|
||||
#include "Core/SPK_ArrayBuffer.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
namespace GL
|
||||
{
|
||||
const std::string GLLineRenderer::GPU_BUFFER_NAME("SPK_GLLineRenderer_GPU");
|
||||
|
||||
float* GLLineRenderer::gpuBuffer = NULL;
|
||||
float* GLLineRenderer::gpuIterator = NULL;
|
||||
|
||||
GLLineRenderer::GLLineRenderer(float length,float width) :
|
||||
GLRenderer(),
|
||||
LineRendererInterface(length,width)
|
||||
{}
|
||||
|
||||
bool GLLineRenderer::checkBuffers(const Group& group)
|
||||
{
|
||||
FloatBuffer* fBuffer;
|
||||
if ((fBuffer = dynamic_cast<FloatBuffer*>(group.getBuffer(GPU_BUFFER_NAME))) == NULL)
|
||||
return false;
|
||||
|
||||
gpuIterator = gpuBuffer = fBuffer->getData();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLLineRenderer::createBuffers(const Group& group)
|
||||
{
|
||||
FloatBuffer* fBuffer = dynamic_cast<FloatBuffer*>(group.createBuffer(GPU_BUFFER_NAME,FloatBufferCreator(14),0,false));
|
||||
gpuIterator = gpuBuffer = fBuffer->getData();
|
||||
}
|
||||
|
||||
void GLLineRenderer::destroyBuffers(const Group& group)
|
||||
{
|
||||
group.destroyBuffer(GPU_BUFFER_NAME);
|
||||
}
|
||||
|
||||
void GLLineRenderer::render(const Group& group)
|
||||
{
|
||||
if (!prepareBuffers(group))
|
||||
return;
|
||||
|
||||
initBlending();
|
||||
initRenderingHints();
|
||||
|
||||
glLineWidth(width);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
for (size_t i = 0; i < group.getNbParticles(); ++i)
|
||||
{
|
||||
const Particle& particle = group.getParticle(i);
|
||||
|
||||
*(gpuIterator++) = particle.position().x;
|
||||
*(gpuIterator++) = particle.position().y;
|
||||
*(gpuIterator++) = particle.position().z;
|
||||
|
||||
gpuIterator += 4; // skips the first vertex color data as GL_FLAT was forced
|
||||
|
||||
*(gpuIterator++) = particle.position().x + particle.velocity().x * length;
|
||||
*(gpuIterator++) = particle.position().y + particle.velocity().y * length;
|
||||
*(gpuIterator++) = particle.position().z + particle.velocity().z * length;
|
||||
|
||||
*(gpuIterator++) = particle.getR();
|
||||
*(gpuIterator++) = particle.getG();
|
||||
*(gpuIterator++) = particle.getB();
|
||||
*(gpuIterator++) = particle.getParamCurrentValue(PARAM_ALPHA);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
// interleaves vertex and color data
|
||||
glVertexPointer(3,GL_FLOAT,7 * sizeof(float),gpuBuffer);
|
||||
glColorPointer(4,GL_FLOAT,7 * sizeof(float),gpuBuffer + 3);
|
||||
|
||||
glDrawArrays(GL_LINES,0,group.getNbParticles() << 1);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
}}
|
204
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLLineTrailRenderer.cpp
Normal file
204
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLLineTrailRenderer.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLLineTrailRenderer.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
#include "Core/SPK_Group.h"
|
||||
#include "Core/SPK_ArrayBuffer.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
namespace GL
|
||||
{
|
||||
const std::string GLLineTrailRenderer::VERTEX_BUFFER_NAME("SPK_GLLineTrailRenderer_Vertex");
|
||||
const std::string GLLineTrailRenderer::COLOR_BUFFER_NAME("SPK_GLLineTrailRenderer_Color");
|
||||
const std::string GLLineTrailRenderer::VALUE_BUFFER_NAME("SPK_GLLineTrailRenderer_Value");
|
||||
|
||||
float* GLLineTrailRenderer::vertexBuffer = NULL;
|
||||
float* GLLineTrailRenderer::vertexIterator = NULL;
|
||||
float* GLLineTrailRenderer::colorBuffer = NULL;
|
||||
float* GLLineTrailRenderer::colorIterator = NULL;
|
||||
float* GLLineTrailRenderer::valueBuffer = NULL;
|
||||
float* GLLineTrailRenderer::valueIterator = NULL;
|
||||
|
||||
GLLineTrailRenderer::GLLineTrailRenderer() :
|
||||
GLRenderer(),
|
||||
nbSamples(8),
|
||||
width(1.0f),
|
||||
duration(1.0f),
|
||||
degeneratedR(0.0f),
|
||||
degeneratedG(0.0f),
|
||||
degeneratedB(0.0f),
|
||||
degeneratedA(0.0f)
|
||||
{
|
||||
enableBlending(true);
|
||||
}
|
||||
|
||||
void GLLineTrailRenderer::setDegeneratedLines(float r,float g,float b,float a)
|
||||
{
|
||||
degeneratedR = r;
|
||||
degeneratedG = g;
|
||||
degeneratedB = b;
|
||||
degeneratedA = a;
|
||||
}
|
||||
|
||||
bool GLLineTrailRenderer::checkBuffers(const Group& group)
|
||||
{
|
||||
FloatBuffer* fVertexBuffer;
|
||||
FloatBuffer* fColorBuffer;
|
||||
FloatBuffer* fValueBuffer;
|
||||
|
||||
if ((fVertexBuffer = dynamic_cast<FloatBuffer*>(group.getBuffer(VERTEX_BUFFER_NAME,nbSamples))) == NULL)
|
||||
return false;
|
||||
|
||||
if ((fColorBuffer = dynamic_cast<FloatBuffer*>(group.getBuffer(COLOR_BUFFER_NAME,nbSamples))) == NULL)
|
||||
return false;
|
||||
|
||||
if ((fValueBuffer = dynamic_cast<FloatBuffer*>(group.getBuffer(VALUE_BUFFER_NAME,nbSamples))) == NULL)
|
||||
return false;
|
||||
|
||||
vertexIterator = vertexBuffer = fVertexBuffer->getData();
|
||||
colorIterator = colorBuffer = fColorBuffer->getData();
|
||||
valueIterator = valueBuffer = fValueBuffer->getData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLLineTrailRenderer::createBuffers(const Group& group)
|
||||
{
|
||||
FloatBuffer* fVertexBuffer = dynamic_cast<FloatBuffer*>(group.createBuffer(VERTEX_BUFFER_NAME,FloatBufferCreator((nbSamples + 2) * 3),nbSamples,true));
|
||||
FloatBuffer* fColorBuffer = dynamic_cast<FloatBuffer*>(group.createBuffer(COLOR_BUFFER_NAME,FloatBufferCreator((nbSamples + 2) << 2),nbSamples,true));
|
||||
FloatBuffer* fValueBuffer = dynamic_cast<FloatBuffer*>(group.createBuffer(VALUE_BUFFER_NAME,FloatBufferCreator(nbSamples),nbSamples,true));
|
||||
|
||||
vertexIterator = vertexBuffer = fVertexBuffer->getData();
|
||||
colorIterator = colorBuffer = fColorBuffer->getData();
|
||||
valueIterator = valueBuffer = fValueBuffer->getData();
|
||||
|
||||
// Fills the buffers with correct values
|
||||
for (size_t i = 0; i < group.getNbParticles(); ++i)
|
||||
{
|
||||
const Particle& particle = group.getParticle(i);
|
||||
init(particle,particle.getAge());
|
||||
}
|
||||
|
||||
// Resets the iterators at the beginning after the init
|
||||
vertexIterator = vertexBuffer;
|
||||
colorIterator = colorBuffer;
|
||||
valueIterator = valueBuffer;
|
||||
}
|
||||
|
||||
void GLLineTrailRenderer::destroyBuffers(const Group& group)
|
||||
{
|
||||
group.destroyBuffer(VERTEX_BUFFER_NAME);
|
||||
group.destroyBuffer(COLOR_BUFFER_NAME);
|
||||
group.destroyBuffer(VALUE_BUFFER_NAME);
|
||||
}
|
||||
|
||||
void GLLineTrailRenderer::init(const Group& group)
|
||||
{
|
||||
if (!prepareBuffers(group))
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < group.getNbParticles(); ++i)
|
||||
{
|
||||
const Particle& particle = group.getParticle(i);
|
||||
init(particle,particle.getAge());
|
||||
}
|
||||
}
|
||||
|
||||
void GLLineTrailRenderer::render(const Group& group)
|
||||
{
|
||||
if (!prepareBuffers(group))
|
||||
return;
|
||||
|
||||
initBlending();
|
||||
initRenderingHints();
|
||||
|
||||
// Inits lines' parameters
|
||||
glLineWidth(width);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
for (size_t i = 0; i < group.getNbParticles(); ++i)
|
||||
{
|
||||
const Particle& particle = group.getParticle(i);
|
||||
float age = particle.getAge();
|
||||
float oldAge = *valueIterator;
|
||||
|
||||
if ((age == 0.0f)||(age < *valueIterator)) // If the particle is new, buffers for it are reinitialized
|
||||
init(particle,0.0f);
|
||||
else
|
||||
{
|
||||
if (age - *(valueIterator + 1) >= duration / (nbSamples - 1)) // shifts the data by one
|
||||
{
|
||||
memmove(vertexIterator + 6,vertexIterator + 3,(nbSamples - 1) * 3 * sizeof(float));
|
||||
memmove(colorIterator + 8,colorIterator + 4,((nbSamples - 1) << 2) * sizeof(float));
|
||||
memmove(valueIterator + 1,valueIterator,(nbSamples - 1) * sizeof(float));
|
||||
|
||||
// post degenerated vertex copy
|
||||
memcpy(vertexIterator + (nbSamples + 1) * 3,vertexIterator + nbSamples * 3,3 * sizeof(float));
|
||||
}
|
||||
|
||||
// Updates the current sample
|
||||
const Vector3D& pos = particle.position();
|
||||
*(vertexIterator++) = pos.x;
|
||||
*(vertexIterator++) = pos.y;
|
||||
*(vertexIterator++) = pos.z;
|
||||
|
||||
memcpy(vertexIterator,vertexIterator - 3,3 * sizeof(float));
|
||||
vertexIterator += (nbSamples + 1) * 3;
|
||||
|
||||
colorIterator += 4; // skips post degenerated vertex color
|
||||
*(colorIterator++) = particle.getR();
|
||||
*(colorIterator++) = particle.getG();
|
||||
*(colorIterator++) = particle.getB();
|
||||
*(colorIterator++) = particle.getParamCurrentValue(PARAM_ALPHA);
|
||||
colorIterator += 3;
|
||||
|
||||
*(valueIterator++) = age;
|
||||
//valueIterator += nbSamples;
|
||||
|
||||
// Updates alpha
|
||||
for (size_t i = 0; i < nbSamples - 1; ++i)
|
||||
{
|
||||
float ratio = (age - oldAge) / (duration - age + *valueIterator);
|
||||
if (ratio > 0.0f)
|
||||
*colorIterator *= ratio < 1.0f ? 1.0f - ratio : 0.0f;
|
||||
colorIterator += 4;
|
||||
++valueIterator;
|
||||
}
|
||||
++colorIterator;
|
||||
}
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glColorPointer(4,GL_FLOAT,0,colorBuffer);
|
||||
glVertexPointer(3,GL_FLOAT,0,vertexBuffer);
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP,0,group.getNbParticles() * (nbSamples + 2));
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
}}
|
104
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLPointRenderer.cpp
Normal file
104
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLPointRenderer.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLPointRenderer.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
#include "Core/SPK_Group.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
namespace GL
|
||||
{
|
||||
GLPointRenderer::GLPointRenderer(float size) :
|
||||
GLRenderer(),
|
||||
PointRendererInterface(POINT_SQUARE,size),
|
||||
GLExtHandler(),
|
||||
textureIndex(0),
|
||||
worldSize(false)
|
||||
{}
|
||||
|
||||
bool GLPointRenderer::setType(PointType type)
|
||||
{
|
||||
if ((type == POINT_SPRITE)&&(!loadGLExtPointSprite()))
|
||||
return false;
|
||||
|
||||
this->type = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLPointRenderer::enableWorldSize(bool worldSizeEnabled)
|
||||
{
|
||||
worldSize = ((worldSizeEnabled)&&(loadGLExtPointParameter()));
|
||||
return worldSize;
|
||||
}
|
||||
|
||||
void GLPointRenderer::render(const Group& group)
|
||||
{
|
||||
initBlending();
|
||||
initRenderingHints();
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case POINT_SQUARE :
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_POINT_SMOOTH);
|
||||
if (getPointSpriteGLExt() == SUPPORTED)
|
||||
disablePointSpriteGLExt();
|
||||
break;
|
||||
|
||||
case POINT_SPRITE :
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D,textureIndex);
|
||||
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,getTextureBlending());
|
||||
enablePointSpriteGLExt();
|
||||
break;
|
||||
|
||||
case POINT_CIRCLE :
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_POINT_SMOOTH);
|
||||
if (getPointSpriteGLExt() == SUPPORTED)
|
||||
disablePointSpriteGLExt();
|
||||
break;
|
||||
}
|
||||
|
||||
if (worldSize)
|
||||
enablePointParameterGLExt(size,true);
|
||||
else
|
||||
{
|
||||
glPointSize(size);
|
||||
|
||||
if (getPointParameterGLExt() == SUPPORTED)
|
||||
disablePointParameterGLExt();
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glColorPointer(group.getModel()->isEnabled(PARAM_ALPHA) ? 4 : 3,GL_FLOAT,group.getParamStride(),group.getParamAddress(PARAM_RED));
|
||||
glVertexPointer(3,GL_FLOAT,group.getPositionStride(),group.getPositionAddress());
|
||||
|
||||
glDrawArrays(GL_POINTS,0,group.getNbParticles());
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
}}
|
279
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLQuadRenderer.cpp
Normal file
279
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLQuadRenderer.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLQuadRenderer.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
#include "Core/SPK_Group.h"
|
||||
#include "Core/SPK_ArrayBuffer.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
namespace GL
|
||||
{
|
||||
const std::string GLQuadRenderer::GPU_BUFFER_NAME("SPK_GLQuadRenderer_GPU");
|
||||
const std::string GLQuadRenderer::TEXTURE_BUFFER_NAME("SPK_GLQuadRenderer_Texture");
|
||||
|
||||
float* GLQuadRenderer::gpuBuffer = NULL;
|
||||
float* GLQuadRenderer::gpuIterator = NULL;
|
||||
float* GLQuadRenderer::textureBuffer = NULL;
|
||||
float* GLQuadRenderer::textureIterator = NULL;
|
||||
|
||||
void (GLQuadRenderer::*GLQuadRenderer::renderParticle)(const Particle&) const = NULL;
|
||||
|
||||
GLQuadRenderer::GLQuadRenderer(float scaleX,float scaleY) :
|
||||
GLRenderer(),
|
||||
QuadRendererInterface(scaleX,scaleY),
|
||||
Oriented3DRendererInterface(),
|
||||
GLExtHandler(),
|
||||
textureIndex(0)
|
||||
{}
|
||||
|
||||
bool GLQuadRenderer::checkBuffers(const Group& group)
|
||||
{
|
||||
FloatBuffer* fGpuBuffer;
|
||||
|
||||
if ((fGpuBuffer = dynamic_cast<FloatBuffer*>(group.getBuffer(GPU_BUFFER_NAME))) == NULL)
|
||||
return false;
|
||||
|
||||
if (texturingMode != TEXTURE_NONE)
|
||||
{
|
||||
FloatBuffer* fTextureBuffer;
|
||||
|
||||
if ((fTextureBuffer = dynamic_cast<FloatBuffer*>(group.getBuffer(TEXTURE_BUFFER_NAME,texturingMode))) == NULL)
|
||||
textureBuffer = createTextureBuffer(group);
|
||||
|
||||
textureIterator = textureBuffer = fTextureBuffer->getData();
|
||||
}
|
||||
|
||||
gpuIterator = gpuBuffer = fGpuBuffer->getData();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLQuadRenderer::createBuffers(const Group& group)
|
||||
{
|
||||
FloatBuffer* fBuffer = dynamic_cast<FloatBuffer*>(group.createBuffer(GPU_BUFFER_NAME,FloatBufferCreator(28),0,false));
|
||||
gpuIterator = gpuBuffer = fBuffer->getData();
|
||||
if (texturingMode != TEXTURE_NONE)
|
||||
textureIterator = textureBuffer = createTextureBuffer(group);
|
||||
}
|
||||
|
||||
void GLQuadRenderer::destroyBuffers(const Group& group)
|
||||
{
|
||||
group.destroyBuffer(GPU_BUFFER_NAME);
|
||||
group.destroyBuffer(TEXTURE_BUFFER_NAME);
|
||||
}
|
||||
|
||||
float* GLQuadRenderer::createTextureBuffer(const Group& group) const
|
||||
{
|
||||
FloatBuffer* fbuffer = NULL;
|
||||
|
||||
switch(texturingMode)
|
||||
{
|
||||
case TEXTURE_2D :
|
||||
fbuffer = dynamic_cast<FloatBuffer*>(group.createBuffer(TEXTURE_BUFFER_NAME,FloatBufferCreator(8),TEXTURE_2D,false));
|
||||
if (!group.getModel()->isEnabled(PARAM_TEXTURE_INDEX))
|
||||
{
|
||||
float t[8] = {1.0f,0.0f,0.0f,0.0f,0.0f,1.0f,1.0f,1.0f};
|
||||
for (size_t i = 0; i < group.getParticles().getNbReserved() << 3; ++i)
|
||||
fbuffer->getData()[i] = t[i & 7];
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXTURE_3D :
|
||||
fbuffer = dynamic_cast<FloatBuffer*>(group.createBuffer(TEXTURE_BUFFER_NAME,FloatBufferCreator(12),TEXTURE_3D,false));
|
||||
float t[12] = {1.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f,1.0f,1.0f,0.0f};
|
||||
for (size_t i = 0; i < group.getParticles().getNbReserved() * 12; ++i)
|
||||
fbuffer->getData()[i] = t[i % 12];
|
||||
break;
|
||||
}
|
||||
|
||||
return fbuffer->getData();
|
||||
}
|
||||
|
||||
bool GLQuadRenderer::setTexturingMode(TexturingMode mode)
|
||||
{
|
||||
if ((mode == TEXTURE_3D)&&(!loadGLExtTexture3D()))
|
||||
return false;
|
||||
|
||||
texturingMode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLQuadRenderer::render(const Group& group)
|
||||
{
|
||||
if (!prepareBuffers(group))
|
||||
return;
|
||||
|
||||
float oldModelView[16];
|
||||
for (int i = 0; i < 16; ++i)
|
||||
oldModelView[i] = modelView[i];
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX,modelView);
|
||||
for (int i = 0; i < 16; ++i)
|
||||
if (oldModelView[i] != modelView[i])
|
||||
{
|
||||
invertModelView();
|
||||
break;
|
||||
}
|
||||
|
||||
initBlending();
|
||||
initRenderingHints();
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
switch(texturingMode)
|
||||
{
|
||||
case TEXTURE_2D :
|
||||
if (getTexture3DGLExt() == SUPPORTED)
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D,textureIndex);
|
||||
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,getTextureBlending());
|
||||
|
||||
if (!group.getModel()->isEnabled(PARAM_TEXTURE_INDEX))
|
||||
{
|
||||
if (!group.getModel()->isEnabled(PARAM_ANGLE))
|
||||
renderParticle = &GLQuadRenderer::render2D;
|
||||
else
|
||||
renderParticle = &GLQuadRenderer::render2DRot;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!group.getModel()->isEnabled(PARAM_ANGLE))
|
||||
renderParticle = &GLQuadRenderer::render2DAtlas;
|
||||
else
|
||||
renderParticle = &GLQuadRenderer::render2DAtlasRot;
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXTURE_3D :
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_TEXTURE_3D);
|
||||
glBindTexture(GL_TEXTURE_3D,textureIndex);
|
||||
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,getTextureBlending());
|
||||
|
||||
if (!group.getModel()->isEnabled(PARAM_ANGLE))
|
||||
renderParticle = &GLQuadRenderer::render3D;
|
||||
else
|
||||
renderParticle = &GLQuadRenderer::render3DRot;
|
||||
break;
|
||||
|
||||
case TEXTURE_NONE :
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if (getTexture3DGLExt() == SUPPORTED)
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
if (!group.getModel()->isEnabled(PARAM_ANGLE))
|
||||
renderParticle = &GLQuadRenderer::render2D;
|
||||
else
|
||||
renderParticle = &GLQuadRenderer::render2DRot;
|
||||
break;
|
||||
}
|
||||
|
||||
bool globalOrientation = precomputeOrientation3D(
|
||||
group,
|
||||
Vector3D(-invModelView[8],-invModelView[9],-invModelView[10]),
|
||||
Vector3D(invModelView[4],invModelView[5],invModelView[6]),
|
||||
Vector3D(invModelView[12],invModelView[13],invModelView[14]));
|
||||
|
||||
if (globalOrientation)
|
||||
{
|
||||
computeGlobalOrientation3D();
|
||||
|
||||
for (size_t i = 0; i < group.getNbParticles(); ++i)
|
||||
(this->*renderParticle)(group.getParticle(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < group.getNbParticles(); ++i)
|
||||
{
|
||||
const Particle& particle = group.getParticle(i);
|
||||
computeSingleOrientation3D(particle);
|
||||
(this->*renderParticle)(particle);
|
||||
}
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
if (texturingMode == TEXTURE_2D)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2,GL_FLOAT,0,textureBuffer);
|
||||
}
|
||||
else if (texturingMode == TEXTURE_3D)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(3,GL_FLOAT,0,textureBuffer);
|
||||
}
|
||||
|
||||
// interleaves vertex and color data
|
||||
glVertexPointer(3,GL_FLOAT,7 * sizeof(float),gpuBuffer);
|
||||
glColorPointer(4,GL_FLOAT,7 * sizeof(float),gpuBuffer + 3);
|
||||
|
||||
glDrawArrays(GL_QUADS,0,group.getNbParticles() << 2);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
if (texturingMode != TEXTURE_NONE)
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
void GLQuadRenderer::render2D(const Particle& particle) const
|
||||
{
|
||||
scaleQuadVectors(particle,scaleX,scaleY);
|
||||
GLCallColorAndVertex(particle);
|
||||
}
|
||||
|
||||
void GLQuadRenderer::render2DRot(const Particle& particle) const
|
||||
{
|
||||
rotateAndScaleQuadVectors(particle,scaleX,scaleY);
|
||||
GLCallColorAndVertex(particle);
|
||||
}
|
||||
|
||||
void GLQuadRenderer::render3D(const Particle& particle) const
|
||||
{
|
||||
scaleQuadVectors(particle,scaleX,scaleY);
|
||||
GLCallColorAndVertex(particle);
|
||||
GLCallTexture3D(particle);
|
||||
}
|
||||
|
||||
void GLQuadRenderer::render3DRot(const Particle& particle) const
|
||||
{
|
||||
rotateAndScaleQuadVectors(particle,scaleX,scaleY);
|
||||
GLCallColorAndVertex(particle);
|
||||
GLCallTexture3D(particle);
|
||||
}
|
||||
|
||||
void GLQuadRenderer::render2DAtlas(const Particle& particle) const
|
||||
{
|
||||
scaleQuadVectors(particle,scaleX,scaleY);
|
||||
GLCallColorAndVertex(particle);
|
||||
GLCallTexture2DAtlas(particle);
|
||||
}
|
||||
|
||||
void GLQuadRenderer::render2DAtlasRot(const Particle& particle) const
|
||||
{
|
||||
rotateAndScaleQuadVectors(particle,scaleX,scaleY);
|
||||
GLCallColorAndVertex(particle);
|
||||
GLCallTexture2DAtlas(particle);
|
||||
}
|
||||
}}
|
80
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLRenderer.cpp
Normal file
80
libs/spark/src/RenderingAPIs/OpenGL/SPK_GLRenderer.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLRenderer.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
namespace GL
|
||||
{
|
||||
GLRenderer::GLRenderer() :
|
||||
Renderer(),
|
||||
blendingEnabled(false),
|
||||
srcBlending(GL_SRC_ALPHA),
|
||||
destBlending(GL_ONE_MINUS_SRC_ALPHA),
|
||||
textureBlending(GL_MODULATE)
|
||||
{}
|
||||
|
||||
GLRenderer::~GLRenderer() {}
|
||||
|
||||
void GLRenderer::setBlending(BlendingMode blendMode)
|
||||
{
|
||||
switch(blendMode)
|
||||
{
|
||||
case BLENDING_NONE :
|
||||
srcBlending = GL_ONE;
|
||||
destBlending = GL_ZERO;
|
||||
blendingEnabled = false;
|
||||
break;
|
||||
|
||||
case BLENDING_ADD :
|
||||
srcBlending = GL_SRC_ALPHA;
|
||||
destBlending = GL_ONE;
|
||||
blendingEnabled = true;
|
||||
break;
|
||||
|
||||
case BLENDING_ALPHA :
|
||||
srcBlending = GL_SRC_ALPHA;
|
||||
destBlending = GL_ONE_MINUS_SRC_ALPHA;
|
||||
blendingEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLRenderer::saveGLStates()
|
||||
{
|
||||
glPushAttrib(GL_POINT_BIT |
|
||||
GL_LINE_BIT |
|
||||
GL_ENABLE_BIT |
|
||||
GL_COLOR_BUFFER_BIT |
|
||||
GL_CURRENT_BIT |
|
||||
GL_TEXTURE_BIT |
|
||||
GL_DEPTH_BUFFER_BIT |
|
||||
GL_LIGHTING_BIT |
|
||||
GL_POLYGON_BIT);
|
||||
}
|
||||
|
||||
void GLRenderer::restoreGLStates()
|
||||
{
|
||||
glPopAttrib();
|
||||
}
|
||||
}}
|
78
libs/spark/src/SPK_All.cpp
Normal file
78
libs/spark/src/SPK_All.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Note : //
|
||||
// //
|
||||
// This file is used to speed up the compilation of a module, lower the size //
|
||||
// of the output library on certain compilers and allow deeper optimizations //
|
||||
// by reunifying all compilation units into one (single compilation unit //
|
||||
// method). //
|
||||
// //
|
||||
// Either only this file or all the files below should be compiled, not both or //
|
||||
// some 'multiple definition of symbols' errors will occur. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Core
|
||||
#include "Core/SPK_DEF.cpp"
|
||||
#include "Core/SPK_Vector3D.cpp"
|
||||
#include "Core/SPK_Registerable.cpp" // 1.03
|
||||
#include "Core/SPK_Transformable.cpp" // 1.03
|
||||
#include "Core/SPK_BufferHandler.cpp" // 1.04
|
||||
#include "Core/SPK_Renderer.cpp"
|
||||
#include "Core/SPK_System.cpp"
|
||||
#include "Core/SPK_Particle.cpp"
|
||||
#include "Core/SPK_Zone.cpp"
|
||||
#include "Core/SPK_Interpolator.cpp" // 1.05
|
||||
#include "Core/SPK_Model.cpp"
|
||||
#include "Core/SPK_Emitter.cpp"
|
||||
#include "Core/SPK_Modifier.cpp"
|
||||
#include "Core/SPK_Group.cpp"
|
||||
#include "Core/SPK_Factory.cpp" // 1.03
|
||||
|
||||
// Zones
|
||||
#include "Extensions/Zones/SPK_AABox.cpp"
|
||||
#include "Extensions/Zones/SPK_Point.cpp"
|
||||
#include "Extensions/Zones/SPK_Sphere.cpp"
|
||||
#include "Extensions/Zones/SPK_Plane.cpp"
|
||||
#include "Extensions/Zones/SPK_Line.cpp" // 1.01
|
||||
#include "Extensions/Zones/SPK_Ring.cpp" // 1.05
|
||||
|
||||
// Emitters
|
||||
#include "Extensions/Emitters/SPK_StraightEmitter.cpp"
|
||||
#include "Extensions/Emitters/SPK_SphericEmitter.cpp"
|
||||
#include "Extensions/Emitters/SPK_NormalEmitter.cpp" // 1.02
|
||||
#include "Extensions/Emitters/SPK_RandomEmitter.cpp" // 1.02
|
||||
|
||||
// Modifiers
|
||||
#include "Extensions/Modifiers/SPK_Obstacle.cpp"
|
||||
#include "Extensions/Modifiers/SPK_Destroyer.cpp"
|
||||
#include "Extensions/Modifiers/SPK_PointMass.cpp"
|
||||
#include "Extensions/Modifiers/SPK_ModifierGroup.cpp" // 1.02
|
||||
#include "Extensions/Modifiers/SPK_LinearForce.cpp" // 1.03
|
||||
#include "Extensions/Modifiers/SPK_Collision.cpp" // 1.04
|
||||
#include "Extensions/Modifiers/SPK_Vortex.cpp" // 1.05
|
||||
|
||||
// Renderer Interfaces
|
||||
#include "Extensions/Renderers/SPK_QuadRendererInterface.cpp" // 1.04
|
||||
#include "Extensions/Renderers/SPK_Oriented3DRendererInterface.cpp" // 1.04
|
42
libs/spark/src/SPK_GL_All.cpp
Normal file
42
libs/spark/src/SPK_GL_All.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Note : //
|
||||
// //
|
||||
// This file is used to speed up the compilation of a module, lower the size //
|
||||
// of the output library on certain compilers and allow deeper optimizations //
|
||||
// by reunifying all compilation units into one (single compilation unit //
|
||||
// method). //
|
||||
// //
|
||||
// Either only this file or all the files below should be compiled, not both or //
|
||||
// some 'multiple definition of symbols' errors will occur. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// GL
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLExtHandler.cpp" // 1.01
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLRenderer.cpp"
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLLineRenderer.cpp"
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLPointRenderer.cpp"
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLQuadRenderer.cpp"
|
||||
#include "RenderingAPIs/OpenGL/SPK_GLLineTrailRenderer.cpp" // 1.03
|
Reference in New Issue
Block a user