Commit 8145f603 authored by David Llewellyn-Jones's avatar David Llewellyn-Jones

Optimised triangle rasterisation for SVX output.

parent 0531a9f8
......@@ -2044,7 +2044,6 @@ void CurveOutputVoxelSlice (unsigned char * pcData, int nResolution, int nChanne
//SetVector3 (avTriangle[0], (256 + 100 * sin (fRot)), (256 + 100 * cos (fRot)), 0.0f);
//SetVector3 (avTriangle[1], (256 + 100 * sin (fRot + M_PI * (2.0 / 3.0))), (256 + 100 * cos (fRot + M_PI * (2.0 / 3.0))), 0.0f);
//SetVector3 (avTriangle[2], (256 + 100 * sin (fRot + M_PI * (4.0 / 3.0))), (256 + 100 * cos (fRot + M_PI * (4.0 / 3.0))), 0.0f);
//CurveRasteriseTriangle (pcData, nResolution, nChannels, & avTriangle[0], & avTriangle[1], & avTriangle[2]);
}
......@@ -2211,100 +2210,123 @@ void CurveReorderQuadVertices (Vector3 * avBounds, int nVertices) {
// Use pixel coordinates for this call
void CurveRasteriseTriangle (unsigned char * pcData, int nResolution, int nChannels, Vector3 const * pvV1, Vector3 const * pvV2, Vector3 const * pvV3) {
Vector3 vDir1;
Vector3 vDir2;
//Vector3 vDir3;
float fXSteps;
float fYSteps;
float fXEnd;
float fXStep;
float fYStep;
static const float fDX = 0.5f;
static const float fDY = 0.5f;
Vector3 vXGrad;
Vector3 vYGrad;
Vector3 vXPoint;
Vector3 vYPoint;
Vector3 vPoint;
int nChannel;
Vector3 const * apvCorner[3];
Vector3 const * pvSwitch;
int nX;
int nY;
float fXEndFull;
float fXEndStep;
// Calculate direcdtions between vertices
vDir1 = SubtractVectors (pvV2, pvV1);
vDir2 = SubtractVectors (pvV3, pvV1);
//vDir3 = SubtractVectors (pvV3, pvV2);
// Calculate gradient steps
if (abs (vDir1.fX) >= abs (vDir1.fY)) {
fXSteps = abs (vDir1.fX) / fDX;
if (fXSteps == 0.0f) {
// There's still a problem; probably vertices are identical
fXSteps = 1.0f;
}
}
else {
fXSteps = abs (vDir1.fY) / fDX;
if (fXSteps == 0.0f) {
// There's still a problem; probably vertices are identical
fXSteps = 1.0f;
}
}
// Calculate the gradient
vXGrad = ScaleVector (& vDir1, (1.0f / fXSteps));
float fXStart;
float fXEnd;
float fYStart;
float fYEnd;
float fXStartDelta;
float fXEndDelta;
int nChannel;
// Calculate the gradient steps
if (abs (vDir2.fX) >= abs (vDir2.fY)) {
fYSteps = abs (vDir2.fX) / fDY;
if (fYSteps == 0.0f) {
// There's still a problem; probably vertices are identical
fYSteps = 1.0f;
}
// Re-order the vectors by y-value (lowest first)
apvCorner[0] = pvV1;
apvCorner[1] = pvV2;
apvCorner[2] = pvV3;
if (apvCorner[0]->fY > apvCorner[1]->fY) {
apvCorner[0] = pvV2;
apvCorner[1] = pvV1;
}
else {
fYSteps = abs (vDir2.fY) / fDY;
if (fYSteps == 0.0f) {
// There's still a problem; probably vertices are identical
fYSteps = 1.0f;
}
if (apvCorner[0]->fY > apvCorner[2]->fY) {
apvCorner[2] = apvCorner[0];
apvCorner[0] = pvV3;
}
if (apvCorner[1]->fY > apvCorner[2]->fY) {
pvSwitch = apvCorner[2];
apvCorner[2] = apvCorner[1];
apvCorner[1] = pvSwitch;
}
// Calculate the gradient
vYGrad = ScaleVector (& vDir2, (1.0f / fYSteps));
// Calculate some utility variables used to figure out how long we need to draw each line
if (abs (vDir1.fX) >= abs (vDir1.fY)) {
fXEndFull = (vDir1.fX / fDX);
fXEndStep = (fXEndFull / fYSteps);
// Start at the bottom and render upwards
fXStart = round (apvCorner[0]->fX);
fXEnd = fXStart;
fYStart = floor (apvCorner[0]->fY);
fYEnd = ceil (apvCorner[1]->fY);
if ((ceil (apvCorner[2]->fY) - floor (apvCorner[0]->fY)) != 0.0f) {
fXEndDelta = (round (apvCorner[2]->fX) - round (apvCorner[0]->fX)) / (ceil (apvCorner[2]->fY) - floor (apvCorner[0]->fY));
}
else {
fXEndFull = (vDir1.fY / fDX);
fXEndStep = (fXEndFull / fYSteps);
fXEndDelta = 1.0f;
}
if (abs (ceil (apvCorner[1]->fY) - floor (apvCorner[0]->fY)) > 0.0f) {
fXStartDelta = (round (apvCorner[1]->fX) - round (apvCorner[0]->fX)) / (ceil (apvCorner[1]->fY) - floor (apvCorner[0]->fY));
fXEndDelta = (round (apvCorner[2]->fX) - round (apvCorner[0]->fX)) / (ceil (apvCorner[2]->fY) - floor (apvCorner[0]->fY));
if ((fXEndDelta - fXStartDelta) >= 0.0) {
for (nY = fYStart; nY < fYEnd; nY++) {
fXStart += fXStartDelta;
fXEnd += fXEndDelta;
for (nX = round (fXStart) - 1; nX <= round (fXEnd) + 1; nX++) {
// Plot the point to the bitmap
if ((nX >= 0) && (nX < nResolution) && (nY >= 0) && (nY < nResolution)) {
for (nChannel = 0; nChannel < nChannels; nChannel++) {
pcData[(((nX + ((nResolution - nY - 1) * nResolution)) * nChannels) + nChannel)] = 255;
}
}
}
}
}
else {
for (nY = fYStart; nY < fYEnd; nY++) {
fXStart += fXStartDelta;
fXEnd += fXEndDelta;
for (nX = round (fXStart) + 1; nX >= round (fXEnd) - 1; nX--) {
// Plot the point to the bitmap
if ((nX >= 0) && (nX < nResolution) && (nY >= 0) && (nY < nResolution)) {
for (nChannel = 0; nChannel < nChannels; nChannel++) {
pcData[(((nX + ((nResolution - nY - 1) * nResolution)) * nChannels) + nChannel)] = 255;
}
}
}
}
}
}
// Draw the triangle
for (fYStep = 0.0f; fYStep < fYSteps; fYStep += fDY) {
// The length of the line we need to draw
fXEnd = abs (fXEndFull - (fYStep * fXEndStep));
// Draw a line of the triangle
for (fXStep = 0.0f; fXStep < fXEnd; fXStep += fDX) {
// Calculate the position of the point
// TODO: Calculate this incrementally
vYPoint = ScaleVector (& vYGrad, fYStep);
vXPoint = ScaleVector (& vXGrad, fXStep);
vPoint = AddVectors (& vXPoint, & vYPoint);
vPoint = AddVectors (& vPoint, pvV1);
nX = vPoint.fX;
nY = vPoint.fY;
// Plot the point to the bitmap
for (nChannel = 0; nChannel < nChannels; nChannel++) {
pcData[(((nX + ((nResolution - nY - 1) * nResolution)) * nChannels) + nChannel)] = 255;
// Start at the bottom and render upwards
fXStart = round (apvCorner[1]->fX);
fYStart = ceil (apvCorner[1]->fY);
// fXEnd stays the same
fYEnd = ceil (apvCorner[2]->fY);
if (abs (ceil (apvCorner[2]->fY) - ceil (apvCorner[1]->fY)) > 0.0f) {
fXStartDelta = (round (apvCorner[2]->fX) - round (apvCorner[1]->fX)) / (ceil (apvCorner[2]->fY) - ceil (apvCorner[1]->fY));
// fXEndDelta stays the same
if (fXStart <= fXEnd) {
for (nY = fYStart; nY < fYEnd; nY++) {
fXStart += fXStartDelta;
fXEnd += fXEndDelta;
for (nX = round (fXStart) - 1; nX <= round (fXEnd) + 1; nX++) {
// Plot the point to the bitmap
if ((nX >= 0) && (nX < nResolution) && (nY >= 0) && (nY < nResolution)) {
for (nChannel = 0; nChannel < nChannels; nChannel++) {
pcData[(((nX + ((nResolution - nY - 1) * nResolution)) * nChannels) + nChannel)] = 255;
}
}
}
}
}
else {
for (nY = fYStart; nY < fYEnd; nY++) {
fXStart += fXStartDelta;
fXEnd += fXEndDelta;
for (nX = round (fXStart) + 1; nX >= round (fXEnd) - 1; nX--) {
// Plot the point to the bitmap
if ((nX >= 0) && (nX < nResolution) && (nY >= 0) && (nY < nResolution)) {
for (nChannel = 0; nChannel < nChannels; nChannel++) {
pcData[(((nX + ((nResolution - nY - 1) * nResolution)) * nChannels) + nChannel)] = 255;
}
}
}
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment