|
@ -0,0 +1,205 @@ |
|
|
|
|
|
/*
|
|
|
|
|
|
* To change this license header, choose License Headers in Project Properties. |
|
|
|
|
|
* To change this template file, choose Tools | Templates |
|
|
|
|
|
* and open the template in the editor. |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* File: Raster.cc |
|
|
|
|
|
* Author: blobt |
|
|
|
|
|
* |
|
|
|
|
|
* Created on January 23, 2020, 6:00 PM |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#include "Rgba.h"
|
|
|
|
|
|
#include "Raster.h"
|
|
|
|
|
|
#include "Image.h"
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std; |
|
|
|
|
|
|
|
|
|
|
|
Raster::Raster(int width, int height) { |
|
|
|
|
|
_width = width; |
|
|
|
|
|
_height = height; |
|
|
|
|
|
|
|
|
|
|
|
buffer = new Rgba[width * height]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Raster::~Raster() { |
|
|
|
|
|
delete buffer; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Raster::drawPoint(int x, int y, Rgba color, int pointSize) { |
|
|
|
|
|
switch (pointSize) { |
|
|
|
|
|
case 1: |
|
|
|
|
|
setPixel(x, y, color); |
|
|
|
|
|
break; |
|
|
|
|
|
case 2: |
|
|
|
|
|
setPixel(x, y, color); |
|
|
|
|
|
setPixel(x + 1, y, color); |
|
|
|
|
|
setPixel(x, y + 1, color); |
|
|
|
|
|
setPixel(x + 1, y + 1, color); |
|
|
|
|
|
break; |
|
|
|
|
|
case 3: |
|
|
|
|
|
setPixel(x - 1, y - 1, color); |
|
|
|
|
|
setPixel(x, y - 1, color); |
|
|
|
|
|
setPixel(x + 1, y - 1, color); |
|
|
|
|
|
|
|
|
|
|
|
setPixel(x - 1, y, color); |
|
|
|
|
|
setPixel(x, y, color); |
|
|
|
|
|
setPixel(x + 1, y, color); |
|
|
|
|
|
|
|
|
|
|
|
setPixel(x - 1, y + 1, color); |
|
|
|
|
|
setPixel(x, y + 1, color); |
|
|
|
|
|
setPixel(x + 1, y + 1, color); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 画一条平行于x轴的直线 |
|
|
|
|
|
* @param span |
|
|
|
|
|
*/ |
|
|
|
|
|
void Raster::drawSpan(const Span &span, Image* image) { |
|
|
|
|
|
//float length = tmax<int>(span.xStart - span.xEnd, 1); //取保length不为0
|
|
|
|
|
|
|
|
|
|
|
|
Rgba color; |
|
|
|
|
|
float2 uv; |
|
|
|
|
|
float scale; |
|
|
|
|
|
float length = span.xEnd - span.xStart; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int startX = tmax<int>(span.xStart, 0); |
|
|
|
|
|
int endX = tmin<int>(span.xEnd, _width); |
|
|
|
|
|
|
|
|
|
|
|
int t = 0; |
|
|
|
|
|
//优化3 x轴越界处理
|
|
|
|
|
|
for (int i = startX; i <= endX; i++) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (length == 0) { |
|
|
|
|
|
scale = 0; |
|
|
|
|
|
} else { |
|
|
|
|
|
scale = (float) (i - startX) / length; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uv = uvLerp(span.uvStart, span.uvEnd, scale); |
|
|
|
|
|
|
|
|
|
|
|
color = image->pixelUv(uv.x, uv.y); |
|
|
|
|
|
setPixel(i, span.y, color); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Raster::drawEge(const Ege& e1, const Ege& e2, Image* image) { |
|
|
|
|
|
|
|
|
|
|
|
float xOffset1 = fabs(e1.x2 - e1.x1); |
|
|
|
|
|
float yOffset1 = fabs(e1.y2 - e1.y1); |
|
|
|
|
|
float setp1 = 1 / yOffset1; |
|
|
|
|
|
float scale1 = (e1.y2 - e2.y2) / yOffset1; //TODO:yOffset1 不能为0
|
|
|
|
|
|
|
|
|
|
|
|
float xOffset2 = fabs(e2.x2 - e2.x1); |
|
|
|
|
|
float yOffset2 = fabs(e2.y2 - e2.y1); |
|
|
|
|
|
float setp2 = 1 / yOffset2; //TODO:yOffset2 不能为0
|
|
|
|
|
|
float scale2 = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//优化2 y轴越界处理
|
|
|
|
|
|
int startY2 = tmin<int>(e2.y2, _height); |
|
|
|
|
|
int endY2 = tmax<int>(e2.y1, 0); |
|
|
|
|
|
scale2 = (e2.y2 - startY2) / yOffset2; |
|
|
|
|
|
|
|
|
|
|
|
int startY1 = tmin<int>(e1.y2, _height); |
|
|
|
|
|
float s = (e1.y2 - startY1) / yOffset1; |
|
|
|
|
|
scale1 = tmax<float>(scale1, s); |
|
|
|
|
|
|
|
|
|
|
|
float2 uvE1; |
|
|
|
|
|
float2 uvE2; |
|
|
|
|
|
for (int y = startY2; y > endY2; y--) { |
|
|
|
|
|
|
|
|
|
|
|
int x2; |
|
|
|
|
|
if (e2.x2 < e2.x1) { |
|
|
|
|
|
x2 = e2.x2 + xOffset2 * scale2; |
|
|
|
|
|
} else { |
|
|
|
|
|
x2 = e2.x2 - xOffset2 * scale2; |
|
|
|
|
|
} |
|
|
|
|
|
uvE2 = uvLerp(e2.uv2, e2.uv1, scale2); |
|
|
|
|
|
scale2 += setp2; |
|
|
|
|
|
//setPixel(x2, y, e2.color2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int x1; |
|
|
|
|
|
if (e1.x2 < e1.x1) { |
|
|
|
|
|
x1 = e1.x2 + xOffset1 * scale1; |
|
|
|
|
|
} else { |
|
|
|
|
|
x1 = e1.x2 - xOffset1 * scale1; |
|
|
|
|
|
} |
|
|
|
|
|
uvE1 = uvLerp(e1.uv2, e1.uv1, scale1); |
|
|
|
|
|
scale1 += setp1; |
|
|
|
|
|
//setPixel(x1, y, e1.color2);
|
|
|
|
|
|
|
|
|
|
|
|
Span span(x1, x2, y, Rgba(255,255,255), Rgba(255,255,255), uvE1, uvE2); |
|
|
|
|
|
drawSpan(span, image); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Raster::drawTriangle(const Vertex& vertex, Image* image) { |
|
|
|
|
|
|
|
|
|
|
|
//优化1 不画3个点都不在坐标内的三角形
|
|
|
|
|
|
if (!isIn(vertex.p0) && !isIn(vertex.p1) && !isIn(vertex.p2)) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Ege eges[3] = { |
|
|
|
|
|
Ege(vertex.p0.x, vertex.p0.y, vertex.p1.x, vertex.p1.y, vertex.c0, vertex.c1, vertex.uv0, vertex.uv1), |
|
|
|
|
|
Ege(vertex.p1.x, vertex.p1.y, vertex.p2.x, vertex.p2.y, vertex.c1, vertex.c2, vertex.uv1, vertex.uv2), |
|
|
|
|
|
Ege(vertex.p2.x, vertex.p2.y, vertex.p0.x, vertex.p0.y, vertex.c2, vertex.c0, vertex.uv2, vertex.uv0), |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
int iMax = 0; |
|
|
|
|
|
int length = eges[0].y2 - eges[0].y1; |
|
|
|
|
|
|
|
|
|
|
|
int curLength = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i < 3; i++) { |
|
|
|
|
|
curLength = eges[i].y2 - eges[i].y1; |
|
|
|
|
|
if (curLength > length) { |
|
|
|
|
|
iMax = i; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int iShort1 = (iMax + 1) % 3; |
|
|
|
|
|
int iShort2 = (iMax + 2) % 3; |
|
|
|
|
|
|
|
|
|
|
|
drawEge(eges[iMax], eges[iShort1], image); |
|
|
|
|
|
drawEge(eges[iMax], eges[iShort2], image); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int Raster::size() { |
|
|
|
|
|
return _width * _height * sizeof (Rgba); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Raster::clean() { |
|
|
|
|
|
memset(buffer, 0, size()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool Raster::setPixel(int x, int y, Rgba color) { |
|
|
|
|
|
if (x < 0 || y < 0 || x >= _width || y >= _height) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
//行列是反的
|
|
|
|
|
|
buffer[ ((_height - 1) - y) * _width + x] = color; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Rgba Raster::getPixel(int x, int y) { |
|
|
|
|
|
return buffer[ ((_height - 1) - y) * _width + x]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool Raster::isIn(int2 point) { |
|
|
|
|
|
if (point.x >= 0 && point.x <= _width && point.y >= 0 && point.y < _height) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
} |