-
Notifications
You must be signed in to change notification settings - Fork 3
/
Sprite3d.hpp
199 lines (155 loc) · 7.48 KB
/
Sprite3d.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
//////////////////////////////////////////////////////////////////////////////
//
// Sprite3d
//
// Copyright (c) 2015 M. J. Silk
//
// 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 acknowledgement 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.
//
// M. J. Silk
// MJSilk2@gmail.com
//
//////////////////////////////////////////////////////////////////////////////
#ifndef HAPAX_SFML_SPRITE3D_HPP
#define HAPAX_SFML_SPRITE3D_HPP
#include <vector>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/System/Vector3.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Sprite.hpp> // to construct from sf::Sprite
namespace sf
{
// Sprite3d version 1.0.0
class Sprite3d : public sf::Drawable, public sf::Transformable
{
public:
// constructors
Sprite3d();
Sprite3d(const sf::Texture& texture); // create from texture
Sprite3d(const sf::Texture& texture, const sf::IntRect& textureRect); // create from texture and texture rectangle
Sprite3d(const sf::Texture& texture, const sf::Texture& backTexture); // create from (front) texture and back texture
Sprite3d(const sf::Texture& texture, const sf::IntRect& textureRect, const sf::Texture& backTexture, sf::Vector2i backTextureOffset = sf::Vector2i()); // create from (front) texture, texture rectangle, back texture, and back texture offset
Sprite3d(const sf::Sprite& sprite); // create from standard sprite (copies texture, texture rectangle and all transformations)
// get a standard sprite formed similarly to sprite3d
const sf::Sprite getSprite() const;
// standard sprite
const sf::Texture* getTexture() const;
sf::IntRect getTextureRect() const;
sf::Color getColor() const;
sf::FloatRect getLocalBounds() const;
sf::FloatRect getGlobalBounds() const;
void setTexture(const sf::Texture& texture, bool resetRect = false, bool resetBackOffset = false);
void setTextureRect(const sf::IntRect& rectangle);
void setColor(const sf::Color& color);
// back face
const sf::Texture* getBackTexture() const;
bool getBackFlipEnabled() const;
sf::Vector2i getTextureOffset() const;
sf::Vector2i getBackTextureOffset() const;
void setBackTexture(const sf::Texture& texture, bool resetOffset = false);
void setBackFlipEnabled(bool flipBack = true);
void setTextureOffset(sf::Vector2i textureOffset = sf::Vector2i());
void setBackTextureOffset(sf::Vector2i backTextureOffset = sf::Vector2i());
// 3D rotation
float getPitch() const;
float getYaw() const;
float getRoll() const;
sf::Vector3f getRotation3d() const;
float getMostExtremeAngle() const; // most extreme angle of pitch and yaw. ranges from 0 to 90
void setPitch(float pitch); // rotation around the x axis
void setYaw(float yaw); // rotation around the y axis
void setRoll(float roll); // rotation around the z axis (this is the usual 2D rotation)
void setRotation(float rotation); // supplied as the 3d rotation method overrides the sf::Transformable rotation method
void setRotation(sf::Vector3f rotation); // set pitch, yaw, and roll at once.
void setRotation3d(sf::Vector3f rotation); // set pitch, yaw, and roll at once.
// mesh setup
unsigned int getMeshDensity() const;
unsigned int getSubdividedMeshDensity() const;
unsigned int getSubdivision() const;
bool getDynamicSubdivisionEnabled() const;
void reserveMeshDensity(unsigned int meshDensity); // allow an expected maximum mesh density to be reserved in advance
void setMeshDensity(unsigned int meshDensity);
void setDynamicSubdivisionEnabled(bool enabled = true);
void setDynamicSubdivisionRange(unsigned int maximum, unsigned int minimum = 0u);
void setSubdivision(const unsigned int subdivision) const; // required to be const to allow dynamic subdivision
void setNumberOfPoints(unsigned int numberOfPoints); // provided for convenience (sets number of points before any subdivision)
void setNumberOfQuads(unsigned int numberOfPoints); // provided for convenience (sets number of apparent quads before any subdivision)
void minimalMesh();
// 3D setup
// depth controls the amount of the apparent depth of the 3D effect.
// higher values give a more extreme depth effect but more visible texture distortion
// higher values give a more subtle depth effect but less visible texture distortion
float getDepth() const;
void setDepth(float depth);
private:
const float m_depthToShallownessConversionNumerator;
float m_pitch;
float m_yaw;
float m_depth; // even though m_shallowness is the one that actually gets used internally, this is stored as a form of cache to return through getDepth() to avoid the unnecessary division in a getter
float m_shallowness;
unsigned int m_meshDensity;
bool m_flipBack; // flips the back's texture coordinates so that it shows the right way around
// texture
const sf::Texture* m_pTexture;
const sf::Texture* m_pBackTexture;
sf::Vector2i m_size;
sf::Vector2i m_textureOffset;
sf::Vector2i m_backTextureOffset;
// for dynamic subdivision based on angle
bool m_useDynamicSubdivision;
unsigned int m_minSubdivision;
unsigned int m_maxSubdivision;
// need to be mutable to allow dynamic subdivision
mutable unsigned int m_subdivision;
mutable unsigned int m_subdividedMeshDensity; // stored as a cache to avoid unnecessary power calculations
mutable std::vector<sf::Vector3f> m_points;
// need to be mutable to allow modification through draw call
mutable std::vector<sf::Vector2f> m_transformedPoints;
mutable sf::Vector3f m_origin;
mutable std::vector<sf::Vertex> m_vertices;
mutable std::vector<float> m_compactTransformMatrix;
mutable bool m_isBackFacing;
// corners' global positions (mutable as they are automatically updated when the points are transformed)
mutable sf::Vector2f m_topLeft;
mutable sf::Vector2f m_topRight;
mutable sf::Vector2f m_bottomLeft;
mutable sf::Vector2f m_bottomRight;
void createPointGrid() const; // needs to be const to allow dynamic subdivision
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
void updateTransformedPoints() const;
void updateVertices() const;
void updateGlobalCorners() const;
unsigned int getPointIndexForVertexIndex(unsigned int vertexIndex, bool invertPointX = false) const;
unsigned int getNumberOfVerticesNeededForCurrentSubdividedMeshDensity() const;
float linearInterpolation(float from, float to, float alpha) const;
float mod(float numerator, float denominator) const;
float min(float a, float b) const;
float max(float a, float b) const;
sf::Vector2i abs(const sf::Vector2i& vector) const;
};
} // namespace sf
#endif // HAPAX_SFML_SPRITE3D_HPP