219 lines
6 KiB
C++
219 lines
6 KiB
C++
/*
|
|
* Aurora: https://github.com/pixelmatix/aurora
|
|
* Copyright (c) 2014 Jason Coon
|
|
*
|
|
* Portions of this code are adapted from Noel Bundy's work: https://github.com/TwystNeko/Object3d
|
|
* Copyright (c) 2014 Noel Bundy
|
|
*
|
|
* Portions of this code are adapted from the Petty library: https://code.google.com/p/peggy/
|
|
* Copyright (c) 2008 Windell H Oskay. All right reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
* this software and associated documentation files (the "Software"), to deal in
|
|
* the Software without restriction, including without limitation the rights to
|
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
* subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#ifndef PatternCube_H
|
|
#define PatternCube_H
|
|
|
|
class PatternCube : public Drawable {
|
|
private:
|
|
float focal = 30; // Focal of the camera
|
|
int cubeWidth = 28; // Cube size
|
|
float Angx = 20.0, AngxSpeed = 0.05; // rotation (angle+speed) around X-axis
|
|
float Angy = 10.0, AngySpeed = 0.05; // rotation (angle+speed) around Y-axis
|
|
float Ox = 15.5, Oy = 15.5; // position (x,y) of the frame center
|
|
int zCamera = 110; // distance from cube to the eye of the camera
|
|
|
|
// Local vertices
|
|
Vertex local[8];
|
|
// Camera aligned vertices
|
|
Vertex aligned[8];
|
|
// On-screen projected vertices
|
|
Point screen[8];
|
|
// Faces
|
|
squareFace face[6];
|
|
// Edges
|
|
EdgePoint edge[12];
|
|
int nbEdges;
|
|
// ModelView matrix
|
|
float m00, m01, m02, m10, m11, m12, m20, m21, m22;
|
|
|
|
// constructs the cube
|
|
void make(int w)
|
|
{
|
|
nbEdges = 0;
|
|
|
|
local[0].set(-w, w, w);
|
|
local[1].set(w, w, w);
|
|
local[2].set(w, -w, w);
|
|
local[3].set(-w, -w, w);
|
|
local[4].set(-w, w, -w);
|
|
local[5].set(w, w, -w);
|
|
local[6].set(w, -w, -w);
|
|
local[7].set(-w, -w, -w);
|
|
|
|
face[0].set(1, 0, 3, 2);
|
|
face[1].set(0, 4, 7, 3);
|
|
face[2].set(4, 0, 1, 5);
|
|
face[3].set(4, 5, 6, 7);
|
|
face[4].set(1, 2, 6, 5);
|
|
face[5].set(2, 3, 7, 6);
|
|
|
|
int f, i;
|
|
for (f = 0; f < 6; f++)
|
|
{
|
|
for (i = 0; i < face[f].length; i++)
|
|
{
|
|
face[f].ed[i] = this->findEdge(face[f].sommets[i], face[f].sommets[i ? i - 1 : face[f].length - 1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// finds edges from faces
|
|
int findEdge(int a, int b)
|
|
{
|
|
int i;
|
|
for (i = 0; i < nbEdges; i++)
|
|
if ((edge[i].x == a && edge[i].y == b) || (edge[i].x == b && edge[i].y == a))
|
|
return i;
|
|
edge[nbEdges++].set(a, b);
|
|
return i;
|
|
}
|
|
|
|
// rotates according to angle x&y
|
|
void rotate(float angx, float angy)
|
|
{
|
|
int i;
|
|
float cx = cos(angx);
|
|
float sx = sin(angx);
|
|
float cy = cos(angy);
|
|
float sy = sin(angy);
|
|
|
|
m00 = cy;
|
|
m01 = 0;
|
|
m02 = -sy;
|
|
m10 = sx * sy;
|
|
m11 = cx;
|
|
m12 = sx * cy;
|
|
m20 = cx * sy;
|
|
m21 = -sx;
|
|
m22 = cx * cy;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
aligned[i].x = m00 * local[i].x + m01 * local[i].y + m02 * local[i].z;
|
|
aligned[i].y = m10 * local[i].x + m11 * local[i].y + m12 * local[i].z;
|
|
aligned[i].z = m20 * local[i].x + m21 * local[i].y + m22 * local[i].z + zCamera;
|
|
|
|
screen[i].x = floor((Ox + focal * aligned[i].x / aligned[i].z));
|
|
screen[i].y = floor((Oy - focal * aligned[i].y / aligned[i].z));
|
|
}
|
|
|
|
for (i = 0; i < 12; i++)
|
|
edge[i].visible = false;
|
|
|
|
Point *pa, *pb, *pc;
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
pa = screen + face[i].sommets[0];
|
|
pb = screen + face[i].sommets[1];
|
|
pc = screen + face[i].sommets[2];
|
|
|
|
boolean back = ((pb->x - pa->x) * (pc->y - pa->y) - (pb->y - pa->y) * (pc->x - pa->x)) < 0;
|
|
if (!back)
|
|
{
|
|
int j;
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
edge[face[i].ed[j]].visible = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
byte hue = 0;
|
|
int step = 0;
|
|
|
|
public:
|
|
PatternCube() {
|
|
name = (char *)"Cube";
|
|
make(cubeWidth);
|
|
}
|
|
|
|
unsigned int drawFrame() {
|
|
uint8_t blurAmount = beatsin8(2, 10, 255);
|
|
|
|
#if FASTLED_VERSION >= 3001000
|
|
blur2d(effects.leds, VPANEL_W, VPANEL_H, blurAmount);
|
|
#else
|
|
effects.DimAll(blurAmount); effects.ShowFrame();
|
|
#endif
|
|
|
|
zCamera = beatsin8(2, 100, 140);
|
|
AngxSpeed = beatsin8(3, 1, 10) / 100.0f;
|
|
AngySpeed = beatcos8(5, 1, 10) / 100.0f;
|
|
|
|
// Update values
|
|
Angx += AngxSpeed;
|
|
Angy += AngySpeed;
|
|
if (Angx >= TWO_PI)
|
|
Angx -= TWO_PI;
|
|
if (Angy >= TWO_PI)
|
|
Angy -= TWO_PI;
|
|
|
|
rotate(Angx, Angy);
|
|
|
|
// Draw cube
|
|
int i;
|
|
|
|
CRGB color = effects.ColorFromCurrentPalette(hue, 128);
|
|
|
|
// Backface
|
|
EdgePoint *e;
|
|
for (i = 0; i < 12; i++)
|
|
{
|
|
e = edge + i;
|
|
if (!e->visible) {
|
|
matrix.drawLine(screen[e->x].x, screen[e->x].y, screen[e->y].x, screen[e->y].y, color);
|
|
}
|
|
}
|
|
|
|
color = effects.ColorFromCurrentPalette(hue, 255);
|
|
|
|
// Frontface
|
|
for (i = 0; i < 12; i++)
|
|
{
|
|
e = edge + i;
|
|
if (e->visible)
|
|
{
|
|
matrix.drawLine(screen[e->x].x, screen[e->x].y, screen[e->y].x, screen[e->y].y, color);
|
|
}
|
|
}
|
|
|
|
step++;
|
|
if (step == 8) {
|
|
step = 0;
|
|
hue++;
|
|
}
|
|
|
|
effects.ShowFrame();
|
|
|
|
return 20;
|
|
}
|
|
};
|
|
|
|
#endif
|