Add fourccId support.

This commit is contained in:
DelinWorks 2022-06-16 15:25:43 +03:00
parent 2b2a57e8ce
commit 2e3c84252d
5 changed files with 71 additions and 37 deletions

View File

@ -796,7 +796,7 @@ void ParticleSystem::addParticles(int count, int animationIndex, int animationCe
case EmissionShapeType::CIRCLE:
{
auto val = _rng.float01() * shape.innerRadius / shape.innerRadius;
val = powf(val, 1 / shape.edgeElasticity);
val = powf(val, 1 / shape.edgeBias);
auto point = Vec2(0.0F, val * shape.innerRadius);
point = point.rotateByAngle(Vec2::ZERO, -CC_DEGREES_TO_RADIANS(shape.coneOffset + shape.coneAngle / 2 * _rng.rangef()));
_particleData.posx[i] = _sourcePosition.x + shape.x + point.x / 2;
@ -807,7 +807,7 @@ void ParticleSystem::addParticles(int count, int animationIndex, int animationCe
case EmissionShapeType::TORUS:
{
auto val = _rng.float01() * shape.outerRadius / shape.outerRadius;
val = powf(val, 1 / shape.edgeElasticity);
val = powf(val, 1 / shape.edgeBias);
auto point = Vec2(0.0F, ((val * (shape.outerRadius - shape.innerRadius) + shape.outerRadius) - (shape.outerRadius - shape.innerRadius)));
point = point.rotateByAngle(Vec2::ZERO, -CC_DEGREES_TO_RADIANS(shape.coneOffset + shape.coneAngle / 2 * _rng.rangef()));
_particleData.posx[i] = _sourcePosition.x + shape.x + point.x / 2;
@ -817,7 +817,7 @@ void ParticleSystem::addParticles(int count, int animationIndex, int animationCe
}
case EmissionShapeType::ALPHA_MASK:
{
auto& mask = ParticleEmissionMaskCache::getInstance()->getEmissionMask(shape.maskName);
auto& mask = ParticleEmissionMaskCache::getInstance()->getEmissionMask(shape.fourccId);
Vec2 pos = {shape.x, shape.y};
Vec2 size = mask.size;
@ -1151,7 +1151,7 @@ void ParticleSystem::setEmissionShape(unsigned short index, EmissionShape shape)
iter->second = shape;
}
EmissionShape ParticleSystem::createMaskShape(std::string_view maskName,
EmissionShape ParticleSystem::createMaskShape(std::string_view maskId,
Vec2 pos,
Vec2 overrideSize,
Vec2 scale,
@ -1161,7 +1161,7 @@ EmissionShape ParticleSystem::createMaskShape(std::string_view maskName,
shape.type = EmissionShapeType::ALPHA_MASK;
shape.maskName = maskName;
shape.fourccId = utils::fourccValue(maskId);
shape.x = pos.x;
shape.y = pos.y;
@ -1222,7 +1222,7 @@ EmissionShape ParticleSystem::createRectTorusShape(Vec2 pos, Size innerSize, Siz
return shape;
}
EmissionShape ParticleSystem::createCircleShape(Vec2 pos, float radius, float edgeElasticity)
EmissionShape ParticleSystem::createCircleShape(Vec2 pos, float radius, float edgeBias)
{
EmissionShape shape{};
@ -1236,7 +1236,7 @@ EmissionShape ParticleSystem::createCircleShape(Vec2 pos, float radius, float ed
shape.coneOffset = 0;
shape.coneAngle = 360;
shape.edgeElasticity = edgeElasticity;
shape.edgeBias = edgeBias;
return shape;
}
@ -1255,7 +1255,7 @@ EmissionShape ParticleSystem::createConeShape(Vec2 pos, float radius, float offs
shape.coneOffset = offset;
shape.coneAngle = angle;
shape.edgeElasticity = edgeBias;
shape.edgeBias = edgeBias;
return shape;
}
@ -1275,7 +1275,7 @@ EmissionShape ParticleSystem::createTorusShape(Vec2 pos, float innerRadius, floa
shape.coneOffset = 0;
shape.coneAngle = 360;
shape.edgeElasticity = edgeBias;
shape.edgeBias = edgeBias;
return shape;
}
@ -1300,7 +1300,7 @@ EmissionShape ParticleSystem::createConeTorusShape(Vec2 pos,
shape.coneOffset = offset;
shape.coneAngle = angle;
shape.edgeElasticity = edgeBias;
shape.edgeBias = edgeBias;
return shape;
}
@ -2269,7 +2269,7 @@ ParticleEmissionMaskCache* ParticleEmissionMaskCache::getInstance()
return emissionMaskCache;
}
void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskName,
void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskId,
std::string_view texturePath,
float alphaThreshold,
bool inverted,
@ -2280,10 +2280,10 @@ void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskName,
img->autorelease();
CCASSERT(img, "image texture was nullptr.");
bakeEmissionMask(maskName, img, alphaThreshold, inverted, inbetweenSamples);
bakeEmissionMask(maskId, img, alphaThreshold, inverted, inbetweenSamples);
}
void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskName,
void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskId,
Image* imageTexture,
float alphaThreshold,
bool inverted,
@ -2322,9 +2322,11 @@ void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskName,
}
}
auto iter = this->masks.find(maskName);
auto fourccId = utils::fourccValue(maskId);
auto iter = this->masks.find(fourccId);
if (iter == this->masks.end())
iter = this->masks.emplace(maskName, ParticleEmissionMaskDescriptor{}).first;
iter = this->masks.emplace(fourccId, ParticleEmissionMaskDescriptor{}).first;
ParticleEmissionMaskDescriptor desc;
desc.size = {float(w), float(h)};
@ -2332,16 +2334,16 @@ void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskName,
iter->second = desc;
CCLOG("Particle emission mask '%s' baked (%dx%d), %d samples generated taking %.2fmb of memory.",
std::string(maskName).c_str(), w, h, desc.points.size(), desc.points.size() * 8 / 1e+6);
CCLOG("Particle emission mask '%lu' baked (%dx%d), %d samples generated taking %.2fmb of memory.",
(unsigned long)htonl(fourccId), w, h, desc.points.size(), desc.points.size() * 8 / 1e+6);
}
const ParticleEmissionMaskDescriptor& ParticleEmissionMaskCache::getEmissionMask(std::string_view maskName)
const ParticleEmissionMaskDescriptor& ParticleEmissionMaskCache::getEmissionMask(uint32_t fourccId)
{
auto iter = this->masks.find(maskName);
auto iter = this->masks.find(fourccId);
if (iter == this->masks.end())
{
iter = this->masks.emplace(maskName, ParticleEmissionMaskDescriptor{}).first;
iter = this->masks.emplace(fourccId, ParticleEmissionMaskDescriptor{}).first;
iter->second.size = {float(1), float(1)};
iter->second.points = {{0, 0}};
return iter->second;
@ -2349,9 +2351,24 @@ const ParticleEmissionMaskDescriptor& ParticleEmissionMaskCache::getEmissionMask
return iter->second;
}
void ParticleEmissionMaskCache::removeMask(std::string_view maskName)
const ParticleEmissionMaskDescriptor& ParticleEmissionMaskCache::getEmissionMask(std::string_view maskId)
{
this->masks.erase(maskName);
auto fourccId = utils::fourccValue(maskId);
auto iter = this->masks.find(fourccId);
if (iter == this->masks.end())
{
iter = this->masks.emplace(fourccId, ParticleEmissionMaskDescriptor{}).first;
iter->second.size = {float(1), float(1)};
iter->second.points = {{0, 0}};
return iter->second;
}
return iter->second;
}
void ParticleEmissionMaskCache::removeMask(std::string_view maskId)
{
this->masks.erase(utils::fourccValue(maskId));
}
void ParticleEmissionMaskCache::removeAllMasks()

View File

@ -101,9 +101,9 @@ struct EmissionShape
float outerRadius;
float coneOffset;
float coneAngle;
float edgeElasticity;
float edgeBias;
std::string maskName;
uint32_t fourccId;
};
/** @struct ParticleAnimationDescriptor
@ -270,7 +270,7 @@ public:
/** Bakes a particle emission mask from texture data on cpu and stores it in memory by it's name.
* If the mask already exists then it will be overwritten.
*
* @param maskName The name that identifies the mask.
* @param maskId The id of the mask, FOURCC starts with '#', such as "#abcd"
* @param texturePath Path of the texture that holds alpha data.
* @param alphaThreshold The threshold at which pixels are picked, If a pixel's alpha channel is greater than
* alphaThreshold then it will be picked.
@ -279,7 +279,7 @@ public:
* @param inbetweenSamples How many times should pixels be filled inbetween, this value should be increased If
* you're planning to scale the emission shape up. WARNING: it will use more memory.
*/
void bakeEmissionMask(std::string_view maskName,
void bakeEmissionMask(std::string_view maskId,
std::string_view texturePath,
float alphaThreshold = 0.5F,
bool inverted = false,
@ -288,7 +288,7 @@ public:
/** Bakes a particle emission mask from texture data on cpu and stores it in memory by it's name.
* If the mask already exists then it will be overwritten.
*
* @param maskName The name that identifies the mask.
* @param maskId The id of the mask, FOURCC starts with '#', such as "#abcd"
* @param imageTexture Image object containing texture data with alpha channel.
* @param alphaThreshold The threshold at which pixels are picked, If a pixel's alpha channel is greater than
* alphaThreshold then it will be picked.
@ -297,7 +297,7 @@ public:
* @param inbetweenSamples How many times should pixels be filled inbetween, this value should be increased If
* you're planning to scale the emission shape up. WARNING: it will use more memory.
*/
void bakeEmissionMask(std::string_view maskName,
void bakeEmissionMask(std::string_view maskId,
Image* imageTexture,
float alphaThreshold = 0.5F,
bool inverted = false,
@ -305,21 +305,27 @@ public:
/** Returns a baked mask with the specified name if it exists. otherwise, it will return a dummy mask.
*
* @param maskName The name that identifies the mask.
* @param fourccId The unsigned integer id of the mask.
*/
const ParticleEmissionMaskDescriptor& getEmissionMask(std::string_view maskName);
const ParticleEmissionMaskDescriptor& getEmissionMask(uint32_t fourccId);
/** Returns a baked mask with the specified name if it exists. otherwise, it will return a dummy mask.
*
* @param maskId The id of the mask, FOURCC starts with '#', such as "#abcd"
*/
const ParticleEmissionMaskDescriptor& getEmissionMask(std::string_view maskId);
/** Removes a baked mask and releases the data from memory with the specified name if it exists.
*
* @param maskName The name that identifies the mask.
* @param maskId The id of the mask, FOURCC starts with '#', such as "#abcd"
*/
void removeMask(std::string_view maskName);
void removeMask(std::string_view maskId);
/** Remove all baked masks and releases their data from memory. */
void removeAllMasks();
private:
hlookup::string_map<ParticleEmissionMaskDescriptor> masks;
std::unordered_map<uint32_t, ParticleEmissionMaskDescriptor> masks;
};
@ -1245,13 +1251,13 @@ public:
/** Adds an emission shape of type mask to the system.
* The mask should be added using the ParticleEmissionMaskCache class.
*
* @param maskName Name of the emission mask.
* @param maskId The id of the mask, FOURCC starts with '#', such as "#abcd"
* @param pos Position of the emission shape in local space.
* @param overrideSize Size of the emission mask in pixels, leave ZERO to use texture size.
* @param scale Scale of the emission mask, the size will be multiplied by the specified scale.
* @param angle Angle of the sampled points to be rotated in degrees.
*/
static EmissionShape createMaskShape(std::string_view maskName, Vec2 pos = Vec2::ZERO, Vec2 overrideSize = Vec2::ZERO, Vec2 scale = Vec2::ONE, float angle = 0.0F);
static EmissionShape createMaskShape(std::string_view maskId, Vec2 pos = Vec2::ZERO, Vec2 overrideSize = Vec2::ZERO, Vec2 scale = Vec2::ONE, float angle = 0.0F);
/** Adds an emission shape of type point to the system.
* @param pos Position of the emission shape in local space.

View File

@ -780,6 +780,15 @@ std::string urlDecode(std::string_view st)
return decoded;
}
CC_DLL uint32_t fourccValue(std::string_view str)
{
if (str.empty() || str[0] != '#')
return (uint32_t)-1;
uint32_t value = 0;
memcpy(&value, str.data() + 1, std::min(sizeof(value), str.size() - 1));
return value;
}
} // namespace utils
NS_CC_END

View File

@ -404,6 +404,8 @@ inline char* char2hex(char* p, unsigned char c, unsigned char a = 'a')
CC_DLL std::string urlEncode(std::string_view s);
CC_DLL std::string urlDecode(std::string_view st);
CC_DLL uint32_t fourccValue(std::string_view str);
} // namespace utils
NS_CC_END

View File

@ -1783,9 +1783,9 @@ void DemoEmissionShapeAlphaMask::onEnter()
_emitter->setEmissionShapes(true);
auto cache = ParticleEmissionMaskCache::getInstance();
cache->bakeEmissionMask("mask_001"sv, "Particles/mask.png", 0.5F, false, 1);
cache->bakeEmissionMask("#msk1"sv, "Particles/mask.png", 0.5F, false, 1);
_emitter->addEmissionShape(ParticleSystem::createMaskShape("mask_001"sv, {0, 0}, {400, 200}, Vec2::ONE));
_emitter->addEmissionShape(ParticleSystem::createMaskShape("#msk1"sv, {0, 0}, {400, 200}, Vec2::ONE));
setEmitterPosition();
}