You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
440 lines
13 KiB
440 lines
13 KiB
#pragma once
|
|
|
|
#include "CELLMath.hpp"
|
|
|
|
#include "Image.hpp"
|
|
|
|
namespace CELL
|
|
{
|
|
enum DRAWMODE
|
|
{
|
|
DM_POINTS = 0,
|
|
DM_LINES = 1,
|
|
DM_LINE_LOOP = 2,
|
|
DM_LINE_STRIP = 3,
|
|
DM_TRIANGES = 4,
|
|
};
|
|
|
|
enum DATETYPE
|
|
{
|
|
DT_BYTE,
|
|
DT_FLOAT,
|
|
DT_DOUBLE,
|
|
};
|
|
|
|
struct DateElementDes
|
|
{
|
|
int _size;
|
|
DATETYPE _type;
|
|
int _stride;
|
|
const void* _data;
|
|
};
|
|
|
|
class Span
|
|
{
|
|
public:
|
|
int _xStart;
|
|
int _xEnd;
|
|
Rgba _colorStart;
|
|
Rgba _colorEnd;
|
|
|
|
float2 _uvStart;
|
|
float2 _uvEnd;
|
|
|
|
int _y;
|
|
|
|
public:
|
|
Span(int xStart,int xEnd,int y,Rgba colorStart,Rgba colorEnd,float2 uvStart,float2 uvEnd)
|
|
{
|
|
if (xStart < xEnd)
|
|
{
|
|
_xStart = xStart;
|
|
_xEnd = xEnd;
|
|
_colorStart = colorStart;
|
|
_colorEnd = colorEnd;
|
|
|
|
_uvStart = uvStart;
|
|
_uvEnd = uvEnd;
|
|
|
|
_y = y;
|
|
}
|
|
else
|
|
{
|
|
_xStart = xEnd;
|
|
_xEnd = xStart;
|
|
|
|
_colorStart = colorEnd;
|
|
_colorEnd = colorStart;
|
|
|
|
_uvStart = uvEnd;
|
|
_uvEnd = uvStart;
|
|
_y = y;
|
|
}
|
|
}
|
|
};
|
|
|
|
class Ege
|
|
{
|
|
public:
|
|
int _x1;
|
|
int _y1;
|
|
float2 _uv1;
|
|
Rgba _color1;
|
|
|
|
int _x2;
|
|
int _y2;
|
|
float2 _uv2;
|
|
Rgba _color2;
|
|
|
|
Ege(int x1,int y1,Rgba color1,float2 uv1,int x2,int y2,Rgba color2,float2 uv2)
|
|
{
|
|
if (y1 < y2)
|
|
{
|
|
_x1 = x1;
|
|
_y1 = y1;
|
|
_uv1 = uv1;
|
|
_color1 = color1;
|
|
|
|
_x2 = x2;
|
|
_y2 = y2;
|
|
_uv2 = uv2;
|
|
_color2 = color2;
|
|
}
|
|
else
|
|
{
|
|
_x1 = x2;
|
|
_y1 = y2;
|
|
_uv1 = uv2;
|
|
_color1 = color2;
|
|
|
|
_x2 = x1;
|
|
_y2 = y1;
|
|
_uv2 = uv1;
|
|
_color2 = color1;
|
|
}
|
|
}
|
|
};
|
|
class Raster
|
|
{
|
|
public:
|
|
uint* _buffer;
|
|
int _width;
|
|
int _height;
|
|
Rgba _color;
|
|
|
|
Image* _texture;
|
|
|
|
matrix3 _matModel;
|
|
|
|
DateElementDes _poitionPointer;
|
|
DateElementDes _colorPointer;
|
|
DateElementDes _uvPointer;
|
|
|
|
DateElementDes _defaultColorPointer;
|
|
DateElementDes _defaultUVPointer;
|
|
Rgba _defaultColorArray[3];
|
|
float2 _detaultUVArray[3];
|
|
|
|
|
|
|
|
public:
|
|
Raster(int w,int h,void* buffer);
|
|
~Raster(void);
|
|
|
|
void clear();
|
|
|
|
struct Vertex
|
|
{
|
|
int2 p0;
|
|
float2 uv0;
|
|
Rgba c0;
|
|
|
|
int2 p1;
|
|
float2 uv1;
|
|
Rgba c1;
|
|
|
|
int2 p2;
|
|
float2 uv2;
|
|
Rgba c2;
|
|
|
|
};
|
|
|
|
void drawImage(int startX,int startY,const Image* image)
|
|
{
|
|
int left = tmax<int>(startX,0);
|
|
int top = tmax<int>(startY,0);
|
|
|
|
int right = tmin<int>(startX + image->width(),_width);
|
|
int bottom = tmin<int>(startY + image->height(),_height);
|
|
|
|
for (int x = left ; x < right ; ++ x)
|
|
{
|
|
for (int y = top ; y < bottom ; ++ y)
|
|
{
|
|
Rgba color = image->pixelAt(x - left,y - top);
|
|
setPixelEx(x,y,color);
|
|
}
|
|
}
|
|
}
|
|
public:
|
|
|
|
/**
|
|
* ¾ØÕó²Ù×÷º¯Êý
|
|
*/
|
|
|
|
void loadMatrix(const CELL::matrix3& mat)
|
|
{
|
|
_matModel = mat;
|
|
}
|
|
|
|
void loadIdentity()
|
|
{
|
|
_matModel = CELL::matrix3(1);
|
|
}
|
|
|
|
void vertexPointer(int size,DATETYPE type,int stride,const void* data)
|
|
{
|
|
_poitionPointer._size = size;
|
|
_poitionPointer._type = type;
|
|
_poitionPointer._stride = stride;
|
|
_poitionPointer._data = data;
|
|
}
|
|
|
|
void colorPointer(int size,DATETYPE type,int stride,const void* data)
|
|
{
|
|
_colorPointer._size = size;
|
|
_colorPointer._type = type;
|
|
_colorPointer._stride = stride;
|
|
_colorPointer._data = data;
|
|
}
|
|
|
|
void textureCoordPointer(int size,DATETYPE type,int stride,const void* data)
|
|
{
|
|
_uvPointer._size = size;
|
|
_uvPointer._type = type;
|
|
_uvPointer._stride = stride;
|
|
_uvPointer._data = data;
|
|
}
|
|
|
|
void bindTexture(Image* image)
|
|
{
|
|
_texture = image;
|
|
}
|
|
|
|
void drawArrays(DRAWMODE pri,int start,int count)
|
|
{
|
|
if (_poitionPointer._data == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
DateElementDes colorPointerdesc = _colorPointer;
|
|
DateElementDes uvPointerdesc = _uvPointer;
|
|
if (colorPointerdesc._data == 0)
|
|
{
|
|
colorPointerdesc = _defaultColorPointer;
|
|
}
|
|
if (uvPointerdesc._data == 0)
|
|
{
|
|
uvPointerdesc = _defaultUVPointer;
|
|
}
|
|
char* posData = (char*)_poitionPointer._data;
|
|
char* cData = (char*)colorPointerdesc._data;
|
|
char* uvData = (char*)uvPointerdesc._data;
|
|
|
|
for(int i = start ;i < start + count; i += 3)
|
|
{
|
|
float* fData = (float*)posData;
|
|
float3 p01 (fData[0],fData[1],1);
|
|
|
|
posData += _poitionPointer._stride;
|
|
fData = (float*)(posData);
|
|
p01 = _matModel * p01;
|
|
|
|
float3 p11 (fData[0],fData[1],1);
|
|
posData += _poitionPointer._stride;
|
|
fData = (float*)(posData);
|
|
p11 = _matModel * p11;
|
|
|
|
float3 p21 (fData[0],fData[1],1);
|
|
posData += _poitionPointer._stride;
|
|
p21 = _matModel * p21;
|
|
|
|
int2 p0(p01.x,p01.y);
|
|
int2 p1(p11.x,p11.y);
|
|
int2 p2(p21.x,p21.y);
|
|
|
|
Rgba* pColor = (Rgba*)cData;
|
|
Rgba c0 (*pColor);
|
|
cData += _colorPointer._stride;
|
|
Rgba c1 (*pColor);
|
|
cData += _colorPointer._stride;
|
|
Rgba c2 (*pColor);
|
|
cData += _colorPointer._stride;
|
|
|
|
float* pUV = (float*)uvData;
|
|
float2 uv0 (pUV[0],pUV[1]);
|
|
uvData += _uvPointer._stride;
|
|
pUV = (float*)uvData;
|
|
float2 uv1(pUV[0],pUV[1]);
|
|
uvData += _uvPointer._stride;
|
|
pUV = (float*)uvData;
|
|
float2 uv2(pUV[0],pUV[1]);
|
|
uvData += _uvPointer._stride;
|
|
|
|
|
|
Ege eges[3] =
|
|
{
|
|
Ege(p0.x,p0.y,c0, uv0, p1.x,p1.y,c1, uv1),
|
|
Ege(p1.x,p1.y,c1, uv1, p2.x,p2.y,c2, uv2),
|
|
Ege(p2.x,p2.y,c2, uv2, p0.x,p0.y,c0, uv0),
|
|
};
|
|
drawTrianle(eges);
|
|
|
|
if (_colorPointer._data == 0)
|
|
{
|
|
cData = (char*)colorPointerdesc._data;
|
|
}
|
|
if (_uvPointer._data == 0 )
|
|
{
|
|
|
|
uvData = (char*)uvPointerdesc._data;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void drawTrianle(Ege eges[3])
|
|
{
|
|
int iMax = 0;
|
|
int length = eges[0]._y2 - eges[0]._y1;
|
|
|
|
for (int i = 1 ;i < 3 ; ++ i)
|
|
{
|
|
int len = eges[i]._y2 - eges[i]._y1;
|
|
if (len > length)
|
|
{
|
|
length = len;
|
|
iMax = i;
|
|
}
|
|
}
|
|
int iShort1 = (iMax + 1)%3;
|
|
int iShort2 = (iMax + 2)%3;
|
|
|
|
drawEge(eges[iMax],eges[iShort1],_texture);
|
|
drawEge(eges[iMax],eges[iShort2],_texture);
|
|
}
|
|
void drawTriangle(const Vertex& vertex,Image* image)
|
|
{
|
|
Ege eges[3] =
|
|
{
|
|
Ege(vertex.p0.x,vertex.p0.y,vertex.c0, vertex.uv0, vertex.p1.x,vertex.p1.y,vertex.c1, vertex.uv1),
|
|
Ege(vertex.p1.x,vertex.p1.y,vertex.c1, vertex.uv1, vertex.p2.x,vertex.p2.y,vertex.c2, vertex.uv2),
|
|
Ege(vertex.p2.x,vertex.p2.y,vertex.c2, vertex.uv2, vertex.p0.x,vertex.p0.y,vertex.c0, vertex.uv0),
|
|
};
|
|
int iMax = 0;
|
|
int length = eges[0]._y2 - eges[0]._y1;
|
|
|
|
for (int i = 1 ;i < 3 ; ++ i)
|
|
{
|
|
int len = eges[i]._y2 - eges[i]._y1;
|
|
if (len > length)
|
|
{
|
|
length = len;
|
|
iMax = i;
|
|
}
|
|
}
|
|
int iShort1 = (iMax + 1)%3;
|
|
int iShort2 = (iMax + 2)%3;
|
|
|
|
drawEge(eges[iMax],eges[iShort1],image);
|
|
drawEge(eges[iMax],eges[iShort2],image);
|
|
|
|
}
|
|
|
|
void drawEge(const Ege& e1,const Ege& e2,Image* image)
|
|
{
|
|
float yOffset1 = e1._y2 - e1._y1;
|
|
if (yOffset1 == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float yOffset = e2._y2 - e2._y1;
|
|
if (yOffset == 0)
|
|
{
|
|
return;
|
|
}
|
|
float xOffset = e2._x2 - e2._x1;
|
|
float scale = 0;
|
|
float step = 1.0f/yOffset;
|
|
|
|
|
|
float xOffset1 = e1._x2 - e1._x1;
|
|
float scale1 = (float)(e2._y1 - e1._y1)/yOffset1;
|
|
float step1 = 1.0f/yOffset1;
|
|
|
|
for (int y = e2._y1 ; y < e2._y2 ; ++ y)
|
|
{
|
|
int x1 = e1._x1 + (int)(scale1 * xOffset1);
|
|
int x2 = e2._x1 + (int)(scale * xOffset);
|
|
Rgba color2 = colorLerp(e2._color1,e2._color2,scale);
|
|
Rgba color1 = colorLerp(e1._color1,e1._color2,scale1);
|
|
|
|
float2 uvStart = uvLerp(e1._uv1,e1._uv2,scale1);
|
|
float2 uvEnd = uvLerp(e2._uv1,e2._uv2,scale);
|
|
|
|
Span span(x1,x2,y,color1,color2,uvStart,uvEnd);
|
|
drawSpan(span,image);
|
|
|
|
scale += step;
|
|
scale1 += step1;
|
|
|
|
}
|
|
}
|
|
|
|
void drawSpan(const Span& span,Image* image)
|
|
{
|
|
float length = span._xEnd - span._xStart;
|
|
float scale = 0;
|
|
float step = 1.0f/length;
|
|
for (int x = span._xStart ; x < span._xEnd; ++ x)
|
|
{
|
|
//Rgba color = colorLerp(span._colorStart,span._colorEnd,scale);
|
|
|
|
float2 uv = uvLerp(span._uvStart,span._uvEnd,scale);
|
|
|
|
Rgba pixel = image->pixelUV(uv.x,uv.y);
|
|
|
|
//Rgba dst = color + pixel;
|
|
scale += step;
|
|
|
|
setPixel(x,span._y,pixel);
|
|
}
|
|
}
|
|
void drawLine(float2 pt1,float2 pt2,Rgba color1,Rgba color2);
|
|
|
|
void drawPoints(float2 pt1,Rgba4Byte color)
|
|
{
|
|
|
|
}
|
|
inline void setPixelEx(unsigned x,unsigned y,Rgba color)
|
|
{
|
|
_buffer[y * _width + x] = color._color;
|
|
}
|
|
|
|
inline Rgba getPixel(unsigned x,unsigned y)
|
|
{
|
|
return Rgba(_buffer[y * _width + x]);
|
|
}
|
|
inline void setPixel(unsigned x,unsigned y,Rgba color)
|
|
{
|
|
if (x >= _width || y >= _height)
|
|
{
|
|
return;
|
|
}
|
|
_buffer[y * _width + x] = color._color;
|
|
}
|
|
};
|
|
}
|