Evo necega i da se vidi:
Kod za transformisanje iz local u screen:
Code:
// ovo racunam pre poziva funkcije Project
mat4x4 trans = m_matCurrWorldTransform*m_pCamera->GetViewMatrix();
float angle = m_pCamera->m_fFOV*3.14f/180;
m_fD = 0.5*(m_nScreenWidth - 1)*tan(angle/2);
void DEngine::Project(DPoly * pPoly)
{
for(int i=0;i<3;i++)
{
float z = pPoly->m_Vertices[i].GetLocalPos().z;
// ovo bi culling mehanizam odbacio PRE ovog koda ali za sada je ovako
if(z < 1)
z = 1;
vec2 & projected = pPoly->m_Vertices[i].GetScreenPos();
projected.x = m_fD*pPoly->m_Vertices[i].GetTransformedPos().x/z;
projected.y = m_fD*pPoly->m_Vertices[i].GetTransformedPos().y/z;
projected.x = projected.x + (0.5*m_nScreenWidth - 0.5);
projected.y = -projected.y + (0.5*m_nScreenHeight - 0.5);
}
}
kod "rasterajzera"
Code:
#include "DRasterizer.h"
#include "DEngine.h"
DRasterizer::DRasterizer(void)
{
}
DRasterizer::~DRasterizer(void)
{
}
/*
Funkcija koja crta jednobojni trougao u wire mode. Boja je odredjena bojom poligona
*/
void DRasterizer::DrawWireTriangle(DSurface * pSurface, DPoly * pPoly)
{
vec2 v0 = pPoly->m_Vertices[0].GetScreenPos();
vec2 v1 = pPoly->m_Vertices[1].GetScreenPos();
vec2 v2 = pPoly->m_Vertices[2].GetScreenPos();
DrawLine(pSurface, v0.x, v0.y, v1.x, v1.y, pPoly->GetColor().x*255,
pPoly->GetColor().y*255, pPoly->GetColor().z*255);
DrawLine(pSurface, v1.x, v1.y, v2.x, v2.y, pPoly->GetColor().x*255,
pPoly->GetColor().y*255, pPoly->GetColor().z*255);
DrawLine(pSurface, v0.x, v0.y, v2.x, v2.y, pPoly->GetColor().x*255,
pPoly->GetColor().y*255, pPoly->GetColor().z*255);
}
/* Funkcija za crtanje linije */
void DRasterizer::DrawLine(DSurface * pSurface, int x0, int y0, int x1, int y1, Uint8 R, Uint8 G, UINT8 B)
{
int dx = x1 - x0;
int dy = y1 - y0;
int stepx, stepy;
if(dy < 0)
{
dy = -dy;
stepy = -1;
}
else
stepy = 1;
if(dx < 0)
{
dx = -dx;
stepx = -1;
}
else
stepx = 1;
dy <<= 1;
dx <<= 1;
pSurface->PutPixel(x0, y0, R, G, B);
if(dx > dy)
{
int fraction = dy - ( dx >> 1 );
while(x0 != x1)
{
if(fraction >= 0)
{
y0 += stepy;
fraction -= dx;
}
x0 += stepx;
fraction += dy;
pSurface->PutPixel(x0, y0, R, G, B);
}
}
else
{
int fraction = dx - ( dy >> 1 );
while(y0 != y1)
{
if(fraction >= 0)
{
x0 += stepx;
fraction -= dy;
}
y0 += stepy;
fraction += dx;
pSurface->PutPixel(x0, y0, R, G, B);
}
}
}
/* Funkcija koja crta jednobojni trougao*/
void DRasterizer::DrawTriangle(DSurface * pSurface, DPoly * pPoly)
{
float minY, maxY;
int minIndex, midIndex, maxIndex;
int type = -1;
vec2 vers[3];
vers[0] = pPoly->m_Vertices[0].GetScreenPos();
vers[1] = pPoly->m_Vertices[1].GetScreenPos();
vers[2] = pPoly->m_Vertices[2].GetScreenPos();
minY = vers[0].y;
maxY = vers[0].y;
minIndex = maxIndex = 0;
for(int i=1;i<3;i++)
{
if(vers[i].y < minY)
{
minY = vers[i].y;
minIndex = i;
}
if(vers[i].y > maxY)
{
maxY = vers[i].y;
maxIndex = i;
}
}
// klasifikujemo
for(int i=0;i<3;i++)
{
if(i == minIndex)
continue;
if( (int)minY == (int)vers[i].y )
{
type = TRI_TOP_FLAT;
break;
}
}
for(int i=0;i<3;i++)
{
if(i == maxIndex)
continue;
if( (int)maxY == (int)vers[i].y )
{
type = TRI_BOTTOM_FLAT;
break;
}
}
if(type == -1)
type = TRI_COMPLEX;
/*
if(type == TRI_TOP_FLAT)
cout << "Top flat" << endl;
if(type == TRI_BOTTOM_FLAT)
cout << "Bottom flat" << endl;
if(type == TRI_COMPLEX)
cout << "Complex" << endl;
*/
if(type == TRI_BOTTOM_FLAT)
{
DrawPartOfTriangle(pSurface, TRUE, pPoly, minY, maxY, minIndex);
}
if(type == TRI_TOP_FLAT)
{
DrawPartOfTriangle(pSurface, FALSE, pPoly, minY, maxY, maxIndex);
}
if(type == TRI_COMPLEX)
{
int midIndex = 0;
for(int i=0;i<3;i++)
{
if( i == maxIndex || i == minIndex )
continue;
midIndex = i;
}
DrawPartOfTriangle(pSurface, TRUE, pPoly, minY, vers[midIndex].y, minIndex);
DrawPartOfTriangle(pSurface, FALSE, pPoly, vers[midIndex].y, maxY, maxIndex);
}
}
// crta gornji ili donji deo trougla...
// sharpAngleIndex - index verteksa koji je predstavlja "vrh" trougla
void DRasterizer::DrawPartOfTriangle(DSurface * pSurface, bool upper, DPoly * pPoly, float minY, float maxY, int sharpAngleIndex)
{
vec2 vers[3];
// transformisani vertexi local->world->view->projection->screen
vers[0] = pPoly->m_Vertices[0].GetScreenPos();
vers[1] = pPoly->m_Vertices[1].GetScreenPos();
vers[2] = pPoly->m_Vertices[2].GetScreenPos();
if(upper) // draw upper triangle
{
int index = 0;
vec2 bottomPoints[2];
// izdvajamo donje dve tacke
for(int i=0;i<3;i++)
{
if(i == sharpAngleIndex)
continue;
bottomPoints[index] = pPoly->m_Vertices[i].GetScreenPos();
index++;
}
for(float i=minY;i<maxY;i++)
{
// k -
float k1 = (vers[sharpAngleIndex].x - bottomPoints[0].x)/(vers[sharpAngleIndex].y - bottomPoints[0].y);
float k2 = (vers[sharpAngleIndex].x - bottomPoints[1].x)/(vers[sharpAngleIndex].y - bottomPoints[1].y);
int x1 = (int)((i - minY)*k1 + vers[sharpAngleIndex].x + 0.5f);
int x2 = (int)((i - minY)*k2 + vers[sharpAngleIndex].x + 0.5f);
DRasterizer::DrawHorLine(pSurface, x1, x2, i, pPoly->GetColor().x*255,
pPoly->GetColor().y*255, pPoly->GetColor().z*255);
}
}
else
{ // draw bottom triangle
vec2 topPoints[2];
int index = 0;
// izdvajamo donje dve tacke
for(int i=0;i<3;i++)
{
if(i == sharpAngleIndex)
continue;
topPoints[index] = pPoly->m_Vertices[i].GetScreenPos();
index++;
}
for(float i=minY;i<maxY;i++)
{
float k1 = (vers[sharpAngleIndex].x - topPoints[0].x)/(vers[sharpAngleIndex].y - topPoints[0].y);
float k2 = (vers[sharpAngleIndex].x - topPoints[1].x)/(vers[sharpAngleIndex].y - topPoints[1].y);
int x1 = (int)((i - maxY)*k1 + vers[sharpAngleIndex].x + 0.5f);
int x2 = (int)((i - maxY)*k2 + vers[sharpAngleIndex].x + 0.5f);
DRasterizer::DrawHorLine(pSurface, x1, x2, i, pPoly->GetColor().x*255,
pPoly->GetColor().y*255, pPoly->GetColor().z*255);
}
}
}
void DRasterizer::DrawHorLine(DSurface * pSurface, int x1, int x2, int y, Uint8 R, Uint8 G, Uint8 B)
{
int screenWidth = ENGINE->GetSWidth();
if( (x1 < 0 && x2 < 0) || (x1 > screenWidth && x2 > screenWidth) ) return;
if( x2 < x1 )
{
int temp = x1;
x1 = x2;
x2 = temp;
}
for(int i=x1;i<x2;i++)
{
if(i <= 0 || i >= 640)
continue;
pSurface->PutPixel(i, y, R, G, B);
}
}
EOF