[cpp] Added VertexEffect.

This commit is contained in:
badlogic 2018-03-05 16:08:17 +01:00
parent 9ceec41432
commit e4a029e1a7
9 changed files with 369 additions and 53 deletions

View File

@ -81,7 +81,47 @@ public:
static float fmod(float a, float b);
static bool isNan(float v);
static float random();
static float randomTriangular(float min, float max);
static float randomTriangular(float min, float max, float mode);
static float pow(float a, float b);
};
struct Interpolation {
virtual float apply(float a) = 0;
virtual float interpolate(float start, float end, float a) {
return start + (end - start) * apply(a);
}
};
struct PowInterpolation: public Interpolation {
PowInterpolation(int power): power(power) {
}
float apply(float a) {
if (a <= 0.5f) return MathUtil::pow(a * 2, power) / 2;
return MathUtil::pow((a - 1) * 2, power) / (power % 2 == 0 ? -2 : 2) + 1;
}
int power;
};
struct PowOutInterpolation: public Interpolation {
PowOutInterpolation(int power): power(power) {
}
float apply(float a) {
return MathUtil::pow(a - 1, power) * (power % 2 == 0 ? -1 : 1) + 1;
}
int power;
};
}
#endif /* Spine_MathUtil_h */

View File

@ -0,0 +1,106 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_VertexEffect_h
#define Spine_VertexEffect_h
#include <spine/SpineObject.h>
#include <spine/MathUtil.h>
namespace Spine {
class Skeleton;
class Color;
class VertexEffect: public SpineObject {
public:
virtual void begin(Skeleton& skeleton) = 0;
virtual void transform(float& x, float& y, float &u, float &v, Color &light, Color &dark) = 0;
virtual void end() = 0;
};
class JitterVertexEffect: public VertexEffect {
public:
JitterVertexEffect(float jitterX, float jitterY);
void begin(Skeleton& skeleton);
void transform(float& x, float& y, float &u, float &v, Color &light, Color &dark);
void end();
void setJitterX(float jitterX);
float getJitterX();
void setJitterY(float jitterY);
float getJitterY();
protected:
float _jitterX;
float _jitterY;
};
class SwirlVertexEffect: public VertexEffect {
public:
SwirlVertexEffect(float radius, Interpolation &interpolation);
void begin(Skeleton& skeleton);
void transform(float& x, float& y, float &u, float &v, Color &light, Color &dark);
void end();
void setCenterX(float centerX);
float getCenterX();
void setCenterY(float centerY);
float getCenterY();
void setRadius(float radius);
float getRadius();
void setAngle(float angle);
float getAngle();
void setWorldX(float worldX);
float getWorldX();
void setWorldY(float worldY);
float getWorldY();
protected:
float _centerX;
float _centerY;
float _radius;
float _angle;
float _worldX;
float _worldY;
Interpolation& _interpolation;
};
}
#endif /* Spine_VertexEffect_h */

View File

@ -105,6 +105,7 @@
#include <spine/Updatable.h>
#include <spine/Vector.h>
#include <spine/VertexAttachment.h>
#include <spine/VertexEffect.h>
#include <spine/Vertices.h>
#endif

View File

@ -31,7 +31,8 @@
#include <spine/MathUtil.h>
#include <math.h>
namespace Spine {
using namespace Spine;
float MathUtil::abs(float v) {
return ((v) < 0 ? -(v) : (v));
}
@ -91,4 +92,22 @@ static bool _isNan(float value, float zero) {
bool MathUtil::isNan(float v) {
return _isNan(v, 0);
}
float MathUtil::random() {
return ::rand() / (float)RAND_MAX;
}
float MathUtil::randomTriangular(float min, float max) {
return randomTriangular(min, max, (min + max) * 0.5f);
}
float MathUtil::randomTriangular(float min, float max, float mode) {
float u = random();
float d = max - min;
if (u <= (mode - min) / d) return min + sqrt(u * d * (mode - min));
return max - sqrt((1 - u) * d * (max - mode));
}
float MathUtil::pow(float a, float b) {
return ::pow(a, b);
}

View File

@ -84,7 +84,7 @@ void PathConstraint::update() {
return;
}
PathConstraintData data = _data;
PathConstraintData &data = _data;
SpacingMode spacingMode = data._spacingMode;
bool lengthSpacing = spacingMode == SpacingMode_Length;
RotateMode rotateMode = data._rotateMode;

View File

@ -0,0 +1,146 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/VertexEffect.h>
#include <spine/MathUtil.h>
#include <spine/Skeleton.h>
using namespace Spine;
JitterVertexEffect::JitterVertexEffect(float jitterX, float jitterY): _jitterX(jitterX), _jitterY(jitterY) {
}
void JitterVertexEffect::begin(Skeleton &skeleton) {
}
void JitterVertexEffect::transform(float &x, float &y, float &u, float &v, Color &light, Color &dark) {
float jitterX = _jitterX;
float jitterY = _jitterY;
x += MathUtil::randomTriangular(-jitterX, jitterX);
y += MathUtil::randomTriangular(-jitterX, jitterY);
}
void JitterVertexEffect::end() {
}
void JitterVertexEffect::setJitterX(float jitterX) {
_jitterX = jitterX;
}
float JitterVertexEffect::getJitterX() {
return _jitterX;
}
void JitterVertexEffect::setJitterY(float jitterY) {
_jitterY = jitterY;
}
float JitterVertexEffect::getJitterY() {
return _jitterY;
}
SwirlVertexEffect::SwirlVertexEffect(float radius, Interpolation &interpolation):
_radius(radius),
_interpolation(interpolation),
_centerY(0),
_centerX(0),
_worldX(0),
_worldY(0),
_angle(0) {
}
void SwirlVertexEffect::begin(Skeleton &skeleton) {
_worldX = skeleton.getX() + _centerX;
_worldY = skeleton.getY() + _centerY;
}
void SwirlVertexEffect::transform(float &positionX, float &positionY, float &u, float &v, Color &light, Color &dark) {
float x = positionX - _worldX;
float y = positionY - _worldY;
float dist = (float)MathUtil::sqrt(x * x + y * y);
if (dist < _radius) {
float theta = _interpolation.interpolate(0, _angle, (_radius - dist) / _radius);
float cos = MathUtil::cos(theta), sin = MathUtil::sin(theta);
positionX = cos * x - sin * y + _worldX;
positionY = sin * x + cos * y + _worldY;
}
}
void SwirlVertexEffect::end() {
}
void SwirlVertexEffect::setCenterX(float centerX) {
_centerX = centerX;
}
float SwirlVertexEffect::getCenterX() {
return _centerX;
}
void SwirlVertexEffect::setCenterY(float centerY) {
_centerY = centerY;
}
float SwirlVertexEffect::getCenterY() {
return _centerY;
}
void SwirlVertexEffect::setRadius(float radius) {
_radius = radius;
}
float SwirlVertexEffect::getRadius() {
return _radius;
}
void SwirlVertexEffect::setAngle(float angle) {
_angle = angle * Spine::DEG_RAD;
}
float SwirlVertexEffect::getAngle() {
return _angle;
}
void SwirlVertexEffect::setWorldX(float worldX) {
_worldX = worldX;
}
float SwirlVertexEffect::getWorldX() {
return _worldX;
}
void SwirlVertexEffect::setWorldY(float worldY) {
_worldY = worldY;
}
float SwirlVertexEffect::getWorldY() {
return _worldY;
}

View File

@ -29,11 +29,9 @@
*****************************************************************************/
#include <iostream>
#include <string.h>
#include <spine/spine-sfml.h>
#include <spine/Debug.h>
#include <SFML/Graphics.hpp>
#include <SFML/Window/Mouse.hpp>
using namespace std;
using namespace Spine;
@ -205,9 +203,11 @@ void raptor (SkeletonData* skeletonData, Atlas* atlas) {
SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData);
drawable->timeScale = 1;
// BOZO spSwirlVertexEffect* effect = spSwirlVertexEffect_create(400);
// effect->centerY = -200;
// drawable->vertexEffect = &effect->super;
PowInterpolation pow2(2);
PowOutInterpolation powOut2(2);
SwirlVertexEffect effect(400, powOut2);
effect.setCenterY(-200);
drawable->vertexEffect = &effect;
Skeleton* skeleton = drawable->skeleton;
skeleton->setPosition(320, 590);
@ -231,7 +231,7 @@ void raptor (SkeletonData* skeletonData, Atlas* atlas) {
swirlTime += delta;
float percent = MathUtil::fmod(swirlTime, 2);
if (percent > 1) percent = 1 - (percent - 1);
// BOZO effect->angle = _spMath_interpolate(_spMath_pow2_apply, -60, 60, percent);
effect.setAngle(pow2.interpolate(-60.0f, 60.0f, percent));
drawable->update(delta);
@ -239,7 +239,6 @@ void raptor (SkeletonData* skeletonData, Atlas* atlas) {
window.draw(*drawable);
window.display();
}
// BOZO spSwirlVertexEffect_dispose(effect);
delete drawable;
}
@ -452,6 +451,8 @@ void test (SkeletonData* skeletonData, Atlas* atlas) {
int main () {
DebugExtension dbgExtension;
SpineExtension::setInstance(&dbgExtension);
testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor.atlas", 0.5f);
testcase(test, "data/tank-pro.json", "data/tank-pro.skel", "data/tank.atlas", 1.0f);
testcase(spineboy, "data/spineboy-ess.json", "data/spineboy-ess.skel", "data/spineboy.atlas", 0.6f);
testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl.atlas", 0.5f);

View File

@ -53,7 +53,7 @@ namespace Spine {
SkeletonDrawable::SkeletonDrawable(SkeletonData *skeletonData, AnimationStateData *stateData) :
timeScale(1),
vertexArray(new VertexArray(Triangles, skeletonData->getBones().size() * 4)),
worldVertices(), clipper() {
worldVertices(), clipper(), vertexEffect(NULL) {
Bone::setYDown(true);
worldVertices.ensureCapacity(SPINE_MESH_VERTEX_COUNT_MAX);
skeleton = new(__FILE__, __LINE__) Skeleton(skeletonData);
@ -64,6 +64,13 @@ SkeletonDrawable::SkeletonDrawable(SkeletonData *skeletonData, AnimationStateDat
if (ownsAnimationStateData) stateData = new(__FILE__, __LINE__) AnimationStateData(skeletonData);
state = new(__FILE__, __LINE__) AnimationState(stateData);
quadIndices.add(0);
quadIndices.add(1);
quadIndices.add(2);
quadIndices.add(2);
quadIndices.add(3);
quadIndices.add(0);
}
SkeletonDrawable::~SkeletonDrawable() {
@ -83,15 +90,8 @@ void SkeletonDrawable::update(float deltaTime) {
void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const {
vertexArray->clear();
states.texture = NULL;
Vector<unsigned short> quadIndices;
quadIndices.add(0);
quadIndices.add(1);
quadIndices.add(2);
quadIndices.add(2);
quadIndices.add(3);
quadIndices.add(0);
// BOZO if (vertexEffect != 0) vertexEffect->begin(vertexEffect, skeleton);
if (vertexEffect != NULL) vertexEffect->begin(*skeleton);
sf::Vertex vertex;
Texture *texture = NULL;
@ -206,54 +206,55 @@ void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const {
Vector2u size = texture->getSize();
/* BOZO if (vertexEffect != 0) {
spFloatArray_clear(tempUvs);
spColorArray_clear(tempColors);
if (vertexEffect != 0) {
tempUvs.clear();
tempColors.clear();
for (int i = 0; i < verticesCount; i++) {
spColor vertexColor = light;
spColor dark;
dark.r = dark.g = dark.b = dark.a = 0;
Color vertexColor = light;
Color dark;
dark._r = dark._g = dark._b = dark._a = 0;
int index = i << 1;
float x = vertices[index];
float y = vertices[index + 1];
float u = uvs[index];
float v = uvs[index + 1];
vertexEffect->transform(vertexEffect, &x, &y, &u, &v, &vertexColor, &dark);
vertices[index] = x;
vertices[index + 1] = y;
spFloatArray_add(tempUvs, u);
spFloatArray_add(tempUvs, v);
spColorArray_add(tempColors, vertexColor);
float x = (*vertices)[index];
float y = (*vertices)[index + 1];
float u = (*uvs)[index];
float v = (*uvs)[index + 1];
vertexEffect->transform(x, y, u, v, vertexColor, dark);
(*vertices)[index] = x;
(*vertices)[index + 1] = y;
tempUvs.add(u);
tempUvs.add(v);
tempColors.add(vertexColor);
}
for (int i = 0; i < indicesCount; ++i) {
int index = indices[i] << 1;
vertex.position.x = vertices[index];
vertex.position.y = vertices[index + 1];
vertex.texCoords.x = uvs[index] * size.x;
vertex.texCoords.y = uvs[index + 1] * size.y;
spColor vertexColor = tempColors->items[index >> 1];
vertex.color.r = static_cast<Uint8>(vertexColor.r * 255);
vertex.color.g = static_cast<Uint8>(vertexColor.g * 255);
vertex.color.b = static_cast<Uint8>(vertexColor.b * 255);
vertex.color.a = static_cast<Uint8>(vertexColor.a * 255);
int index = (*indices)[i] << 1;
vertex.position.x = (*vertices)[index];
vertex.position.y = (*vertices)[index + 1];
vertex.texCoords.x = (*uvs)[index] * size.x;
vertex.texCoords.y = (*uvs)[index + 1] * size.y;
Color vertexColor = tempColors[index >> 1];
vertex.color.r = static_cast<Uint8>(vertexColor._r * 255);
vertex.color.g = static_cast<Uint8>(vertexColor._g * 255);
vertex.color.b = static_cast<Uint8>(vertexColor._b * 255);
vertex.color.a = static_cast<Uint8>(vertexColor._a * 255);
vertexArray->append(vertex);
}
} else {
for (int ii = 0; ii < indicesCount; ++ii) {
int index = (*indices)[ii] << 1;
vertex.position.x = (*vertices)[index];
vertex.position.y = (*vertices)[index + 1];
vertex.texCoords.x = (*uvs)[index] * size.x;
vertex.texCoords.y = (*uvs)[index + 1] * size.y;
vertexArray->append(vertex);
}
} else {*/
for (int ii = 0; ii < indicesCount; ++ii) {
int index = (*indices)[ii] << 1;
vertex.position.x = (*vertices)[index];
vertex.position.y = (*vertices)[index + 1];
vertex.texCoords.x = (*uvs)[index] * size.x;
vertex.texCoords.y = (*uvs)[index + 1] * size.y;
vertexArray->append(vertex);
}
clipper.clipEnd(slot);
}
target.draw(*vertexArray, states);
clipper.clipEnd();
// BOZO if (vertexEffect != 0) vertexEffect->end(vertexEffect);
if (vertexEffect != 0) vertexEffect->end();
}
void SFMLTextureLoader::load(AtlasPage &page, const String &path) {

View File

@ -47,6 +47,7 @@ public:
AnimationState *state;
float timeScale;
sf::VertexArray *vertexArray;
VertexEffect* vertexEffect;
SkeletonDrawable(SkeletonData *skeleton, AnimationStateData *stateData = 0);
@ -64,6 +65,7 @@ private:
mutable Vector<float> worldVertices;
mutable Vector<float> tempUvs;
mutable Vector<Color> tempColors;
mutable Vector<unsigned short> quadIndices;
mutable SkeletonClipping clipper;
mutable bool usePremultipliedAlpha;
};