From 5678539e05d2451f5185f87a4506832058d9ea01 Mon Sep 17 00:00:00 2001 From: Andrew Tribick Date: Wed, 29 Dec 2021 13:36:37 +0100 Subject: [PATCH] Remove unused particle system code --- docs/Doxyfile | 4 - src/celengine/CMakeLists.txt | 4 - src/celengine/meshmanager.cpp | 18 - src/celengine/particlesystem.cpp | 509 --------------------------- src/celengine/particlesystem.h | 245 ------------- src/celengine/particlesystemfile.cpp | 359 ------------------- src/celengine/particlesystemfile.h | 53 --- src/celutil/filetype.cpp | 3 - src/celutil/filetype.h | 2 +- 9 files changed, 1 insertion(+), 1196 deletions(-) delete mode 100644 src/celengine/particlesystem.cpp delete mode 100644 src/celengine/particlesystem.h delete mode 100644 src/celengine/particlesystemfile.cpp delete mode 100644 src/celengine/particlesystemfile.h diff --git a/docs/Doxyfile b/docs/Doxyfile index e0839b0b5..b4a6ac140 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -840,10 +840,6 @@ EXCLUDE = src/packdb.cpp \ src/celmath/plane.h \ src/celmath/quaternion.h \ src/celmath/vecmath.h \ - src/celengine/particlesystem.cpp \ - src/celengine/particlesystem.h \ - src/celengine/particlesystemfile.cpp \ - src/celengine/particlesystemfile.h \ src/celengine/vertexbuf.h \ src/celtxf/*.* diff --git a/src/celengine/CMakeLists.txt b/src/celengine/CMakeLists.txt index d1c268d03..e1c861e89 100644 --- a/src/celengine/CMakeLists.txt +++ b/src/celengine/CMakeLists.txt @@ -91,10 +91,6 @@ set(CELENGINE_SOURCES parseobject.h parser.cpp parser.h -# particlesystem.cpp -# particlesystemfile.cpp -# particlesystemfile.h -# particlesystem.h planetgrid.cpp planetgrid.h pointstarrenderer.cpp diff --git a/src/celengine/meshmanager.cpp b/src/celengine/meshmanager.cpp index 134c0d6f5..e3db57135 100644 --- a/src/celengine/meshmanager.cpp +++ b/src/celengine/meshmanager.cpp @@ -8,9 +8,6 @@ // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. -// Experimental particle system support -#define PARTICLE_SYSTEM 0 - #include #include #include @@ -40,11 +37,6 @@ #include "spheremesh.h" #include "texmanager.h" -#if PARTICLE_SYSTEM -#include "particlesystem.h" -#include "particlesystemfile.h" -#endif - using celestia::util::GetLogger; namespace @@ -509,16 +501,6 @@ GeometryInfo::load(const fs::path& resolvedFilename) model->transform(center, scale); } } -#if PARTICLE_SYSTEM - else if (fileType == Content_CelestiaParticleSystem) - { - ifstream in(filename); - if (in.good()) - { - return LoadParticleSystem(in, path); - } - } -#endif // Condition the model for optimal rendering if (model != nullptr) diff --git a/src/celengine/particlesystem.cpp b/src/celengine/particlesystem.cpp deleted file mode 100644 index b52b151e9..000000000 --- a/src/celengine/particlesystem.cpp +++ /dev/null @@ -1,509 +0,0 @@ -// particlesystem.cpp -// -// Stateless particle system renderer. -// -// Copyright (C) 2008, Chris Laurel -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -#include -#include -#include -#include -#include -#include "modelgeometry.h" -#include "particlesystem.h" -#include "glsupport.h" -#include "vecgl.h" -#include "rendcontext.h" -#include "texmanager.h" - -using namespace cmod; -using namespace Eigen; -using namespace std; - -/* !!! IMPORTANT !!! - * The particle system code is still under development; the complete - * set of particle system features has not been decided and the cpart - * format is not even close time final. There are most certainly bugs. - * DO NOT enable this code and invest a lot of time in creating your - * own particle system files until development is further along. - */ - -/* STATELESS PARTICLE SYSTEMS - * - * THEORY - * In a typical particle system, initial particle states are generated - * and stored in array. At each time step, particles have their states - * updated and are then drawn. A typical sequence is: - * - Compute the forces acting on the particles - * - Update particle positions and velocities - * - Age the particles (updating state such as color and size) - * - Render the particles - * - * This process is well-suited to a simulation where the time steps are - * relatively uniform. But, we cannot rely on a uniform time step in Celestia. - * The user may skip ahead instantly to times in the distance past or future, - * change the time rate to over a billion times normal, or reverse time. - * Numerical integration of particle positions is completely impractical. - * - * Instead, Celestia uses 'stateless' particle systems. From the particle - * system description, the particle positions and appearances can be generated - * for any time. Initial states are generated from a pseudorandom sequence - * and state at the current time is computed analytically from those initial - * values. The fact that motions must be calculated analytically means that - * only very simply force models may be used; still, a large variety of - * effects are still practical. - * - * A particle system is just a list of particle emitters. Each emitter has - * a fixed emission rate (particles per second), start time, and end time. - * There are few properties that apply to all particles produced by an emitter: - * texture, lifetime, start/end color, and start/end size - * Color and size are linearly interpolated between start and end values over - * the lifetime of a particle. - * An emitter has two different 'generators': one produces initial particle - * velocities, the other initial positions. - * - * Emitter generators are fed with values from a linear congruential - * generator. Other pseudorandom number generators can produce sequences with - * better distributions and can have better performance at generating values. - * However, seeding these other generators is very slow, and seeding must - * be every time a particle is to be drawn. The well-known defects in - * pseudorandom sequences produced by an LCG are not visible in a particle - * system (and lack of apparent visual artifacts is the *only* requirement here.) - */ - -// Same values as rand48() -static const uint64_t A = ((uint64_t) 0x5deece66ul << 4) | 0xd; -static const uint64_t C = 0xb; -static const uint64_t M = ((uint64_t) 1 << 48) - 1; - -/*! Linear congruential random number generator that emulates - * rand48() - */ -class LCGRandomGenerator -{ -public: - LCGRandomGenerator() : previous(0) = default; - - LCGRandomGenerator(uint64_t seed) : - previous(seed) - { - } - - uint64_t randUint64() - { - previous = (A * previous + C) & M; - return previous; - } - - /*! Return a random integer between -2^31 and 2^31 - 1 - */ - int32_t randInt32() - { - return (int32_t) (randUint64() >> 16); - } - - /*! Return a random integer between 0 and 2^32 - 1 - */ - uint32_t randUint32() - { - return (uint32_t) (randUint64() >> 16); - } - - /*! Generate a random floating point value in [ 0, 1 ) - * This function directly manipulates the bits of a floating - * point number, and will not work properly on a system that - * doesn't use IEEE754 floats. - */ - float randFloat() - { - uint32_t randBits = randInt32(); - randBits = (randBits & 0x007fffff) | 0x3f800000; - return *reinterpret_cast(&randBits) - 1.0f; - } - - /*! Generate a random floating point value in [ -1, 1 ) - * This function directly manipulates the bits of a floating - * point number, and will not work properly on a system that - * doesn't use IEEE754 floats. - */ - float randSfloat() - { - uint32_t randBits = (uint32_t) (randUint64() >> 16); - randBits = (randBits & 0x007fffff) | 0x40000000; - return *reinterpret_cast(&randBits) - 3.0f; - } - -private: - uint64_t previous; -}; - - -/**** Generator implementations ****/ - -Vector3f -ConstantGenerator::generate(LCGRandomGenerator& /* gen */) const -{ - return m_value; -} - - -Vector3f -BoxGenerator::generate(LCGRandomGenerator& gen) const -{ - return Vector3f(gen.randSfloat() * m_semiAxes.x(), - gen.randSfloat() * m_semiAxes.y(), - gen.randSfloat() * m_semiAxes.z()) + m_center; -} - - -Vector3f -LineGenerator::generate(LCGRandomGenerator& gen) const -{ - return m_origin + m_direction * gen.randFloat(); -} - - -Vector3f -EllipsoidSurfaceGenerator::generate(LCGRandomGenerator& gen) const -{ - float theta = (float) PI * gen.randSfloat(); - float cosPhi = gen.randSfloat(); - float sinPhi = std::sqrt(1.0f - cosPhi * cosPhi); - if (cosPhi < 0.0f) - sinPhi = -sinPhi; - - float s = std::sin(theta); - float c = std::cos(theta); - return Vector3f(sinPhi * c * m_semiAxes.x(), sinPhi * s * m_semiAxes.y(), cosPhi * m_semiAxes.z()) + m_center; -} - - -Vector3f -ConeGenerator::generate(LCGRandomGenerator& gen) const -{ - float theta = (float) PI * gen.randSfloat(); - float cosPhi = 1.0f - m_cosMinAngle - gen.randFloat() * m_cosAngleVariance; - float sinPhi = std::sqrt(1.0f - cosPhi * cosPhi); - if (cosPhi < 0.0f) - sinPhi = -sinPhi; - - float s = std::sin(theta); - float c = std::cos(theta); - return Vector3f(sinPhi * c, sinPhi * s, cosPhi) * (m_minLength + gen.randFloat() * m_lengthVariance); -} - - - -Vector3f -GaussianDiscGenerator::generate(LCGRandomGenerator& gen) const -{ - float r1 = 0.0f; - float r2 = 0.0f; - float s = 0.0f; - - do - { - r1 = gen.randSfloat(); - r2 = gen.randSfloat(); - s = r1 * r1 + r2 * r2; - } while (s > 1.0f); - - // Choose angle uniformly distributed in [ 0, 2*PI ), radius - // with a Gaussian distribution. Use the polar form of the - // Box-Muller transform to produce a normally distributed - // random number. - float r = r1 * std::sqrt(-2.0f * std::log(s) / s) * m_sigma; - float theta = r2 * 2.0f * (float) PI; - return Vector3f(r * std::cos(theta), r * std::sin(theta), 0.0f); -} - - - -ParticleEmitter::ParticleEmitter() : - m_startTime(-numeric_limits::infinity()), - m_endTime(-numeric_limits::infinity()), - m_texture(InvalidResource), - m_rate(1.0f), - m_lifetime(1.0f), - m_startColor(1.0f, 1.0f, 1.0f, 0.0f), - m_startSize(1.0f), - m_endColor(1.0f, 1.0f, 1.0f, 0.0f), - m_endSize(1.0f), - m_positionGenerator(nullptr), - m_velocityGenerator(nullptr), - m_acceleration(Vector3f::Zero()), - m_nonZeroAcceleration(false), - m_minRotationRate(0.0f), - m_rotationRateVariance(0.0f), - m_rotationEnabled(false), - m_blendMode(cmod::Material::PremultipliedAlphaBlend) -{ -} - - -ParticleEmitter::~ParticleEmitter() -{ - delete m_positionGenerator; - delete m_velocityGenerator; -} - - -void -ParticleEmitter::setLifespan(double startTime, double endTime) -{ - m_startTime = startTime; - m_endTime = endTime; -} - - -void -ParticleEmitter::setRotationRateRange(float minRate, float maxRate) -{ - m_rotationEnabled = minRate != 0.0f || maxRate != 0.0f; - m_minRotationRate = minRate; - m_rotationRateVariance = maxRate - minRate; -} - - -void -ParticleEmitter::setAcceleration(const Vector3f& acceleration) -{ - m_acceleration = acceleration; - m_nonZeroAcceleration = m_acceleration != Vector3f::Zero(); -} - - -void -ParticleEmitter::setBlendMode(cmod::Material::BlendMode blendMode) -{ - m_blendMode = blendMode; -} - - -static const uint64_t scrambleMask = (uint64_t(0xcccccccc) << 32) | 0xcccccccc; - -void -ParticleEmitter::render(double tsec, - RenderContext& rc, - ParticleVertex* particleBuffer, - unsigned int particleBufferCapacity) const -{ - double t = tsec; - bool startBounded = m_startTime > -numeric_limits::infinity(); - bool endBounded = m_endTime < numeric_limits::infinity(); - - // Return immediately if we're far enough past the end time that no - // particles remain. - if (endBounded) - { - if (t > m_endTime + m_lifetime) - return; - } - - // If a start time is specified, set t to be relative to the start time. - // Return immediately if we haven't reached the start time yet. - if (startBounded) - { - t -= m_startTime; - if (t < 0.0) - return; - } - - Matrix3f modelViewMatrix = rc.getCameraOrientation().conjugate().toRotationMatrix(); - - rc.setMaterial(&m_material); - - Vector3f v0 = modelViewMatrix * Vector3f(-1.0f, -1.0f, 0.0f); - Vector3f v1 = modelViewMatrix * Vector3f( 1.0f, -1.0f, 0.0f); - Vector3f v2 = modelViewMatrix * Vector3f( 1.0f, 1.0f, 0.0f); - Vector3f v3 = modelViewMatrix * Vector3f(-1.0f, 1.0f, 0.0f); - - Texture* texture = nullptr; - if (m_texture != InvalidResource) - { - texture = GetTextureManager()->find(m_texture); - } - - if (texture != nullptr) - texture->bind(); - - // Use premultiplied alpha - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - glDepthMask(GL_FALSE); - - double emissionInterval = 1.0 / m_rate; - double dserial = std::fmod(t * m_rate, (double) (1 << 31)); - auto serial = (int) (dserial); - double age = (dserial - serial) * emissionInterval; - auto invLifetime = (float) (1.0 / m_lifetime); - - double maxAge = m_lifetime; - if (startBounded) - { - maxAge = std::min((double) m_lifetime, t); - } - - if (endBounded && tsec > m_endTime) - { - auto skipParticles = (int) ((tsec - m_endTime) * m_rate); - serial -= skipParticles; - age += skipParticles * emissionInterval; - } - - Vec4f startColor(m_startColor.red(), m_startColor.green(), m_startColor.blue(), m_startColor.alpha()); - Vec4f endColor(m_endColor.red(), m_endColor.green(), m_endColor.blue(), m_endColor.alpha()); - - unsigned int particleCount = 0; - - while (age < maxAge) - { - // When the particle buffer is full, render the particles and flush it - if (particleCount == particleBufferCapacity) - { - glDrawArrays(GL_TRIANGLE_FAN, 0, particleCount * 4); - particleCount = 0; - } - - float alpha = (float) age * invLifetime; - float beta = 1.0f - alpha; - float size = alpha * m_endSize + beta * m_startSize; - - // Scramble the random number generator seed so that we don't end up with - // artifacts from using regularly incrementing values. - // - // TODO: consider whether the generator could be seeded just once before - // the first particle is drawn. This would entail further restrictions, - // such as no 'branching' (variable number of calls to LCG::generate()) in - // particle state calculation. - LCGRandomGenerator gen(uint64_t(serial) * uint64_t(0x128ef719) ^ scrambleMask); - - // Calculate the color of the particle - // TODO: switch to using a lookup table for color and opacity - unsigned char color[4]; - color[Color::Red] = (unsigned char) ((alpha * endColor.x + beta * startColor.x) * 255.99f); - color[Color::Green] = (unsigned char) ((alpha * endColor.y + beta * startColor.y) * 255.99f); - color[Color::Blue] = (unsigned char) ((alpha * endColor.z + beta * startColor.z) * 255.99f); - color[Color::Alpha] = (unsigned char) ((alpha * endColor.w + beta * startColor.w) * 255.99f); - - Vector3f v = m_velocityGenerator->generate(gen); - Vector3f center = m_positionGenerator->generate(gen) + v * (float) age; - if (m_nonZeroAcceleration) - center += m_acceleration * (float) (age * age); - - if (!m_rotationEnabled) - { - particleBuffer[particleCount * 4 + 0].set(center + v0 * size, Vector2f(0.0f, 1.0f), color); - particleBuffer[particleCount * 4 + 1].set(center + v1 * size, Vector2f(1.0f, 1.0f), color); - particleBuffer[particleCount * 4 + 2].set(center + v2 * size, Vector2f(1.0f, 0.0f), color); - particleBuffer[particleCount * 4 + 3].set(center + v3 * size, Vector2f(0.0f, 0.0f), color); - } - else - { - float rotationRate = m_minRotationRate + m_rotationRateVariance * gen.randFloat(); - float rotation = rotationRate * (float) age; - float c = std::cos(rotation); - float s = std::sin(rotation); - - particleBuffer[particleCount * 4 + 0].set(center + (modelViewMatrix * Vector3f(-c + s, -s - c, 0.0f)) * size, Vector2f(0.0f, 1.0f), color); - particleBuffer[particleCount * 4 + 1].set(center + (modelViewMatrix * Vector3f( c + s, s - c, 0.0f)) * size, Vector2f(1.0f, 1.0f), color); - particleBuffer[particleCount * 4 + 2].set(center + (modelViewMatrix * Vector3f( c - s, s + c, 0.0f)) * size, Vector2f(1.0f, 0.0f), color); - particleBuffer[particleCount * 4 + 3].set(center + (modelViewMatrix * Vector3f(-c - s, -s + c, 0.0f)) * size, Vector2f(0.0f, 0.0f), color); - } - - ++particleCount; - - age += emissionInterval; - serial--; - } - - // Render any remaining particles in the buffer - if (particleCount > 0) - { - glDrawArrays(GL_TRIANGLE_FAN, 0, particleCount * 4); - } -} - - -void -ParticleEmitter::createMaterial() -{ - m_material.diffuse = cmod::Material::Color(0.0f, 0.0f, 0.0f); - m_material.emissive = cmod::Material::Color(1.0f, 1.0f, 1.0f); - m_material.blend = m_blendMode; - m_material.opacity = 0.99f; - m_material.maps[0] = new CelestiaTextureResource(m_texture); -} - - -#define STRUCT_OFFSET(s, memberName) ((uint32_t) (reinterpret_cast(&(s).memberName) - reinterpret_cast(&(s)))) - -ParticleSystem::ParticleSystem() : - m_vertexDesc(nullptr), - m_vertexData(nullptr), - m_particleCapacity(0), - m_particleCount(0) -{ - m_particleCapacity = 1000; - m_vertexData = new ParticleVertex[m_particleCapacity * 4]; - - // Create the vertex description; currently, it is the same for all - // particle systems. - ParticleVertex temp; - Mesh::VertexAttribute attributes[3]; - attributes[0] = cmod::Mesh::VertexAttribute(Mesh::Position, Mesh::Float3, STRUCT_OFFSET(temp, position)); - attributes[1] = Mesh::VertexAttribute(Mesh::Texture0, Mesh::Float2, STRUCT_OFFSET(temp, texCoord)); - attributes[2] = Mesh::VertexAttribute(Mesh::Color0, Mesh::UByte4, STRUCT_OFFSET(temp, color)); - m_vertexDesc = new Mesh::VertexDescription(sizeof(ParticleVertex), 3, attributes); -} - - -ParticleSystem::~ParticleSystem() -{ - for (const auto emitter : m_emitterList) - delete emitter; - - delete[] m_vertexData; - delete m_vertexDesc; -} - - -void -ParticleSystem::render(RenderContext& rc, double tsec) -{ - rc.setVertexArrays(*m_vertexDesc, m_vertexData); - - for (const auto emitter : m_emitterList) - { - emitter->render(tsec, rc, m_vertexData, m_particleCapacity); - } -} - - -bool -ParticleSystem::pick(const Eigen::ParametrizedLine& /* r */, double& /* distance */) const -{ - // Pick selection for particle systems not supported (because it's - // not typically desirable.) - return false; -} - - -bool -ParticleSystem::isOpaque() const -{ - return false; -} - - -void -ParticleSystem::addEmitter(ParticleEmitter* emitter) -{ - m_emitterList.push_back(emitter); -} diff --git a/src/celengine/particlesystem.h b/src/celengine/particlesystem.h deleted file mode 100644 index deff567b3..000000000 --- a/src/celengine/particlesystem.h +++ /dev/null @@ -1,245 +0,0 @@ -// particlesystem.h -// -// Copyright (C) 2008, Chris Laurel -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -#ifndef _CELENGINE_PARTICLESYSTEM_H_ -#define _CELENGINE_PARTICLESYSTEM_H_ - -#include "celmodel/model.h" -#include "celmodel/mesh.h" -#include "celutil/color.h" -#include "rendcontext.h" -#include "geometry.h" -#include -#include -#include - -class VectorGenerator; - - - -struct ParticleVertex -{ - void set(const Eigen::Vector3f& _position, const Eigen::Vector2f& _texCoord, const unsigned char* _color) - { - position = _position; - texCoord = _texCoord; - color[Color::Red] = _color[Color::Red]; - color[Color::Green] = _color[Color::Green]; - color[Color::Blue] = _color[Color::Blue]; - color[Color::Alpha] = _color[Color::Alpha]; - } - - Eigen::Vector3f position; - Eigen::Vector2f texCoord; - unsigned char color[4]; -}; - - -class ParticleEmitter -{ -public: - ParticleEmitter(); - ~ParticleEmitter(); - - void render(double tsec, RenderContext& rc, ParticleVertex* particleBuffer, unsigned int particleBufferCapacity) const; - - void setAcceleration(const Eigen::Vector3f& acceleration); - void createMaterial(); - - void setLifespan(double startTime, double endTime); - void setRotationRateRange(float minRate, float maxRate); - void setBlendMode(cmod::Material::BlendMode blendMode); - -private: - double m_startTime; - double m_endTime; - -public: - ResourceHandle m_texture; - - float m_rate; - float m_lifetime; - - Color m_startColor; - float m_startSize; - - Color m_endColor; - float m_endSize; - - VectorGenerator* m_positionGenerator; - VectorGenerator* m_velocityGenerator; - -private: - Eigen::Vector3f m_acceleration; - bool m_nonZeroAcceleration; - - float m_minRotationRate; - float m_rotationRateVariance; - bool m_rotationEnabled; - - cmod::Material::BlendMode m_blendMode; - - cmod::Material m_material; -}; - - -class ParticleSystem : public Geometry -{ - public: - ParticleSystem(); - virtual ~ParticleSystem(); - - virtual void render(RenderContext& rc, double tsec = 0.0); - virtual bool pick(const Eigen::ParametrizedLine& r, double& distance) const; - virtual bool isOpaque() const; - - void addEmitter(ParticleEmitter* emitter); - - public: - std::list m_emitterList; - - cmod::Mesh::VertexDescription* m_vertexDesc; - ParticleVertex* m_vertexData; - unsigned int m_particleCapacity; - unsigned int m_particleCount; -}; - - -class LCGRandomGenerator; - -/*! Generator abstract base class. - * Subclasses must implement generate() method. - */ -class VectorGenerator -{ -public: - VectorGenerator() = default; - virtual ~VectorGenerator() = default; - virtual Eigen::Vector3f generate(LCGRandomGenerator& gen) const = 0; -}; - - -/*! Simplest generator; produces the exact same value on each call - * to generate(). - */ -class ConstantGenerator : public VectorGenerator -{ -public: - ConstantGenerator(const Eigen::Vector3f& value) : m_value(value) {} - - virtual Eigen::Vector3f generate(LCGRandomGenerator& gen) const; - -private: - Eigen::Vector3f m_value; -}; - - -/*! Generates values uniformly distributed within an axis-aligned box. - */ -class BoxGenerator : public VectorGenerator -{ -public: - BoxGenerator(const Eigen::Vector3f& center, const Eigen::Vector3f& axes) : - m_center(center), - m_semiAxes(axes * 0.5f) - { - } - - virtual Eigen::Vector3f generate(LCGRandomGenerator& gen) const; - -private: - Eigen::Vector3f m_center; - Eigen::Vector3f m_semiAxes; -}; - - -/*! Generates values uniformly distributed on a line between - * two points. - */ -class LineGenerator : public VectorGenerator -{ -public: - LineGenerator(const Eigen::Vector3f& p0, const Eigen::Vector3f& p1) : - m_origin(p0), - m_direction(p1 - p0) - { - } - - virtual Eigen::Vector3f generate(LCGRandomGenerator& gen) const; - -private: - Eigen::Vector3f m_origin; - Eigen::Vector3f m_direction; -}; - - -/*! Generates values uniformly distributed on the surface - * of an ellipsoid. - */ -class EllipsoidSurfaceGenerator : public VectorGenerator -{ -public: - EllipsoidSurfaceGenerator(const Eigen::Vector3f& center, const Eigen::Vector3f& semiAxes) : - m_center(center), - m_semiAxes(semiAxes) - { - } - - virtual Eigen::Vector3f generate(LCGRandomGenerator& gen) const; - -private: - Eigen::Vector3f m_center; - Eigen::Vector3f m_semiAxes; -}; - - -/*! Generates values uniformly distributed within a spherical - * section. The section is centered on the z-axis. - */ -class ConeGenerator : public VectorGenerator -{ -public: - ConeGenerator(float minAngle, float maxAngle, float minLength, const float maxLength) : - m_cosMinAngle(1.0f - std::cos(minAngle)), - m_cosAngleVariance(std::cos(minAngle) - std::cos(maxAngle)), - m_minLength(minLength), - m_lengthVariance(maxLength - minLength) - { - } - - virtual Eigen::Vector3f generate(LCGRandomGenerator& gen) const; - -private: - float m_cosMinAngle; - float m_cosAngleVariance; - float m_minLength; - float m_lengthVariance; -}; - - -/*! Generates points in a 2D gaussian distribution in - * the xy-plane and centered on the origin. - */ -class GaussianDiscGenerator : public VectorGenerator -{ -public: - GaussianDiscGenerator(float sigma) : - m_sigma(sigma) - { - } - - virtual Eigen::Vector3f generate(LCGRandomGenerator& gen) const; - -private: - float m_sigma; -}; - -//ParticleSystem* LoadParticleSystem(const std::string& filename, const std::string& resourcePath); - -#endif // _CELENGINE_PARTICLESYSTEM_H_ diff --git a/src/celengine/particlesystemfile.cpp b/src/celengine/particlesystemfile.cpp deleted file mode 100644 index 7c5934933..000000000 --- a/src/celengine/particlesystemfile.cpp +++ /dev/null @@ -1,359 +0,0 @@ -// particlesystem.cpp -// -// Particle system file loader. -// -// Copyright (C) 2008, Chris Laurel -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -#include "particlesystemfile.h" -#include "particlesystem.h" -#include "texmanager.h" -#include - -using namespace Eigen; -using namespace std; - - -/* !!! IMPORTANT !!! - * The particle system code is still under development; the complete - * set of particle system features has not been decided and the cpart - * format is not even close time final. There are most certainly bugs. - * DO NOT enable this code and invest a lot of time in creating your - * own particle system files until development is further along. - */ - - -ParticleSystemLoader::ParticleSystemLoader(istream& in) : - m_tokenizer(&in), - m_parser(&m_tokenizer) -{ -} - - -ParticleSystem* -ParticleSystemLoader::load() -{ - auto* particleSystem = new ParticleSystem(); - - while (m_tokenizer.nextToken() != Tokenizer::TokenEnd) - { - string objType; - - if (m_tokenizer.getTokenType() != Tokenizer::TokenName) - { - raiseError("Error parsing particle system"); - delete particleSystem; - return nullptr; - } - - objType = m_tokenizer.getNameValue(); - if (objType != "Emitter") - { - ostringstream stream; - stream << "Unexpected object '" << objType << "' in particle system file"; - raiseError(stream.str()); - - delete particleSystem; - return nullptr; - } - - Value* objParamsValue = m_parser.readValue(); - if (objParamsValue == nullptr || objParamsValue->getType() != Value::HashType) - { - raiseError("Error parsing particle system"); - - delete particleSystem; - return nullptr; - } - - Hash* objParams = objParamsValue->getHash(); - if (objType == "Emitter") - { - ParticleEmitter* emitter = parseEmitter(objParams); - if (emitter == nullptr) - { - delete particleSystem; - return nullptr; - } - - particleSystem->addEmitter(emitter); - } - } - - return particleSystem; -} - - -VectorGenerator* -ParticleSystemLoader::parseGenerator(Hash* params) -{ - Vector3f constantValue(Vector3f::Zero()); - if (params->getVector("Constant", constantValue)) - { - return new ConstantGenerator(constantValue); - } - - Value* generatorValue = nullptr; - generatorValue = params->getValue("Box"); - if (generatorValue != nullptr) - { - if (generatorValue->getType() != Value::HashType) - { - raiseError("Error in Box syntax"); - return nullptr; - } - - Hash* boxParams = generatorValue->getHash(); - - Vector3f center(Vector3f::Zero()); - Vector3f size(Vector3f::Zero()); - boxParams->getVector("Center", center); - boxParams->getVector("Size", size); - - return new BoxGenerator(center, size); - } - - generatorValue = params->getValue("Line"); - if (generatorValue != nullptr) - { - if (generatorValue->getType() != Value::HashType) - { - raiseError("Error in Line syntax"); - return nullptr; - } - - Hash* lineParams = generatorValue->getHash(); - - Vector3f p0(Vector3f::Zero()); - Vector3f p1(Vector3f::Zero()); - lineParams->getVector("Point1", p0); - lineParams->getVector("Point2", p1); - - return new LineGenerator(p0, p1); - } - - generatorValue = params->getValue("EllipsoidSurface"); - if (generatorValue != nullptr) - { - if (generatorValue->getType() != Value::HashType) - { - raiseError("Error in EllipsoidSurface syntax"); - return nullptr; - } - - Hash* ellipsoidSurfaceParams = generatorValue->getHash(); - - Vector3f center(Vector3f::Zero()); - Vector3f size(2.0f, 2.0f, 2.0f); - ellipsoidSurfaceParams->getVector("Center", center); - ellipsoidSurfaceParams->getVector("Size", size); - - return new EllipsoidSurfaceGenerator(center, size * 0.5f); - } - - generatorValue = params->getValue("Cone"); - if (generatorValue != nullptr) - { - if (generatorValue->getType() != Value::HashType) - { - raiseError("Error in Cone syntax"); - return nullptr; - } - - Hash* coneParams = generatorValue->getHash(); - - double minAngle = 0.0; - double maxAngle = 0.0; - double minSpeed = 0.0; - double maxSpeed = 1.0; - coneParams->getNumber("MinAngle", minAngle); - coneParams->getNumber("MaxAngle", maxAngle); - coneParams->getNumber("MinSpeed", minSpeed); - coneParams->getNumber("MaxSpeed", maxSpeed); - - return new ConeGenerator((float) degToRad(minAngle), (float) degToRad(maxAngle), (float) minSpeed, (float) maxSpeed); - } - - generatorValue = params->getValue("GaussianDisc"); - if (generatorValue != nullptr) - { - if (generatorValue->getType() != Value::HashType) - { - raiseError("Error in GaussianDisc syntax"); - return nullptr; - } - - Hash* gaussianDiscParams = generatorValue->getHash(); - - double sigma = 1.0; - gaussianDiscParams->getNumber("Sigma", sigma); - - return new GaussianDiscGenerator((float) sigma); - } - - raiseError("Missing generator for emitter"); - - return nullptr; -} - - -ParticleEmitter* -ParticleSystemLoader::parseEmitter(Hash* params) -{ - string textureFileName; - ResourceHandle textureHandle = InvalidResource; - if (params->getString("Texture", textureFileName)) - { - textureHandle = GetTextureManager()->getHandle(TextureInfo(textureFileName, getTexturePath(), TextureInfo::BorderClamp)); - } - - double rate = 1.0; - double lifetime = 1.0; - params->getNumber("Rate", rate); - params->getNumber("Lifetime", lifetime); - - double startSize = 1.0; - double endSize = 1.0; - params->getNumber("StartSize", startSize); - params->getNumber("EndSize", endSize); - - Color startColor(Color::White); - Color endColor(Color::Black); - float startOpacity = 0.0f; - float endOpacity = 0.0f; - - params->getColor("StartColor", startColor); - params->getNumber("StartOpacity", startOpacity); - params->getColor("EndColor", endColor); - params->getNumber("EndOpacity", endOpacity); - - VectorGenerator* initialPositionGenerator = nullptr; - Value* positionValue = params->getValue("InitialPosition"); - if (positionValue == nullptr) - { - initialPositionGenerator = new ConstantGenerator(Vector3f::Zero()); - } - else - { - if (positionValue->getType() != Value::HashType) - { - raiseError("Error in InitialPosition syntax"); - } - else - { - initialPositionGenerator = parseGenerator(positionValue->getHash()); - } - } - - if (initialPositionGenerator == nullptr) - { - return nullptr; - } - - VectorGenerator* initialVelocityGenerator = nullptr; - Value* velocityValue = params->getValue("InitialVelocity"); - if (velocityValue == nullptr) - { - initialVelocityGenerator = new ConstantGenerator(Vector3f::Zero()); - } - else - { - if (velocityValue->getType() != Value::HashType) - { - raiseError("Error in InitialVelocity syntax"); - } - else - { - initialVelocityGenerator = parseGenerator(velocityValue->getHash()); - } - } - - if (initialVelocityGenerator == nullptr) - { - delete initialPositionGenerator; - return nullptr; - } - - Vector3f acceleration; - params->getVector("Acceleration", acceleration); - - double startTime = -numeric_limits::infinity(); - double endTime = numeric_limits::infinity(); - params->getNumber("Beginning", startTime); - params->getNumber("Ending", endTime); - - double minRotationRate = 0.0; - double maxRotationRate = 0.0; - params->getNumber("MinRotationRate", minRotationRate); - params->getNumber("MaxRotationRate", maxRotationRate); - - auto* emitter = new ParticleEmitter(); - emitter->m_texture = textureHandle; - emitter->m_rate = (float) rate; - emitter->m_lifetime = (float) lifetime; - emitter->m_startColor = Color(startColor, startOpacity); - emitter->m_endColor = Color(endColor, endOpacity); - emitter->m_startSize = (float) startSize; - emitter->m_endSize = (float) endSize; - emitter->m_positionGenerator = initialPositionGenerator; - emitter->m_velocityGenerator = initialVelocityGenerator; - emitter->createMaterial(); - - emitter->setAcceleration(acceleration); - - emitter->setLifespan(startTime, endTime); - emitter->setRotationRateRange((float) degToRad(minRotationRate), (float) degToRad(maxRotationRate)); - - return emitter; -} - - -void -ParticleSystemLoader::raiseError(const string& errorMessage) -{ - m_errorMessage = errorMessage; -} - - -const string& -ParticleSystemLoader::getErrorMessage() const -{ - return m_errorMessage; -} - - -void -ParticleSystemLoader::setTexturePath(const string& texPath) -{ - m_texPath = texPath; -} - - -const string& -ParticleSystemLoader::getTexturePath() const -{ - return m_texPath; -} - - -ParticleSystem* -LoadParticleSystem(istream& in, const string& texPath) -{ - auto* loader = new ParticleSystemLoader(in); - if (loader == nullptr) - return nullptr; - - loader->setTexturePath(texPath); - - ParticleSystem* particleSystem = loader->load(); - if (particleSystem == nullptr) - cerr << "Error in particle system file: " << loader->getErrorMessage() << '\n'; - - delete loader; - - return particleSystem; -} diff --git a/src/celengine/particlesystemfile.h b/src/celengine/particlesystemfile.h deleted file mode 100644 index 42e6fe391..000000000 --- a/src/celengine/particlesystemfile.h +++ /dev/null @@ -1,53 +0,0 @@ -// particlesystem.h -// -// Particle system file loader. -// -// Copyright (C) 2008, Chris Laurel -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -#ifndef _CELENGINE_PARTICLESYSTEMFILE_H_ -#define _CELENGINE_PARTICLESYSTEMFILE_H_ - -#include -#include -#include -#include "parser.h" - -class ParticleSystem; -class VectorGenerator; -class ParticleEmitter; - -class ParticleSystemLoader -{ - public: - ParticleSystemLoader(std::istream&); - ~ParticleSystemLoader() = default; - - ParticleSystem* load(); - VectorGenerator* parseGenerator(Hash* params); - ParticleEmitter* parseEmitter(Hash* params); - - const std::string& getErrorMessage() const; - void setTexturePath(const std::string&); - const std::string& getTexturePath() const; - - static ParticleSystemLoader* OpenParticleSystemFile(std::istream& in); - - private: - virtual void raiseError(const std::string&); - - private: - Tokenizer m_tokenizer; - Parser m_parser; - std::string m_errorMessage; - std::string m_texPath; -}; - - -ParticleSystem* LoadParticleSystem(std::istream& in, const std::string& texPath); - -#endif // _CELENGINE_PARTICLESYSTEMFILE_H_ diff --git a/src/celutil/filetype.cpp b/src/celutil/filetype.cpp index df0a9162f..aae42a635 100644 --- a/src/celutil/filetype.cpp +++ b/src/celutil/filetype.cpp @@ -35,7 +35,6 @@ static const char CelestiaLegacyScriptExt[] = ".cel"; static const char CelestiaScriptExt[] = ".clx"; static const char CelestiaScriptExt2[] = ".celx"; static const char CelestiaModelExt[] = ".cmod"; -static const char CelestiaParticleSystemExt[] = ".cpart"; static const char CelestiaXYZTrajectoryExt[] = ".xyz"; static const char CelestiaXYZVTrajectoryExt[] = ".xyzv"; static const char ContentXYZVBinaryExt[] = ".xyzvbin"; @@ -82,8 +81,6 @@ ContentType DetermineFileType(const fs::path& filename) return Content_CelestiaScript; if (compareIgnoringCase(CelestiaModelExt, ext) == 0) return Content_CelestiaModel; - if (compareIgnoringCase(CelestiaParticleSystemExt, ext) == 0) - return Content_CelestiaParticleSystem; if (compareIgnoringCase(DXT5NormalMapExt, ext) == 0) return Content_DXT5NormalMap; if (compareIgnoringCase(CelestiaXYZTrajectoryExt, ext) == 0) diff --git a/src/celutil/filetype.h b/src/celutil/filetype.h index 671d6b3db..ad10405a1 100644 --- a/src/celutil/filetype.h +++ b/src/celutil/filetype.h @@ -34,7 +34,7 @@ enum ContentType Content_DXT5NormalMap = 17, Content_CelestiaXYZTrajectory = 18, Content_CelestiaXYZVTrajectory = 19, - Content_CelestiaParticleSystem = 20, + // Content_CelestiaParticleSystem = 20, Content_WarpMesh = 21, Content_CelestiaXYZVBinary = 22, #ifdef USE_LIBAVIF