瀏覽代碼

[cpp] Added VertexEffect.

badlogic 7 年之前
父節點
當前提交
e4a029e1a7

+ 40 - 0
spine-cpp/spine-cpp/include/spine/MathUtil.h

@@ -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 */

+ 106 - 0
spine-cpp/spine-cpp/include/spine/VertexEffect.h

@@ -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 */

+ 1 - 0
spine-cpp/spine-cpp/include/spine/spine.h

@@ -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

+ 20 - 1
spine-cpp/spine-cpp/src/spine/MathUtil.cpp

@@ -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);
 }

+ 1 - 1
spine-cpp/spine-cpp/src/spine/PathConstraint.cpp

@@ -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;

+ 146 - 0
spine-cpp/spine-cpp/src/spine/VertexEffect.cpp

@@ -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;
+}

+ 8 - 7
spine-sfml/cpp/example/main.cpp

@@ -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);

+ 45 - 44
spine-sfml/cpp/src/spine/spine-sfml.cpp

@@ -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) {

+ 2 - 0
spine-sfml/cpp/src/spine/spine-sfml.h

@@ -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;
 };