2021-10-05 01:10:25 +00:00
|
|
|
/* Snowstorm - Particle effects in C
|
|
|
|
*
|
|
|
|
* Copyright (c) 2021 Evan Hemsley
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Evan "cosmonaut" Hemsley <evan@moonside.games>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
#include "snowstorm.h"
|
2021-10-05 01:10:25 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
2021-10-05 21:44:00 +00:00
|
|
|
#include <string.h>
|
2021-10-05 01:10:25 +00:00
|
|
|
#include <time.h>
|
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
#define PI 3.14159265358979323846
|
|
|
|
|
|
|
|
typedef struct Snowstorm_Color
|
|
|
|
{
|
|
|
|
uint8_t r;
|
|
|
|
uint8_t g;
|
|
|
|
uint8_t b;
|
|
|
|
uint8_t a;
|
|
|
|
} Snowstorm_Color;
|
|
|
|
|
|
|
|
typedef struct Snowstorm_UV
|
|
|
|
{
|
|
|
|
float left;
|
|
|
|
float top;
|
|
|
|
float right;
|
|
|
|
float bottom;
|
|
|
|
} Snowstorm_UV;
|
|
|
|
|
2021-10-05 01:10:25 +00:00
|
|
|
typedef struct Snowstorm_Vector2
|
|
|
|
{
|
|
|
|
float x;
|
|
|
|
float y;
|
|
|
|
} Snowstorm_Vector2;
|
|
|
|
|
|
|
|
static inline Snowstorm_Vector2 Vector2_Rotate(Snowstorm_Vector2 vector, float angle)
|
|
|
|
{
|
|
|
|
Snowstorm_Vector2 rotated;
|
|
|
|
rotated.x = vector.x * cosf(angle) - vector.y * sinf(angle);
|
|
|
|
rotated.y = vector.x * sinf(angle) + vector.y * cosf(angle);
|
|
|
|
return rotated;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float Vector2_Magnitude(Snowstorm_Vector2 vector)
|
|
|
|
{
|
|
|
|
return sqrtf(vector.x * vector.x + vector.y * vector.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Snowstorm_Vector2 Vector2_Normalize(Snowstorm_Vector2 vector)
|
|
|
|
{
|
|
|
|
float length = Vector2_Magnitude(vector);
|
|
|
|
|
|
|
|
Snowstorm_Vector2 normalized;
|
|
|
|
normalized.x = vector.x / length;
|
|
|
|
normalized.y = vector.y / length;
|
|
|
|
|
|
|
|
return normalized;
|
|
|
|
}
|
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
typedef struct Snowstorm_Matrix3x2
|
|
|
|
{
|
|
|
|
float M11;
|
|
|
|
float M12;
|
|
|
|
float M21;
|
|
|
|
float M22;
|
|
|
|
float M31;
|
|
|
|
float M32;
|
|
|
|
} Snowstorm_Matrix3x2;
|
|
|
|
|
|
|
|
static inline Snowstorm_Matrix3x2 Matrix3x2_CreateTranslation(float x, float y)
|
|
|
|
{
|
|
|
|
Snowstorm_Matrix3x2 result;
|
|
|
|
result.M11 = 1;
|
|
|
|
result.M12 = 0;
|
|
|
|
result.M21 = 0;
|
|
|
|
result.M22 = 1;
|
|
|
|
result.M31 = x;
|
|
|
|
result.M32 = y;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Snowstorm_Matrix3x2 Matrix3x2_CreateScale(float x, float y)
|
|
|
|
{
|
|
|
|
Snowstorm_Matrix3x2 result;
|
|
|
|
result.M11 = x;
|
|
|
|
result.M12 = 0;
|
|
|
|
result.M21 = 0;
|
|
|
|
result.M22 = y;
|
|
|
|
result.M31 = 0;
|
|
|
|
result.M32 = 0;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Snowstorm_Matrix3x2 Matrix3x2_CreateRotation(float radians)
|
|
|
|
{
|
|
|
|
Snowstorm_Matrix3x2 result;
|
|
|
|
float c, s;
|
|
|
|
float epsilon = 0.001f * PI / 180; /* 0.1 % of a degree */
|
|
|
|
|
|
|
|
if (radians > -epsilon && radians < epsilon)
|
|
|
|
{
|
|
|
|
/* Exact case for zero rotation. */
|
|
|
|
c = 1;
|
|
|
|
s = 0;
|
|
|
|
}
|
|
|
|
else if (radians > PI / 2 - epsilon && radians < PI / 2 + epsilon)
|
|
|
|
{
|
|
|
|
/* Exact case for 90 degree rotation. */
|
|
|
|
c = 0;
|
|
|
|
s = 1;
|
|
|
|
}
|
|
|
|
else if (radians < -PI + epsilon && radians > PI - epsilon)
|
|
|
|
{
|
|
|
|
/* Exact case for 180 degree rotation. */
|
|
|
|
c = -1;
|
|
|
|
s = 0;
|
|
|
|
}
|
|
|
|
else if (radians > -PI / 2 - epsilon && radians < -PI / 2 + epsilon)
|
|
|
|
{
|
|
|
|
/* Exact case for 270 degree rotation. */
|
|
|
|
c = 0;
|
|
|
|
s = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Arbitrary rotation. */
|
|
|
|
c = cosf(radians);
|
|
|
|
s = sinf(radians);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* [ c s ]
|
|
|
|
* [ -s c ]
|
|
|
|
* [ 0 0 ]
|
|
|
|
*/
|
|
|
|
result.M11 = c;
|
|
|
|
result.M12 = s;
|
|
|
|
result.M21 = -s;
|
|
|
|
result.M22 = c;
|
|
|
|
result.M31 = 0;
|
|
|
|
result.M32 = 0;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Snowstorm_Matrix3x2 Matrix3x2_Multiply(Snowstorm_Matrix3x2 m1, Snowstorm_Matrix3x2 m2)
|
|
|
|
{
|
|
|
|
Snowstorm_Matrix3x2 result;
|
|
|
|
|
|
|
|
/* First row */
|
|
|
|
result.M11 = m1.M11 * m2.M11 + m1.M12 * m2.M21;
|
|
|
|
result.M12 = m1.M11 * m2.M12 + m1.M12 * m2.M22;
|
|
|
|
|
|
|
|
/* Second row */
|
|
|
|
result.M21 = m1.M21 * m2.M11 + m1.M22 * m2.M21;
|
|
|
|
result.M22 = m1.M21 * m2.M12 + m1.M22 * m2.M22;
|
|
|
|
|
|
|
|
/* Third row */
|
|
|
|
result.M31 = m1.M31 * m2.M11 + m1.M32 * m2.M21 + m2.M31;
|
|
|
|
result.M32 = m1.M31 * m2.M12 + m1.M32 * m2.M22 + m2.M32;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Snowstorm_Vector2 Vector2_Transform(Snowstorm_Vector2 vector, Snowstorm_Matrix3x2 matrix)
|
|
|
|
{
|
|
|
|
Snowstorm_Vector2 result;
|
|
|
|
result.x = (vector.x * matrix.M11) + (vector.y * matrix.M21) + matrix.M31;
|
|
|
|
result.y = (vector.x * matrix.M12) + (vector.y * matrix.M22) + matrix.M32;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-10-05 01:10:25 +00:00
|
|
|
typedef struct Snowstorm_Particle
|
|
|
|
{
|
|
|
|
float time;
|
2021-10-05 21:44:00 +00:00
|
|
|
float timeRate;
|
2021-10-05 01:10:25 +00:00
|
|
|
Snowstorm_Vector2 position;
|
|
|
|
Snowstorm_Vector2 velocity;
|
|
|
|
Snowstorm_Vector2 scale;
|
|
|
|
float size;
|
|
|
|
float rotation;
|
|
|
|
float spin;
|
|
|
|
|
|
|
|
float directionVariance;
|
|
|
|
float speedVariance;
|
|
|
|
Snowstorm_Vector2 catchup;
|
2021-10-05 21:44:00 +00:00
|
|
|
|
|
|
|
uint32_t uvIndex;
|
2021-10-05 01:10:25 +00:00
|
|
|
} Snowstorm_Particle;
|
|
|
|
|
|
|
|
typedef struct Snowstorm_Context
|
|
|
|
{
|
2021-10-05 21:44:00 +00:00
|
|
|
Snowstorm_Particle* particles;
|
2021-10-05 01:10:25 +00:00
|
|
|
uint32_t particleCount;
|
2021-10-05 21:44:00 +00:00
|
|
|
uint32_t particleCapacity;
|
2021-10-05 01:10:25 +00:00
|
|
|
|
|
|
|
Snowstorm_Vector2 wind;
|
|
|
|
|
|
|
|
float leftBound;
|
|
|
|
float topBound;
|
|
|
|
float rightBound;
|
|
|
|
float bottomBound;
|
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
Snowstorm_UV* uvs;
|
|
|
|
uint32_t uvCount;
|
|
|
|
|
|
|
|
uint8_t* currentBufferAddress; /* GM doesnt let you pass more than 4 arguments with different types lol */
|
|
|
|
} Snowstorm_Context;
|
2021-10-05 01:10:25 +00:00
|
|
|
|
|
|
|
static inline float Approach(float value, float target, float maxChange)
|
|
|
|
{
|
|
|
|
return value + min(max(target - value, -maxChange), maxChange);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float WrapWithOvershoot(float value, float min, float max)
|
|
|
|
{
|
|
|
|
if (value < min)
|
|
|
|
{
|
|
|
|
value = max - (min - value);
|
|
|
|
}
|
|
|
|
if (value > max)
|
|
|
|
{
|
|
|
|
value = min + (value - max);
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float Random(float a)
|
|
|
|
{
|
|
|
|
return (float)rand() / (float)(RAND_MAX / a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline float RandomRange(float min, float max)
|
|
|
|
{
|
|
|
|
return Random(max - min) + min;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Snowstorm_Init()
|
|
|
|
{
|
|
|
|
srand((unsigned int)time(NULL));
|
2021-10-05 21:44:00 +00:00
|
|
|
}
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
const char* Snowstorm_Create()
|
|
|
|
{
|
|
|
|
Snowstorm_Context *context = malloc(sizeof(Snowstorm_Context));
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
context->particleCapacity = 128;
|
|
|
|
context->particles = malloc(sizeof(Snowstorm_Particle) * context->particleCapacity);
|
2021-10-05 01:10:25 +00:00
|
|
|
context->particleCount = 0;
|
|
|
|
|
|
|
|
context->leftBound = -10;
|
|
|
|
context->rightBound = 490;
|
|
|
|
context->topBound = -10;
|
|
|
|
context->bottomBound = 280;
|
|
|
|
|
|
|
|
context->wind.x = 0;
|
|
|
|
context->wind.y = 0;
|
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
context->uvs = NULL;
|
|
|
|
context->uvCount = 0;
|
|
|
|
|
|
|
|
context->currentBufferAddress = NULL;
|
|
|
|
|
|
|
|
return (const char*)context;
|
2021-10-05 01:10:25 +00:00
|
|
|
}
|
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
void Snowstorm_SetUVCount(const char *contextPointer, double count)
|
2021-10-05 01:10:25 +00:00
|
|
|
{
|
2021-10-05 21:44:00 +00:00
|
|
|
Snowstorm_Context *context = (Snowstorm_Context*)contextPointer;
|
|
|
|
|
|
|
|
context->uvCount = (uint32_t)count;
|
|
|
|
context->uvs = realloc(context->uvs, sizeof(Snowstorm_UV) * context->uvCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Snowstorm_SetLeftTopUV(const char *contextPointer, double index, double left, double top)
|
|
|
|
{
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
|
|
|
|
|
|
|
context->uvs[(uint32_t)index].left = left;
|
|
|
|
context->uvs[(uint32_t)index].top = top;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Snowstorm_SetRightBottomUV(const char* contextPointer, double index, double right, double bottom)
|
|
|
|
{
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
|
|
|
|
|
|
|
context->uvs[(uint32_t)index].right = right;
|
|
|
|
context->uvs[(uint32_t)index].bottom = bottom;
|
|
|
|
}
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
void Snowstorm_Update(const char *contextPointer)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
2021-10-05 01:10:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < context->particleCount; i += 1)
|
|
|
|
{
|
2021-10-05 21:44:00 +00:00
|
|
|
Snowstorm_Particle *particle = &context->particles[i];
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
particle->time += particle->timeRate;
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
float speed = Vector2_Magnitude(particle->velocity);
|
|
|
|
float rotation = sinf(particle->time / (speed * 100)) * particle->directionVariance;
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
float windSpeed = Vector2_Magnitude(context->wind);
|
|
|
|
Snowstorm_Vector2 wind = Vector2_Normalize(context->wind);
|
|
|
|
wind.x *= (windSpeed + particle->speedVariance);
|
|
|
|
wind.y *= (windSpeed + particle->speedVariance);
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
wind = Vector2_Rotate(wind, rotation);
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
particle->velocity.x = Approach(particle->velocity.x, wind.x, particle->catchup.x);
|
|
|
|
particle->velocity.y = Approach(particle->velocity.y, wind.y, particle->catchup.y);
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
particle->position.x = WrapWithOvershoot(particle->position.x + particle->velocity.x, context->leftBound, context->rightBound);
|
|
|
|
particle->position.y = WrapWithOvershoot(particle->position.y + particle->velocity.y, context->topBound, context->bottomBound);
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
particle->scale.y = particle->size * sinf(particle->time / 10);
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
particle->rotation += particle->spin;
|
2021-10-05 01:10:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
void Snowstorm_ApplyChaos(const char* contextPointer, double directionChaos, double speedChaos)
|
2021-10-05 01:10:25 +00:00
|
|
|
{
|
|
|
|
uint32_t i;
|
2021-10-05 21:44:00 +00:00
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
2021-10-05 01:10:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < context->particleCount; i += 1)
|
|
|
|
{
|
2021-10-05 21:44:00 +00:00
|
|
|
Snowstorm_Particle* particle = &context->particles[i];
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
particle->directionVariance = RandomRange(-directionChaos, directionChaos);
|
|
|
|
particle->speedVariance = RandomRange(-speedChaos, speedChaos);
|
2021-10-05 01:10:25 +00:00
|
|
|
}
|
2021-10-05 21:44:00 +00:00
|
|
|
}
|
2021-10-05 01:10:25 +00:00
|
|
|
|
2021-10-05 21:44:00 +00:00
|
|
|
void Snowstorm_ApplyWind(const char *contextPointer, double xSpeed, double ySpeed)
|
|
|
|
{
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
2021-10-05 01:10:25 +00:00
|
|
|
context->wind.x = (float)xSpeed;
|
|
|
|
context->wind.y = (float)ySpeed;
|
|
|
|
}
|
2021-10-05 21:44:00 +00:00
|
|
|
|
|
|
|
void Snowstorm_SetParticles(const char *contextPointer, double count)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
|
|
|
|
|
|
|
if (count > context->particleCapacity)
|
|
|
|
{
|
|
|
|
context->particleCapacity *= 2;
|
|
|
|
context->particles = realloc(context->particles, sizeof(Snowstorm_Particle) * context->particleCapacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < count; i += 1)
|
|
|
|
{
|
|
|
|
Snowstorm_Particle* particle = &context->particles[i];
|
|
|
|
|
|
|
|
particle->time = 0;
|
|
|
|
particle->timeRate = 0.7f + RandomRange(-0.3f, 0.3f);
|
|
|
|
particle->position.x = RandomRange(context->leftBound, context->rightBound);
|
|
|
|
particle->position.y = RandomRange(context->topBound, context->bottomBound);
|
|
|
|
particle->directionVariance = 0;
|
|
|
|
particle->speedVariance = 0;
|
|
|
|
particle->catchup.x = RandomRange(0.2f, 1);
|
|
|
|
particle->catchup.y = RandomRange(0.2f, 1);
|
|
|
|
particle->velocity.x = context->wind.x;
|
|
|
|
particle->velocity.y = context->wind.y;
|
|
|
|
particle->size = 0.4f;
|
|
|
|
particle->scale.x = particle->size;
|
|
|
|
particle->scale.y = particle->size;
|
|
|
|
particle->spin = RandomRange(-0.1745329f, 0.1745329f); /* 10 degrees */
|
|
|
|
particle->rotation = 0;
|
|
|
|
particle->uvIndex = rand() % context->uvCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Snowstorm_SetBufferAddress(const char *contextPointer, const char* bufferAddress)
|
|
|
|
{
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
|
|
|
context->currentBufferAddress = (uint8_t*)bufferAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
double Snowstorm_RequiredSnowBufferSize(const char *contextPointer)
|
|
|
|
{
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
|
|
|
return (double)context->particleCount * 6 * (sizeof(Snowstorm_Vector2) + sizeof(Snowstorm_Color) + (2 * sizeof(float)));
|
|
|
|
}
|
|
|
|
|
|
|
|
double Snowstorm_FillSnowBuffer(const char *contextPointer)
|
|
|
|
{
|
|
|
|
uint32_t i, vertexCount;
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
|
|
|
uint8_t* bufferAddress = context->currentBufferAddress;
|
|
|
|
|
|
|
|
Snowstorm_Color color;
|
|
|
|
color.r = 255;
|
|
|
|
color.g = 255;
|
|
|
|
color.b = 255;
|
|
|
|
color.a = 255;
|
|
|
|
|
|
|
|
vertexCount = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < context->particleCount; i += 1)
|
|
|
|
{
|
|
|
|
Snowstorm_Particle* particle = &context->particles[i];
|
|
|
|
|
|
|
|
Snowstorm_Vector2 leftTop;
|
|
|
|
Snowstorm_Vector2 rightTop;
|
|
|
|
Snowstorm_Vector2 leftBottom;
|
|
|
|
Snowstorm_Vector2 rightBottom;
|
|
|
|
|
|
|
|
leftTop.x = -particle->scale.x;
|
|
|
|
leftTop.y = -particle->scale.y;
|
|
|
|
|
|
|
|
rightTop.x = particle->scale.x;
|
|
|
|
rightTop.y = -particle->scale.y;
|
|
|
|
|
|
|
|
leftBottom.x = -particle->scale.x;
|
|
|
|
leftBottom.y = particle->scale.y;
|
|
|
|
|
|
|
|
rightBottom.x = particle->scale.x;
|
|
|
|
rightBottom.y = particle->scale.y;
|
|
|
|
|
|
|
|
Snowstorm_Matrix3x2 translation = Matrix3x2_CreateTranslation(particle->position.x, particle->position.y);
|
|
|
|
Snowstorm_Matrix3x2 rotation = Matrix3x2_CreateRotation(particle->rotation);
|
|
|
|
Snowstorm_Matrix3x2 transform = Matrix3x2_Multiply(translation, rotation);
|
|
|
|
|
|
|
|
leftTop = Vector2_Transform(leftTop, transform);
|
|
|
|
rightTop = Vector2_Transform(rightTop, transform);
|
|
|
|
leftBottom = Vector2_Transform(leftBottom, transform);
|
|
|
|
rightBottom = Vector2_Transform(rightBottom, transform);
|
|
|
|
|
|
|
|
float leftUV = context->uvs[particle->uvIndex].left;
|
|
|
|
float topUV = context->uvs[particle->uvIndex].top;
|
|
|
|
float rightUV = context->uvs[particle->uvIndex].right;
|
|
|
|
float bottomUV = context->uvs[particle->uvIndex].bottom;
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &leftTop, sizeof(Snowstorm_Vector2));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Vector2);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &color, sizeof(Snowstorm_Color));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Color);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &leftUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &topUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &rightTop, sizeof(Snowstorm_Vector2));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Vector2);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &color, sizeof(Snowstorm_Color));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Color);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &rightUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &topUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &leftBottom, sizeof(Snowstorm_Vector2));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Vector2);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &color, sizeof(Snowstorm_Color));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Color);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &leftUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &bottomUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &leftBottom, sizeof(Snowstorm_Vector2));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Vector2);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &color, sizeof(Snowstorm_Color));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Color);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &leftUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &bottomUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &rightTop, sizeof(Snowstorm_Vector2));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Vector2);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &color, sizeof(Snowstorm_Color));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Color);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &rightUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &topUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &rightBottom, sizeof(Snowstorm_Vector2));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Vector2);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &color, sizeof(Snowstorm_Color));
|
|
|
|
bufferAddress += sizeof(Snowstorm_Color);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &rightUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
memcpy(bufferAddress, &bottomUV, sizeof(float));
|
|
|
|
bufferAddress += sizeof(float);
|
|
|
|
|
|
|
|
vertexCount += 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (double)vertexCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Snowstorm_Destroy(const char *contextPointer)
|
|
|
|
{
|
|
|
|
Snowstorm_Context* context = (Snowstorm_Context*)contextPointer;
|
|
|
|
|
|
|
|
if (context->particles != NULL)
|
|
|
|
{
|
|
|
|
free(context->particles);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (context->uvs != NULL)
|
|
|
|
{
|
|
|
|
free(context->uvs);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(context);
|
|
|
|
}
|