Add Library

This commit is contained in:
Siwat Sirichai 2019-08-09 09:01:56 +07:00
parent e365b9dbd9
commit 3c47103b39
318 changed files with 56465 additions and 0 deletions

View file

@ -0,0 +1,86 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Entity.h"
class Animation : public Entity
{
public:
int start, end, frameDuration;
int time;
int drawMode;
Animation(Sprites &sprites, int x, int y, int start, int end, int frameDuration, int drawMode = 0)
{
this->x = x;
this->y = y;
this->sprites = &sprites;
this->start = start;
this->end = end;
this->frameDuration = frameDuration;
time = 0;
this->drawMode = drawMode;
}
virtual ~Animation()
{
}
bool act(int dt)
{
time += dt;
return time < (end - start + 1) * frameDuration;
}
/*
void draw(Graphics &g)
{
int current = time / frameDuration + start;
if (drawMode == 0)
this->sprites->drawMix(g, current, this->x, this->y);
else if (drawMode == 1)
this->sprites->drawAdd(g, current, this->x, this->y);
}
*/
static void animationsAct(Animation **animations, int dt, int maxCount = 100)
{
for (int i = 0; i < maxCount; i++)
{
if (animations[i])
if (!animations[i]->act(dt))
{
delete animations[i];
animations[i] = 0;
}
}
}
/*
void animationsDraw(Graphics &g, Animation **animations, int maxCount = 100)
{
for (int i = 0; i < maxCount; i++)
if (animations[i])
if (animations[i])
animations[i]->draw(g);
}
*/
void animationsEmit(Animation **animations, Animation *e, int maxCount = 100)
{
for (int i = 0; i < maxCount; i++)
{
if (!animations[i])
{
animations[i] = e;
return;
}
}
delete e;
}
};

View file

@ -0,0 +1,69 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include <stdlib.h>
#include "TriangleTree.h"
#include "../Tools/Log.h"
template<class Graphics>
class Engine3D
{
public:
typedef typename Graphics::Color Color;
TriangleTree *triangleBuffer;
TriangleTree *triangleRoot;
int trinagleBufferSize;
int triangleCount;
Engine3D(const int initialTrinagleBufferSize = 1)
{
trinagleBufferSize = initialTrinagleBufferSize;
triangleBuffer = (TriangleTree*)malloc(sizeof(TriangleTree) * trinagleBufferSize);
if(!triangleBuffer)
ERROR("Not enough memory for triangleBuffer");
triangleRoot = 0;
triangleCount = 0;
}
void enqueueTriangle(short *v0, short *v1, short *v2, Color color)
{
if (triangleCount >= trinagleBufferSize)
return;
TriangleTree &t = triangleBuffer[triangleCount++];
t.set(v0, v1, v2, color);
if (triangleRoot)
triangleRoot->add(&triangleRoot, t);
else
triangleRoot = &t;
}
void drawTriangleTree(Graphics &g, TriangleTree *t)
{
if (t->left)
drawTriangleTree(g, t->left);
g.triangle(t->v[0], t->v[1], t->v[2], t->color);
if (t->right)
drawTriangleTree(g, t->right);
}
virtual void begin()
{
triangleCount = 0;
triangleRoot = 0;
}
virtual void end(Graphics &g)
{
if (triangleRoot)
drawTriangleTree(g, triangleRoot);
}
};

View file

@ -0,0 +1,26 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Graphics.h"
#include "Sprites.h"
class Entity
{
public:
int x, y;
int vx, vy;
int life;
int faction;
Sprites *sprites;
virtual bool act(int dt);
virtual void draw() = 0;
};

View file

@ -0,0 +1,35 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
class Font
{
public:
const int firstChar;
const int charCount;
const unsigned char *pixels;
const int charWidth;
const int charHeight;
Font(int charWidth, int charHeight, const unsigned char *pixels, int firstChar = 32, int charCount = 96)
:firstChar(firstChar),
charCount(charCount),
pixels(pixels),
charWidth(charWidth),
charHeight(charHeight)
{
}
bool valid(char ch) const
{
return ch >= firstChar && ch < firstChar + charCount;
}
};

View file

@ -0,0 +1,698 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include <stdlib.h>
#include <math.h>
#include "Font.h"
#include "ImageDrawer.h"
template<typename Color>
class Graphics: public ImageDrawer
{
public:
int cursorX, cursorY, cursorBaseX;
long frontColor, backColor;
Font *font;
int frameBufferCount;
int currentFrameBuffer;
Color **frameBuffers[3];
Color **frontBuffer;
Color **backBuffer;
bool autoScroll;
int xres;
int yres;
virtual void dotFast(int x, int y, Color color) = 0;
virtual void dot(int x, int y, Color color) = 0;
virtual void dotAdd(int x, int y, Color color) = 0;
virtual void dotMix(int x, int y, Color color) = 0;
virtual Color get(int x, int y) = 0;
virtual Color** allocateFrameBuffer() = 0;
virtual Color** allocateFrameBuffer(int xres, int yres, Color value)
{
Color** frame = (Color **)malloc(yres * sizeof(Color *));
if(!frame)
ERROR("Not enough memory for frame buffer");
for (int y = 0; y < yres; y++)
{
frame[y] = (Color *)malloc(xres * sizeof(Color));
if(!frame[y])
ERROR("Not enough memory for frame buffer");
for (int x = 0; x < xres; x++)
frame[y][x] = value;
}
return frame;
}
virtual Color RGBA(int r, int g, int b, int a = 255) const = 0;
virtual int R(Color c) const = 0;
virtual int G(Color c) const = 0;
virtual int B(Color c) const = 0;
virtual int A(Color c) const = 0;
Color RGB(unsigned long rgb) const
{
return RGBA(rgb & 255, (rgb >> 8) & 255, (rgb >> 16) & 255);
}
Color RGBA(unsigned long rgba) const
{
return RGBA(rgba & 255, (rgba >> 8) & 255, (rgba >> 16) & 255, rgba >> 24);
}
Color RGB(int r, int g, int b) const
{
return RGBA(r, g, b);
}
void setFrameBufferCount(unsigned char i)
{
frameBufferCount = i > 3 ? 3 : i;
}
virtual void show(bool vSync = false)
{
if(!frameBufferCount)
return;
currentFrameBuffer = (currentFrameBuffer + 1) % frameBufferCount;
frontBuffer = frameBuffers[currentFrameBuffer];
backBuffer = frameBuffers[(currentFrameBuffer + frameBufferCount - 1) % frameBufferCount];
}
Graphics(int xres = 0, int yres = 0)
{
this->xres = xres;
this->yres = yres;
font = 0;
cursorX = cursorY = cursorBaseX = 0;
frontColor = -1;
backColor = 0;
frameBufferCount = 1;
for(int i = 0; i < 3; i++)
frameBuffers[i] = 0;
frontBuffer = 0;
backBuffer = 0;
autoScroll = true;
}
virtual bool allocateFrameBuffers()
{
if(yres <= 0 || xres <= 0)
return false;
for(int i = 0; i < frameBufferCount; i++)
frameBuffers[i] = allocateFrameBuffer();
currentFrameBuffer = 0;
show();
return true;
}
virtual void setResolution(int xres, int yres)
{
this->xres = xres;
this->yres = yres;
allocateFrameBuffers();
}
virtual float pixelAspect() const
{
return 1;
}
void setTextColor(long front, long back = 0)
{
frontColor = front;
backColor = back;
}
void setFont(Font &font)
{
this->font = &font;
}
void setCursor(int x, int y)
{
cursorX = cursorBaseX = x;
cursorY = y;
}
virtual void drawChar(int x, int y, int ch)
{
if (!font)
return;
if (!font->valid(ch))
return;
const unsigned char *pix = &font->pixels[font->charWidth * font->charHeight * (ch - font->firstChar)];
for (int py = 0; py < font->charHeight; py++)
for (int px = 0; px < font->charWidth; px++)
if (*(pix++))
dotMix(px + x, py + y, frontColor);
else
dotMix(px + x, py + y, backColor);
}
void print(const char ch)
{
if (!font)
return;
if (font->valid(ch))
drawChar(cursorX, cursorY, ch);
else
drawChar(cursorX, cursorY, ' ');
cursorX += font->charWidth;
if (cursorX + font->charWidth > xres)
{
cursorX = cursorBaseX;
cursorY += font->charHeight;
if(autoScroll && cursorY + font->charHeight > yres)
scroll(cursorY + font->charHeight - yres, backColor);
}
}
void println(const char ch)
{
print(ch);
print("\n");
}
void print(const char *str)
{
if (!font)
return;
while (*str)
{
if(*str == '\n')
{
cursorX = cursorBaseX;
cursorY += font->charHeight;
}
else
print(*str);
str++;
}
}
void println(const char *str)
{
print(str);
print("\n");
}
void print(long number, int base = 10, int minCharacters = 1)
{
if(minCharacters < 1)
minCharacters = 1;
bool sign = number < 0;
if (sign)
number = -number;
const char baseChars[] = "0123456789ABCDEF";
char temp[33];
temp[32] = 0;
int i = 31;
do
{
temp[i--] = baseChars[number % base];
number /= base;
} while (number > 0);
if (sign)
temp[i--] = '-';
for (; i > 31 - minCharacters; i--)
temp[i] = ' ';
print(&temp[i + 1]);
}
void print(unsigned long number, int base = 10, int minCharacters = 1)
{
if(minCharacters < 1)
minCharacters = 1;
const char baseChars[] = "0123456789ABCDEF";
char temp[33];
temp[32] = 0;
int i = 31;
do
{
temp[i--] = baseChars[number % base];
number /= base;
} while (number > 0);
for (; i > 31 - minCharacters; i--)
temp[i] = ' ';
print(&temp[i + 1]);
}
void println(long number, int base = 10, int minCharacters = 1)
{
print(number, base, minCharacters); print("\n");
}
void println(unsigned long number, int base = 10, int minCharacters = 1)
{
print(number, base, minCharacters); print("\n");
}
void print(int number, int base = 10, int minCharacters = 1)
{
print(long(number), base, minCharacters);
}
void println(int number, int base = 10, int minCharacters = 1)
{
println(long(number), base, minCharacters);
}
void print(unsigned int number, int base = 10, int minCharacters = 1)
{
print((unsigned long)(number), base, minCharacters);
}
void println(unsigned int number, int base = 10, int minCharacters = 1)
{
println((unsigned long)(number), base, minCharacters);
}
void print(short number, int base = 10, int minCharacters = 1)
{
print(long(number), base, minCharacters);
}
void println(short number, int base = 10, int minCharacters = 1)
{
println(long(number), base, minCharacters);
}
void print(unsigned short number, int base = 10, int minCharacters = 1)
{
print(long(number), base, minCharacters);
}
void println(unsigned short number, int base = 10, int minCharacters = 1)
{
println(long(number), base, minCharacters);
}
void print(unsigned char number, int base = 10, int minCharacters = 1)
{
print(long(number), base, minCharacters);
}
void println(unsigned char number, int base = 10, int minCharacters = 1)
{
println(long(number), base, minCharacters);
}
void println()
{
print("\n");
}
void print(double number, int fractionalDigits = 2, int minCharacters = 1)
{
long p = long(pow(10, fractionalDigits));
long long n = (double(number) * p + 0.5f);
print(long(n / p), 10, minCharacters - 1 - fractionalDigits);
if(fractionalDigits)
{
print(".");
for(int i = 0; i < fractionalDigits; i++)
{
p /= 10;
print(long(n / p) % 10);
}
}
}
void println(double number, int fractionalDigits = 2, int minCharacters = 1)
{
print(number, fractionalDigits, minCharacters);
print("\n");
}
virtual void clear(Color color = 0)
{
for (int y = 0; y < yres; y++)
for (int x = 0; x < xres; x++)
dotFast(x, y, color);
}
virtual void xLine(int x0, int x1, int y, Color color)
{
if (y < 0 || y >= yres)
return;
if (x0 > x1)
{
int xb = x0;
x0 = x1;
x1 = xb;
}
if (x0 < 0)
x0 = 0;
if (x1 > xres)
x1 = xres;
for (int x = x0; x < x1; x++)
dotFast(x, y, color);
}
void triangle(short *v0, short *v1, short *v2, Color color)
{
short *v[3] = {v0, v1, v2};
if (v[1][1] < v[0][1])
{
short *vb = v[0];
v[0] = v[1];
v[1] = vb;
}
if (v[2][1] < v[1][1])
{
short *vb = v[1];
v[1] = v[2];
v[2] = vb;
}
if (v[1][1] < v[0][1])
{
short *vb = v[0];
v[0] = v[1];
v[1] = vb;
}
int y = v[0][1];
int xac = v[0][0] << 16;
int xab = v[0][0] << 16;
int xbc = v[1][0] << 16;
int xaci = 0;
int xabi = 0;
int xbci = 0;
if (v[1][1] != v[0][1])
xabi = ((v[1][0] - v[0][0]) << 16) / (v[1][1] - v[0][1]);
if (v[2][1] != v[0][1])
xaci = ((v[2][0] - v[0][0]) << 16) / (v[2][1] - v[0][1]);
if (v[2][1] != v[1][1])
xbci = ((v[2][0] - v[1][0]) << 16) / (v[2][1] - v[1][1]);
for (; y < v[1][1] && y < yres; y++)
{
if (y >= 0)
xLine(xab >> 16, xac >> 16, y, color);
xab += xabi;
xac += xaci;
}
for (; y < v[2][1] && y < yres; y++)
{
if (y >= 0)
xLine(xbc >> 16, xac >> 16, y, color);
xbc += xbci;
xac += xaci;
}
}
void line(int x1, int y1, int x2, int y2, Color color)
{
int x, y, xe, ye;
int dx = x2 - x1;
int dy = y2 - y1;
int dx1 = labs(dx);
int dy1 = labs(dy);
int px = 2 * dy1 - dx1;
int py = 2 * dx1 - dy1;
if (dy1 <= dx1)
{
if (dx >= 0)
{
x = x1;
y = y1;
xe = x2;
}
else
{
x = x2;
y = y2;
xe = x1;
}
dot(x, y, color);
for (int i = 0; x < xe; i++)
{
x = x + 1;
if (px < 0)
{
px = px + 2 * dy1;
}
else
{
if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0))
{
y = y + 1;
}
else
{
y = y - 1;
}
px = px + 2 * (dy1 - dx1);
}
dot(x, y, color);
}
}
else
{
if (dy >= 0)
{
x = x1;
y = y1;
ye = y2;
}
else
{
x = x2;
y = y2;
ye = y1;
}
dot(x, y, color);
for (int i = 0; y < ye; i++)
{
y = y + 1;
if (py <= 0)
{
py = py + 2 * dx1;
}
else
{
if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0))
{
x = x + 1;
}
else
{
x = x - 1;
}
py = py + 2 * (dx1 - dy1);
}
dot(x, y, color);
}
}
}
void fillRect(int x, int y, int w, int h, Color color)
{
if (x < 0)
{
w += x;
x = 0;
}
if (y < 0)
{
h += y;
y = 0;
}
if (x + w > xres)
w = xres - x;
if (y + h > yres)
h = yres - y;
for (int j = y; j < y + h; j++)
for (int i = x; i < x + w; i++)
dotFast(i, j, color);
}
void rect(int x, int y, int w, int h, Color color)
{
fillRect(x, y, w, 1, color);
fillRect(x, y, 1, h, color);
fillRect(x, y + h - 1, w, 1, color);
fillRect(x + w - 1, y, 1, h, color);
}
void circle(int x, int y, int r, Color color)
{
int oxr = r;
for(int i = 0; i < r + 1; i++)
{
int xr = (int)sqrt(r * r - i * i);
xLine(x - oxr, x - xr + 1, y + i, color);
xLine(x + xr, x + oxr + 1, y + i, color);
if(i)
{
xLine(x - oxr, x - xr + 1, y - i, color);
xLine(x + xr, x + oxr + 1, y - i, color);
}
oxr = xr;
}
}
void fillCircle(int x, int y, int r, Color color)
{
for(int i = 0; i < r + 1; i++)
{
int xr = (int)sqrt(r * r - i * i);
xLine(x - xr, x + xr + 1, y + i, color);
if(i)
xLine(x - xr, x + xr + 1, y - i, color);
}
}
void ellipse(int x, int y, int rx, int ry, Color color)
{
if(ry == 0)
return;
int oxr = rx;
float f = float(rx) / ry;
f *= f;
for(int i = 0; i < ry + 1; i++)
{
float s = rx * rx - i * i * f;
int xr = (int)sqrt(s <= 0 ? 0 : s);
xLine(x - oxr, x - xr + 1, y + i, color);
xLine(x + xr, x + oxr + 1, y + i, color);
if(i)
{
xLine(x - oxr, x - xr + 1, y - i, color);
xLine(x + xr, x + oxr + 1, y - i, color);
}
oxr = xr;
}
}
void fillEllipse(int x, int y, int rx, int ry, Color color)
{
if(ry == 0)
return;
float f = float(rx) / ry;
f *= f;
for(int i = 0; i < ry + 1; i++)
{
float s = rx * rx - i * i * f;
int xr = (int)sqrt(s <= 0 ? 0 : s);
xLine(x - xr, x + xr + 1, y + i, color);
if(i)
xLine(x - xr, x + xr + 1, y - i, color);
}
}
virtual void scroll(int dy, Color color)
{
if(dy > 0)
{
for(int d = 0; d < dy; d++)
{
Color *l = backBuffer[0];
for(int i = 0; i < yres - 1; i++)
{
backBuffer[i] = backBuffer[i + 1];
}
backBuffer[yres - 1] = l;
xLine(0, xres, yres - 1, color);
}
}
else
{
for(int d = 0; d < -dy; d++)
{
Color *l = backBuffer[yres - 1];
for(int i = 1; i < yres; i++)
{
backBuffer[i] = backBuffer[i - 1];
}
backBuffer[0] = l;
xLine(0, xres, 0, color);
}
}
cursorY -= dy;
}
virtual Color R5G5B4A2ToColor(unsigned short c)
{
int r = (((c << 1) & 0x3e) * 255 + 1) / 0x3e;
int g = (((c >> 4) & 0x3e) * 255 + 1) / 0x3e;
int b = (((c >> 9) & 0x1e) * 255 + 1) / 0x1e;
int a = (((c >> 13) & 6) * 255 + 1) / 6;
return RGBA(r, g, b, a);
}
virtual Color R2G2B2A2ToColor(unsigned char c)
{
int r = ((int(c) & 3) * 255 + 1) / 3;
int g = (((int(c) >> 2) & 3) * 255 + 1) / 3;
int b = (((int(c) >> 4) & 3) * 255 + 1) / 3;
int a = (((int(c) >> 6) & 3) * 255 + 1) / 3;
return RGBA(r, g, b, a);
}
virtual void imageR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dot(px + x, py + y, R5G5B4A2ToColor(((unsigned short*)image.pixels)[i++]));
}
}
virtual void imageAddR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dotAdd(px + x, py + y, R5G5B4A2ToColor(((unsigned short*)image.pixels)[i++]));
}
}
virtual void imageMixR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dotMix(px + x, py + y, R5G5B4A2ToColor(((unsigned short*)image.pixels)[i++]));
}
}
virtual void imageR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dot(px + x, py + y, R2G2B2A2ToColor(((unsigned char*)image.pixels)[i++]));
}
}
virtual void imageAddR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dotAdd(px + x, py + y, R2G2B2A2ToColor(((unsigned char*)image.pixels)[i++]));
}
}
virtual void imageMixR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dotMix(px + x, py + y, R2G2B2A2ToColor(((unsigned char*)image.pixels)[i++]));
}
}
};

View file

@ -0,0 +1,110 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Graphics.h"
class GraphicsR1G1B1A1: public Graphics<unsigned char>
{
public:
typedef unsigned char Color;
GraphicsR1G1B1A1()
{
frontColor = 0xf;
}
virtual int R(Color c) const
{
return (c & 1) * 255;
}
virtual int G(Color c) const
{
return (c & 2) ? 255 : 0;
}
virtual int B(Color c) const
{
return (c & 4) ? 255 : 0;
}
virtual int A(Color c) const
{
return (c & 8) ? 255 : 0;
}
virtual Color RGBA(int r, int g, int b, int a = 255) const
{
return ((r >> 7) & 1) | ((g >> 6) & 2) | ((b >> 5) & 4) | ((a >> 4) & 8);
}
virtual void dotFast(int x, int y, Color color)
{
if(x & 1)
backBuffer[y][x >> 1] = (backBuffer[y][x >> 1] & 0xf) | (color << 4);
else
backBuffer[y][x >> 1] = (backBuffer[y][x >> 1] & 0xf0) | (color & 0xf);
}
virtual void dot(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
{
if(x & 1)
backBuffer[y][x >> 1] = (backBuffer[y][x >> 1] & 0xf) | (color << 4);
else
backBuffer[y][x >> 1] = (backBuffer[y][x >> 1] & 0xf0) | (color & 0xf);
}
}
virtual void dotAdd(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
{
if(x & 1)
backBuffer[y][x >> 1] = backBuffer[y][x >> 1] | (color << 4);
else
backBuffer[y][x >> 1] = backBuffer[y][x >> 1] | (color & 0xf);
}
}
virtual void dotMix(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres && (color & 8) != 0)
{
if(x & 1)
backBuffer[y][x >> 1] = (backBuffer[y][x >> 1] & 0xf) | (color << 4);
else
backBuffer[y][x >> 1] = (backBuffer[y][x >> 1] & 0xf0) | (color & 0xf);
}
}
virtual Color get(int x, int y)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
{
if(x & 1)
return backBuffer[y][x >> 1] = backBuffer[y][x >> 1] >> 4;
else
return backBuffer[y][x >> 1] = backBuffer[y][x >> 1] & 0xf;
}
return 0;
}
virtual void clear(Color color = 0)
{
for (int y = 0; y < this->yres; y++)
for (int x = 0; x < this->xres / 2; x++)
this->backBuffer[y][x] = color | (color << 4);
}
virtual Color** allocateFrameBuffer()
{
return Graphics<Color>::allocateFrameBuffer(xres / 2, yres, (Color)0);
}
};

View file

@ -0,0 +1,91 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Graphics.h"
class GraphicsR1G1B1A1X2S2Swapped: public Graphics<unsigned char>
{
public:
typedef unsigned char Color;
static const Color RGBAXMask = 0x3f;
Color SBits;
GraphicsR1G1B1A1X2S2Swapped()
{
SBits = 0xc0;
frontColor = 0xf;
}
virtual int R(Color c) const
{
return (c & 1) * 255;
}
virtual int G(Color c) const
{
return (c & 2) ? 255 : 0;
}
virtual int B(Color c) const
{
return (c & 4) ? 255 : 0;
}
virtual int A(Color c) const
{
return (c & 8) ? 255 : 0;
}
virtual Color RGBA(int r, int g, int b, int a = 255) const
{
return ((r >> 7) & 1) | ((g >> 6) & 2) | ((b >> 5) & 4) | ((a >> 4) & 8);
}
virtual void dotFast(int x, int y, Color color)
{
backBuffer[y][x^2] = (color & RGBAXMask) | SBits;
}
virtual void dot(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
backBuffer[y][x^2] = (color & RGBAXMask) | SBits;
}
virtual void dotAdd(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
backBuffer[y][x^2] = backBuffer[y][x^2] | (color & RGBAXMask);
}
virtual void dotMix(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres && (color & 8) != 0)
backBuffer[y][x^2] = (color & RGBAXMask) | SBits;
}
virtual Color get(int x, int y)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
return backBuffer[y][x^2] & RGBAXMask;
return 0;
}
virtual void clear(Color color = 0)
{
for (int y = 0; y < this->yres; y++)
for (int x = 0; x < this->xres; x++)
backBuffer[y][x^2] = (color & RGBAXMask) | SBits;
}
virtual Color** allocateFrameBuffer()
{
return Graphics<Color>::allocateFrameBuffer(xres, yres, (Color)SBits);
}
};

View file

@ -0,0 +1,142 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Graphics.h"
class GraphicsR2G2B2A2: public Graphics<unsigned char>
{
public:
typedef unsigned char Color;
static const Color RGBAXMask = 0x3f;
Color SBits;
GraphicsR2G2B2A2()
{
SBits = 0xc0;
frontColor = 0xff;
}
virtual int R(Color c) const
{
return (((int)c & 3) * 255 + 1) / 3;
}
virtual int G(Color c) const
{
return (((int)(c >> 2) & 3) * 255 + 1) / 3;
}
virtual int B(Color c) const
{
return (((int)(c >> 4) & 3) * 255 + 1) / 3;
}
virtual int A(Color c) const
{
return (((int)(c >> 6) & 3) * 255 + 1) / 3;
}
virtual Color RGBA(int r, int g, int b, int a = 255) const
{
return ((r >> 6) & 0b11) | ((g >> 4) & 0b1100) | ((b >> 2) & 0b110000) | (a & 0b11000000);
}
virtual void dotFast(int x, int y, Color color)
{
backBuffer[y][x] = (color & RGBAXMask) | SBits;
}
virtual void dot(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
backBuffer[y][x] = (color & RGBAXMask) | SBits;
}
virtual void dotAdd(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
{
int c0 = backBuffer[y][x^2];
int c1 = color;
int r = (c0 & 0b11) + (c1 & 0b11);
if(r > 0b11) r = 0b11;
int g = (c0 & 0b1100) + (c1 & 0b1100);
if(g > 0b1100) g = 0b1100;
int b = (c0 & 0b110000) + (c1 & 0b110000);
if(b > 0b110000) b = 0b110000;
backBuffer[y][x] = r | (g & 0b1100) | (b & 0b110000) | SBits;
}
}
virtual void dotMix(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres && (color >> 6) != 0)
{
unsigned int ai = (3 - ((int)color >> 6)) * (65536 / 3);
unsigned int a = 65536 - ai;
unsigned int co = backBuffer[y][x^2];
unsigned int ro = (co & 0b11) * ai;
unsigned int go = (co & 0b1100) * ai;
unsigned int bo = (co & 0b110000) * ai;
unsigned int r = (color & 0b11) * a + ro;
unsigned int g = ((color & 0b1100) * a + go) & 0b11000000000000000000;
unsigned int b = ((color & 0b110000) * a + bo) & 0b1100000000000000000000;
backBuffer[y][x] = ((r | g | b) >> 16) | SBits;
}
}
virtual Color get(int x, int y)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
return backBuffer[y][x] & RGBAXMask;
return 0;
}
virtual void clear(Color color = 0)
{
for (int y = 0; y < this->yres; y++)
for (int x = 0; x < this->xres; x++)
backBuffer[y][x] = (color & RGBAXMask) | SBits;
}
virtual void imageR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dot(px + x, py + y, ((unsigned char*)image.pixels)[i++]);
}
}
virtual void imageAddR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dotAdd(px + x, py + y, ((unsigned char*)image.pixels)[i++]);
}
}
virtual void imageMixR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dotMix(px + x, py + y, ((unsigned char*)image.pixels)[i++]);
}
}
virtual Color** allocateFrameBuffer()
{
return Graphics<Color>::allocateFrameBuffer(xres, yres, (Color)SBits);
}
};

View file

@ -0,0 +1,142 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Graphics.h"
class GraphicsR2G2B2S2Swapped: public Graphics<unsigned char>
{
public:
typedef unsigned char Color;
static const Color RGBAXMask = 0x3f;
Color SBits;
GraphicsR2G2B2S2Swapped()
{
SBits = 0xc0;
frontColor = 0xff;
}
virtual int R(Color c) const
{
return (((int)c & 3) * 255 + 1) / 3;
}
virtual int G(Color c) const
{
return (((int)(c >> 2) & 3) * 255 + 1) / 3;
}
virtual int B(Color c) const
{
return (((int)(c >> 4) & 3) * 255 + 1) / 3;
}
virtual int A(Color c) const
{
return (((int)(c >> 6) & 3) * 255 + 1) / 3;
}
virtual Color RGBA(int r, int g, int b, int a = 255) const
{
return ((r >> 6) & 0b11) | ((g >> 4) & 0b1100) | ((b >> 2) & 0b110000) | (a & 0b11000000);
}
virtual void dotFast(int x, int y, Color color)
{
backBuffer[y][x^2] = (color & RGBAXMask) | SBits;
}
virtual void dot(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
backBuffer[y][x^2] = (color & RGBAXMask) | SBits;
}
virtual void dotAdd(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
{
int c0 = backBuffer[y][x^2];
int c1 = color;
int r = (c0 & 0b11) + (c1 & 0b11);
if(r > 0b11) r = 0b11;
int g = (c0 & 0b1100) + (c1 & 0b1100);
if(g > 0b1100) g = 0b1100;
int b = (c0 & 0b110000) + (c1 & 0b110000);
if(b > 0b110000) b = 0b110000;
backBuffer[y][x^2] = r | (g & 0b1100) | (b & 0b110000) | SBits;
}
}
virtual void dotMix(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres && (color >> 6) != 0)
{
unsigned int ai = (3 - ((int)color >> 6)) * (65536 / 3);
unsigned int a = 65536 - ai;
unsigned int co = backBuffer[y][x^2];
unsigned int ro = (co & 0b11) * ai;
unsigned int go = (co & 0b1100) * ai;
unsigned int bo = (co & 0b110000) * ai;
unsigned int r = (color & 0b11) * a + ro;
unsigned int g = ((color & 0b1100) * a + go) & 0b11000000000000000000;
unsigned int b = ((color & 0b110000) * a + bo) & 0b1100000000000000000000;
backBuffer[y][x^2] = ((r | g | b) >> 16) | SBits;
}
}
virtual Color get(int x, int y)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
return backBuffer[y][x^2] & RGBAXMask;
return 0;
}
virtual void clear(Color color = 0)
{
for (int y = 0; y < this->yres; y++)
for (int x = 0; x < this->xres; x++)
backBuffer[y][x^2] = (color & RGBAXMask) | SBits;
}
virtual void imageR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dot(px + x, py + y, ((unsigned char*)image.pixels)[i++]);
}
}
virtual void imageAddR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dotAdd(px + x, py + y, ((unsigned char*)image.pixels)[i++]);
}
}
virtual void imageMixR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
for (int py = 0; py < srcYres; py++)
{
int i = srcX + (py + srcY) * image.xres;
for (int px = 0; px < srcXres; px++)
dotMix(px + x, py + y, ((unsigned char*)image.pixels)[i++]);
}
}
virtual Color** allocateFrameBuffer()
{
return Graphics<Color>::allocateFrameBuffer(xres, yres, (Color)SBits);
}
};

View file

@ -0,0 +1,108 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Graphics.h"
class GraphicsR5G5B4A2: public Graphics<unsigned short>
{
public:
typedef unsigned short Color;
GraphicsR5G5B4A2()
{
frontColor = 0xffff;
}
virtual int R(Color c) const
{
return (((c << 1) & 0x3e) * 255 + 1) / 0x3e;
}
virtual int G(Color c) const
{
return (((c >> 4) & 0x3e) * 255 + 1) / 0x3e;
}
virtual int B(Color c) const
{
return (((c >> 9) & 0x1e) * 255 + 1) / 0x1e;
}
virtual int A(Color c) const
{
return (((c >> 13) & 6) * 255 + 1) / 6;
}
virtual Color RGBA(int r, int g, int b, int a = 255) const
{
return ((r >> 3) & 0b11111) | ((g << 2) & 0b1111100000) | ((b << 6) & 0b11110000000000) | ((a << 8) & 0xc000);
}
virtual void dotFast(int x, int y, Color color)
{
backBuffer[y][x] = color;
}
virtual void dot(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
backBuffer[y][x] = color;
}
virtual void dotAdd(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
{
int c0 = backBuffer[y][x];
int c1 = color;
int r = (c0 & 0b11111) + (c1 & 0b11111);
if(r > 0b11111) r = 0b11111;
int g = (c0 & 0b1111100000) + (c1 & 0b1111100000);
if(g > 0b1111100000) g = 0b1111100000;
int b = (c0 & 0b11110000000000) + (c1 & 0b11110000000000);
if(b > 0b11110000000000) b = 0b11110000000000;
backBuffer[y][x] = r | (g & 0b1111100000) | (b & 0b11110000000000);
}
}
virtual void dotMix(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres && (color >> 14) != 0)
{
unsigned int ai = (3 - (color >> 14)) * (65536 / 3);
unsigned int a = 65536 - ai;
unsigned int co = backBuffer[y][x];
unsigned int ro = (co & 0b11111) * ai;
unsigned int go = (co & 0b1111100000) * ai;
unsigned int bo = (co & 0b11110000000000) * ai;
unsigned int r = (color & 0b11111) * a + ro;
unsigned int g = ((color & 0b1111100000) * a + go) & 0b11111000000000000000000000;
unsigned int b = ((color & 0b11110000000000) * a + bo) & 0b111100000000000000000000000000;
backBuffer[y][x] = (r | g | b) >> 16;
}
}
virtual Color get(int x, int y)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
return backBuffer[y][x];
return 0;
}
virtual void clear(Color color = 0)
{
for (int y = 0; y < this->yres; y++)
for (int x = 0; x < this->xres; x++)
backBuffer[y][x] = color;
}
virtual Color** allocateFrameBuffer()
{
return Graphics<Color>::allocateFrameBuffer(xres, yres, (Color)0);
}
};

View file

@ -0,0 +1,112 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Graphics.h"
class GraphicsR5G5B4S2Swapped: public Graphics<unsigned short>
{
public:
typedef unsigned short Color;
static const Color RGBMask = 0x3fff;
Color SBits;
GraphicsR5G5B4S2Swapped()
{
SBits = 0xc000;
frontColor = 0xffff;
}
virtual int R(Color c) const
{
return (((c << 1) & 0x3e) * 255 + 1) / 0x3e;
}
virtual int G(Color c) const
{
return (((c >> 4) & 0x3e) * 255 + 1) / 0x3e;
}
virtual int B(Color c) const
{
return (((c >> 9) & 0x1e) * 255 + 1) / 0x1e;
}
virtual int A(Color c) const
{
return (((c >> 13) & 6) * 255 + 1) / 6;
}
virtual Color RGBA(int r, int g, int b, int a = 255) const
{
return ((r >> 3) & 0b11111) | ((g << 2) & 0b1111100000) | ((b << 6) & 0b11110000000000) | ((a << 8) & 0xc000);
}
virtual void dotFast(int x, int y, Color color)
{
backBuffer[y][x^1] = (color & RGBMask) | SBits;
}
virtual void dot(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
backBuffer[y][x^1] = (color & RGBMask) | SBits;
}
virtual void dotAdd(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
{
int c0 = backBuffer[y][x^1];
int c1 = color;
int r = (c0 & 0b11111) + (c1 & 0b11111);
if(r > 0b11111) r = 0b11111;
int g = (c0 & 0b1111100000) + (c1 & 0b1111100000);
if(g > 0b1111100000) g = 0b1111100000;
int b = (c0 & 0b11110000000000) + (c1 & 0b11110000000000);
if(b > 0b11110000000000) b = 0b11110000000000;
backBuffer[y][x^1] = r | (g & 0b1111100000) | (b & 0b11110000000000) | SBits;
}
}
virtual void dotMix(int x, int y, Color color)
{
if ((unsigned int)x < xres && (unsigned int)y < yres && (color >> 14) != 0)
{
unsigned int ai = (3 - (color >> 14)) * (65536 / 3);
unsigned int a = 65536 - ai;
unsigned int co = backBuffer[y][x^1];
unsigned int ro = (co & 0b11111) * ai;
unsigned int go = (co & 0b1111100000) * ai;
unsigned int bo = (co & 0b11110000000000) * ai;
unsigned int r = (color & 0b11111) * a + ro;
unsigned int g = ((color & 0b1111100000) * a + go) & 0b11111000000000000000000000;
unsigned int b = ((color & 0b11110000000000) * a + bo) & 0b111100000000000000000000000000;
backBuffer[y][x^1] = ((r | g | b) >> 16) | SBits;
}
}
virtual Color get(int x, int y)
{
if ((unsigned int)x < xres && (unsigned int)y < yres)
return backBuffer[y][x^1] & RGBMask;
return 0;
}
virtual void clear(Color color = 0)
{
for (int y = 0; y < this->yres; y++)
for (int x = 0; x < this->xres; x++)
backBuffer[y][x^1] = (color & RGBMask) | SBits;
}
virtual Color** allocateFrameBuffer()
{
return Graphics<Color>::allocateFrameBuffer(xres, yres, (Color)SBits);
}
};

View file

@ -0,0 +1,52 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
class Image
{
public:
enum PixelFormat
{
R8G8B8A8 = 1,
R1G1B1A1 = 2,
R2G2B2A2 = 3,
R4G4B4A4 = 4,
R5G5B5A1 = 5,
R5G5B4A2 = 6
};
int xres;
int yres;
PixelFormat pixelFormat;
const void *pixels;
void init(int xres, int yres, const void *pixels, PixelFormat pixelFormat)
{
this->xres = xres;
this->yres = yres;
this->pixels = pixels;
this->pixelFormat = pixelFormat;
}
Image(){};
Image(int xres, int yres, const void *pixels, PixelFormat pixelFormat)
{
init(xres, yres, pixels, pixelFormat);
}
/*
Color get(int x, int y) const
{
return pixels[y * xres + x];
}*/
};

View file

@ -0,0 +1,113 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "Image.h"
class ImageDrawer
{
public:
virtual void imageR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
virtual void imageAddR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
virtual void imageMixR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
virtual void imageR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
virtual void imageAddR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
virtual void imageMixR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
void image(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
switch(image.pixelFormat)
{
case Image::R5G5B4A2:
imageR5G5B4A2(image, x, y, srcX, srcY, srcXres, srcYres);
break;
case Image::R2G2B2A2:
imageR2G2B2A2(image, x, y, srcX, srcY, srcXres, srcYres);
break;
default:
break;
}
}
void imageAdd(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
switch(image.pixelFormat)
{
case Image::R5G5B4A2:
imageAddR5G5B4A2(image, x, y, srcX, srcY, srcXres, srcYres);
break;
case Image::R2G2B2A2:
imageAddR2G2B2A2(image, x, y, srcX, srcY, srcXres, srcYres);
break;
default:
break;
}
}
void imageMix(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
{
switch(image.pixelFormat)
{
case Image::R5G5B4A2:
imageMixR5G5B4A2(image, x, y, srcX, srcY, srcXres, srcYres);
break;
case Image::R2G2B2A2:
imageMixR2G2B2A2(image, x, y, srcX, srcY, srcXres, srcYres);
break;
default:
break;
}
}
void image(Image &image, int x, int y)
{
switch(image.pixelFormat)
{
case Image::R5G5B4A2:
imageR5G5B4A2(image, x, y, 0, 0, image.xres, image.yres);
break;
case Image::R2G2B2A2:
imageR2G2B2A2(image, x, y, 0, 0, image.xres, image.yres);
break;
default:
break;
}
}
void imageAdd(Image &image, int x, int y)
{
switch(image.pixelFormat)
{
case Image::R5G5B4A2:
imageAddR5G5B4A2(image, x, y, 0, 0, image.xres, image.yres);
break;
case Image::R2G2B2A2:
imageAddR2G2B2A2(image, x, y, 0, 0, image.xres, image.yres);
break;
default:
break;
}
}
void imageMix(Image &image, int x, int y)
{
switch(image.pixelFormat)
{
case Image::R5G5B4A2:
imageMixR5G5B4A2(image, x, y, 0, 0, image.xres, image.yres);
break;
case Image::R2G2B2A2:
imageMixR2G2B2A2(image, x, y, 0, 0, image.xres, image.yres);
break;
default:
break;
}
}
};

View file

@ -0,0 +1,137 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "../Math/Matrix.h"
#include "Engine3D.h"
#include "../Tools/Log.h"
template <typename Graphics>
class Mesh
{
public:
typedef typename Graphics::Color Color;
int vertexCount;
int edgeCount;
int triangleCount;
const float (*vertices)[3];
const unsigned short (*edges)[2];
const unsigned short (*triangles)[3];
const float (*triangleNormals)[3];
short (*tvertices)[3];
signed char (*tTriNormals)[3];
typedef Color (*triangleShader)(int trinangleNo, short *v0, short *v1, short *v2, const signed char *normal, Color color);
Mesh(int vertCount, const float verts[][3], int edgeCount_ = 0, const unsigned short edges_[][2] = 0, int triCount = 0, const unsigned short tris[][3] = 0, const float triNorms[][3] = 0)
: vertexCount(vertCount),
edgeCount(edgeCount_),
triangleCount(triCount),
vertices(verts),
edges(edges_),
triangles(tris),
triangleNormals(triNorms)
{
tvertices = (short(*)[3])malloc(sizeof(short) * 3 * vertexCount);
if(!tvertices)
ERROR("Not enough memory for vertices");
if (triangleNormals)
{
tTriNormals = (signed char(*)[3])malloc(sizeof(signed char) * 3 * triangleCount);
if(!tTriNormals)
ERROR("Not enough memory for triangle normals");
}
}
~Mesh()
{
delete (tvertices);
}
static Color basicTriangleShader(int trinangleNo, short *v0, short *v1, short *v2, const signed char *normal, Color color)
{
return color;
}
static Color basicTriangleShaderNormals(int trinangleNo, short *v0, short *v1, short *v2, const signed char *normal, Color color)
{
const float scaleN = 1.0f / 127.0f;
const float nx = normal[0] * scaleN;
const float ny = normal[1] * scaleN;
const float nz = normal[2] * scaleN;
const float L[3] = {0, 0, -1};
float NdotL = nx * L[0] + ny * L[1] + nz * L[2];
if(NdotL < 0) NdotL = 0;
return int(NdotL * (color & 0x1f)) | (int(NdotL * ((color >> 5) & 0x1f)) << 5) | (int(NdotL * ((color >> 10) & 0xf)) << 10);
}
void drawTriangles(Engine3D<Graphics> &e, Color color = -1, triangleShader ts = 0)
{
if(ts == 0)
{
if(tTriNormals)
ts = basicTriangleShaderNormals;
else
ts = basicTriangleShader;
}
for (int i = 0; i < triangleCount; i++)
{
short *v0 = tvertices[triangles[i][0]];
short *v1 = tvertices[triangles[i][1]];
short *v2 = tvertices[triangles[i][2]];
int dx1 = v1[0] - v0[0];
int dy1 = v1[1] - v0[1];
int dx2 = v2[0] - v0[0];
int dy2 = v2[1] - v0[1];
if (dx1 * dy2 - dx2 * dy1 < 0)
{
Color c = ts(i, v0, v1, v2, tTriNormals ? tTriNormals[i] : 0, color);
e.enqueueTriangle(tvertices[triangles[i][0]], tvertices[triangles[i][1]], tvertices[triangles[i][2]], c);
}
}
}
void drawEdges(Graphics &g, Color color)
{
for (int i = 0; i < edgeCount; i++)
{
g.line(tvertices[edges[i][0]][0], tvertices[edges[i][0]][1], tvertices[edges[i][1]][0], tvertices[edges[i][1]][1], color);
}
}
void drawVertices(Graphics &g, Color color)
{
for (int i = 0; i < vertexCount; i++)
g.dot(tvertices[i][0], tvertices[i][1], color);
}
void transform(Matrix m, Matrix normTrans = Matrix())
{
for (int i = 0; i < vertexCount; i++)
{
Vector v = m * Vector(vertices[i][0], vertices[i][1], vertices[i][2]);
tvertices[i][0] = v[0] / v[3];
tvertices[i][1] = v[1] / v[3];
tvertices[i][2] = v[2];
}
if (triangleNormals)
for (int i = 0; i < triangleCount; i++)
{
Vector v = normTrans * Vector(triangleNormals[i][0], triangleNormals[i][1], triangleNormals[i][2]);
tTriNormals[i][0] = v[0] * 127;
tTriNormals[i][1] = v[1] * 127;
tTriNormals[i][2] = v[2] * 127;
}
}
};

View file

@ -0,0 +1,108 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
#include "ImageDrawer.h"
#include "Image.h"
class Sprite : public Image
{
public:
typedef Image::PixelFormat PixelFormat;
unsigned char pointCount;
const signed short (*points)[2];
void init(int xres, int yres, const void *pixels, unsigned char pointCount, const signed short points[][2], PixelFormat pixelFormat)
{
static const signed short zeroPoint[][2] = {0, 0};
Image::init(xres, yres, pixels, pixelFormat);
if (pointCount)
{
this->pointCount = pointCount;
this->points = points;
}
else
{
this->pointCount = 1;
this->points = zeroPoint;
}
}
void draw(ImageDrawer &g, int x, int y)
{
g.image(*this, x - points[0][0], y - points[0][1]);
}
void drawMix(ImageDrawer &g, int x, int y)
{
g.imageMix(*this, x - points[0][0], y - points[0][1]);
}
void drawAdd(ImageDrawer &g, int x, int y)
{
g.imageAdd(*this, x - points[0][0], y - points[0][1]);
}
};
class Sprites
{
public:
typedef Image::PixelFormat PixelFormat;
int count;
Sprite *sprites;
Sprites(int count, const void* pixels, const int offsets[], const unsigned short resolutions[][2], const signed short points[][2], const short pointOffsets[], PixelFormat pixelFormat)
{
this->count = count;
this->sprites = new Sprite[count];
for (int i = 0; i < count; i++)
this->sprites[i].init(resolutions[i][0], resolutions[i][1], (unsigned char*)pixels + offsets[i], pointOffsets[i + 1] - pointOffsets[i], &points[pointOffsets[i]], pixelFormat);
}
void draw(ImageDrawer &g, int sprite, int x, int y)
{
sprites[sprite].draw(g, x, y);
}
void drawMix(ImageDrawer &g, int sprite, int x, int y)
{
sprites[sprite].drawMix(g, x, y);
}
void drawAdd(ImageDrawer &g, int sprite, int x, int y)
{
sprites[sprite].drawAdd(g, x, y);
}
int xres(int sprite) const
{
return sprites[sprite].xres;
}
int yres(int sprite) const
{
return sprites[sprite].yres;
}
const short (*points(int sprite) const)[2]
{
return sprites[sprite].points;
}
const short *point(int sprite, int point) const
{
return sprites[sprite].points[point];
}
/*unsigned short get(int sprite, int x, int y) const
{
return sprites[sprite].get(x, y);
}*/
};

View file

@ -0,0 +1,126 @@
/*
Author: bitluni 2019
License:
Creative Commons Attribution ShareAlike 4.0
https://creativecommons.org/licenses/by-sa/4.0/
For further details check out:
https://youtube.com/bitlunislab
https://github.com/bitluni
http://bitluni.net
*/
#pragma once
class TriangleTree
{
public:
short *v[3];
int z;
TriangleTree *left, *right;
int depth;
long color;
void set(short *v0, short *v1, short *v2, long color)
{
v[0] = v0;
v[1] = v1;
v[2] = v2;
z = v[0][2] + v[1][2] + v[2][2];
this->color = color;
left = right = 0;
depth = 1;
}
int leftDepth() const
{
return left ? left->depth : 0;
}
int rightDepth() const
{
return right ? right->depth : 0;
}
void recalcDepth()
{
int l = leftDepth();
int r = rightDepth();
depth = l > r ? l : r;
}
int add(TriangleTree **origin, TriangleTree &t)
{
int d = 1;
if (t.z < z)
{
if (left)
d = left->add(&left, t);
else
left = &t;
}
else
{
if (right)
d = right->add(&right, t);
else
right = &t;
}
if (depth < d + 1)
depth = d + 1;
int l = leftDepth();
int r = rightDepth();
if (l > r + 1)
{
int ll = left->leftDepth();
int lr = left->rightDepth();
if (ll < lr)
{
TriangleTree *tl = left;
left = tl->right;
tl->right = left->left;
left->left = tl;
left->left->recalcDepth();
left->recalcDepth();
ll = left->leftDepth();
lr = left->rightDepth();
l = leftDepth();
recalcDepth();
}
{
*origin = left;
left = left->right;
(*origin)->right = this;
depth = lr > r ? lr + 1 : r + 1;
(*origin)->depth = ll > depth ? ll + 1 : depth + 1;
return (*origin)->depth + 1;
}
}
if (r > l + 1)
{
int rl = right->leftDepth();
int rr = right->rightDepth();
if (rr < rl)
{
TriangleTree *tr = right;
right = tr->left;
tr->left = right->right;
right->right = tr;
right->right->recalcDepth();
right->recalcDepth();
rr = right->rightDepth();
rl = right->leftDepth();
r = rightDepth();
recalcDepth();
}
{
*origin = right;
right = right->left;
(*origin)->left = this;
depth = rl > l ? rl + 1 : l + 1;
(*origin)->depth = rr > depth ? rr + 1 : depth + 1;
return (*origin)->depth + 1;
}
}
return depth;
}
};