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.
568 lines
20 KiB
568 lines
20 KiB
/**
|
|
* \file rasterize.cpp
|
|
*
|
|
* \brief Implementation des Software-Rasterizers
|
|
*
|
|
* Für eine detailierte Beschreibung von Rasterizer und
|
|
* Software-Rasterizer schauen Sie bitte unter \ref rasterize.h
|
|
*
|
|
* \author Georg Steffers <georg@steffers.org> [gs]
|
|
*
|
|
* \date 04.12.2003
|
|
*
|
|
* \version ..2002 [gs]: erste funktionierende Implementation
|
|
* \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen
|
|
* \version 16.12.2003 [gs]: <ul><li>
|
|
* Linienclipping gefixed. Die alte
|
|
* Version versuchte Linien zu zeichnen
|
|
* die sich nach dem Clipping in
|
|
* Area 1001, 1010, 0101, 0110, also den
|
|
* Ecken rechtoben, linksoben,
|
|
* rechtsunten und linksunten neben dem
|
|
* darstellbaren Bereich befanden.
|
|
* </li><li>
|
|
* Außerdum mussten nach jedem Clipping
|
|
* die Masken aktualisiert werden, damit
|
|
* der Algoritmus abbricht wenn die
|
|
* Linie gezeichnet werden kann.
|
|
* Ansosnten führte weiters clipping zu
|
|
* fehlerhaften Ergebnissen.
|
|
* </li><li>
|
|
* draw_polygon_flat ruft jetzt den in
|
|
* polygon.h neu geschriebene
|
|
* Sutherland-Hodgen Clipper auf und
|
|
* zeichnet nur das geclippte Polygon
|
|
* das dieser Zurückliefert.
|
|
* </li></ul>
|
|
* \version 19.12.2003 [gs]: <ul><li>
|
|
* draw_polyeder_wire neu geschrieben. (Der
|
|
* alte Code existiert noch auskommentiert.
|
|
* </li><li>
|
|
* draw_polygon_wire geschrieben. Es macht was man
|
|
* sich denkt, es zeichnte ein Polygon alse linien.
|
|
* </li></ul>
|
|
*
|
|
* \todo (siehe \ref draw_polygon_flat)
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C)2003 Georg Steffers
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
using namespace std;
|
|
|
|
#include <cstdlib>
|
|
#include <climits>
|
|
#include <cstring>
|
|
#include <values.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include "geometry/polygon.h"
|
|
#include "rasterize.h"
|
|
|
|
#define CLIP_MASK_LEFT (0x1<<0)
|
|
#define CLIP_MASK_RIGHT (0x1<<1)
|
|
#define CLIP_MASK_BOTTOM (0x1<<2)
|
|
#define CLIP_MASK_TOP (0x1<<3)
|
|
|
|
rasterizer::rasterizer(unsigned xs, unsigned ys, canvas_imp* ci) {
|
|
x_size=xs;
|
|
y_size=ys;
|
|
|
|
sinfo=ci;
|
|
|
|
zbuf=new (double*)[xs];
|
|
for(unsigned i=0; i<xs; i++) {
|
|
zbuf[i]=new double[ys];
|
|
for(unsigned j=0; j<ys; zbuf[i][j++]=MAXDOUBLE);
|
|
}
|
|
|
|
unsigned sp[]={0,1,2,3};
|
|
vertex v[]={vertex(0,y_size,0,1),
|
|
vertex(0,0,0,1),
|
|
vertex(x_size,0,0,1),
|
|
vertex(x_size,y_size,0,1)};
|
|
|
|
screen_p_vl=vertex_list(v, 4);
|
|
screen_p=polygon((unsigned*)sp, 4, &screen_p_vl);
|
|
}
|
|
|
|
unsigned char* sw_rasterizer::adr_of_point(unsigned x, unsigned y) const {
|
|
return sinfo->p_screenbuf + (x+(y*x_size))*sinfo->bytes_per_pixel;
|
|
}
|
|
|
|
void sw_rasterizer::draw_point_at_paddress(unsigned char** p,
|
|
unsigned long col) const {
|
|
unsigned long mask = 0xFF;
|
|
char shift = 0;
|
|
|
|
// farbytes in Little-Endian order in den Puffer
|
|
for(int i=0; i<sinfo->bytes_per_pixel; i++) {
|
|
**p = (col & mask) >> shift;
|
|
(*p)++;
|
|
mask <<= 8;
|
|
shift += 8;
|
|
}
|
|
}
|
|
|
|
void sw_rasterizer::clear_buffer(void) const {
|
|
memset(sinfo->p_screenbuf, 0x00,
|
|
(size_t)x_size*y_size*sinfo->bytes_per_pixel);
|
|
|
|
for(unsigned i=0; i<x_size; i++) {
|
|
for(unsigned j=0; j<y_size; zbuf[i][j++]=MAXDOUBLE);
|
|
}
|
|
}
|
|
|
|
void sw_rasterizer::draw_point(unsigned x, unsigned y,
|
|
unsigned long col) const {
|
|
unsigned char *p = adr_of_point(x, y);
|
|
draw_point_at_paddress(&p, col);
|
|
}
|
|
|
|
void sw_rasterizer::line(double ax, double ay, double bx, double by,
|
|
unsigned long col) const {
|
|
/* Line-Clipping (nach Cohen-Sutherland) */
|
|
char clip_mask_a=0;
|
|
char clip_mask_b=0;
|
|
unsigned x_size=this->x_size-1;
|
|
unsigned y_size=this->y_size-1;
|
|
|
|
if(ax<0) clip_mask_a |= CLIP_MASK_LEFT;
|
|
if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT;
|
|
if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM;
|
|
if(ay<0) clip_mask_a |= CLIP_MASK_TOP;
|
|
|
|
if(bx<0) clip_mask_b |= CLIP_MASK_LEFT;
|
|
if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT;
|
|
if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM;
|
|
if(by<0) clip_mask_b |= CLIP_MASK_TOP;
|
|
|
|
if((clip_mask_a & clip_mask_b) != 0)
|
|
return;
|
|
|
|
double dx=bx-ax;
|
|
double dy=by-ay;
|
|
double xinc=dx/dy;
|
|
double yinc=dy/dx;
|
|
|
|
if(clip_mask_a != 0) {
|
|
if((clip_mask_a&CLIP_MASK_LEFT)!=0) {
|
|
ay+=(0-ax)*yinc;
|
|
ax=0;
|
|
}
|
|
else if(clip_mask_a & CLIP_MASK_RIGHT) {
|
|
ay+=(x_size-ax)*yinc;
|
|
ax=x_size;
|
|
}
|
|
|
|
clip_mask_a=0;
|
|
if(ax<0) clip_mask_a |= CLIP_MASK_LEFT;
|
|
if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT;
|
|
if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM;
|
|
if(ay<0) clip_mask_a |= CLIP_MASK_TOP;
|
|
|
|
if(clip_mask_a & CLIP_MASK_TOP) {
|
|
ax+=(0-ay)*xinc;
|
|
ay=0;
|
|
}
|
|
else if(clip_mask_a & CLIP_MASK_BOTTOM) {
|
|
ax+=(y_size-ay)*xinc;
|
|
ay=y_size;
|
|
}
|
|
}
|
|
|
|
if(clip_mask_b != 0) {
|
|
if(clip_mask_b & CLIP_MASK_LEFT) {
|
|
by+=(0-bx)*yinc;
|
|
bx=0;
|
|
}
|
|
else if(clip_mask_b & CLIP_MASK_RIGHT) {
|
|
by+=(x_size-bx)*yinc;
|
|
bx=x_size;
|
|
}
|
|
|
|
clip_mask_b=0;
|
|
if(bx<0) clip_mask_b |= CLIP_MASK_LEFT;
|
|
if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT;
|
|
if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM;
|
|
if(by<0) clip_mask_b |= CLIP_MASK_TOP;
|
|
|
|
if(clip_mask_b & CLIP_MASK_TOP) {
|
|
bx+=(0-by)*xinc;
|
|
by=0;
|
|
}
|
|
else if(clip_mask_b & CLIP_MASK_BOTTOM) {
|
|
bx+=(y_size-by)*xinc;
|
|
by=y_size;
|
|
}
|
|
}
|
|
|
|
clip_mask_a=0;
|
|
if(ax<0) clip_mask_a |= CLIP_MASK_LEFT;
|
|
if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT;
|
|
if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM;
|
|
if(ay<0) clip_mask_a |= CLIP_MASK_TOP;
|
|
|
|
clip_mask_b=0;
|
|
if(bx<0) clip_mask_b |= CLIP_MASK_LEFT;
|
|
if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT;
|
|
if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM;
|
|
if(by<0) clip_mask_b |= CLIP_MASK_TOP;
|
|
|
|
if((clip_mask_a | clip_mask_b) == (CLIP_MASK_LEFT | CLIP_MASK_TOP) ||
|
|
(clip_mask_a | clip_mask_b) == (CLIP_MASK_LEFT | CLIP_MASK_BOTTOM) ||
|
|
(clip_mask_a | clip_mask_b) == (CLIP_MASK_RIGHT | CLIP_MASK_TOP) ||
|
|
(clip_mask_a | clip_mask_b) == (CLIP_MASK_RIGHT | CLIP_MASK_BOTTOM))
|
|
return;
|
|
/* ----------- */
|
|
|
|
/* Linie nach Bresenham */
|
|
int Ax=(int)ax;
|
|
int Bx=(int)bx;
|
|
int Ay=(int)ay;
|
|
int By=(int)by;
|
|
|
|
int dX = abs(Bx-Ax);
|
|
int dY = abs(By-Ay);
|
|
|
|
int Xincr=(Ax > Bx)?-1:1;
|
|
int Yincr=(Ay > By)?-1:1;
|
|
|
|
if (dX >= dY) {
|
|
int dPr = dY<<1;
|
|
int dPru = dPr - (dX<<1);
|
|
int P = dPr - dX;
|
|
|
|
for (; dX>=0; dX--) {
|
|
draw_point(Ax, Ay, col);
|
|
if (P > 0) {
|
|
Ax+=Xincr;
|
|
Ay+=Yincr;
|
|
P+=dPru;
|
|
}
|
|
else {
|
|
Ax+=Xincr;
|
|
P+=dPr;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
int dPr = dX<<1;
|
|
int dPru = dPr - (dY<<1);
|
|
int P = dPr - dY;
|
|
|
|
for (; dY>=0; dY--) {
|
|
draw_point(Ax, Ay, col);
|
|
if (P > 0) {
|
|
Ax+=Xincr;
|
|
Ay+=Yincr;
|
|
P+=dPru;
|
|
}
|
|
else {
|
|
Ay+=Yincr;
|
|
P+=dPr;
|
|
}
|
|
}
|
|
}
|
|
/*------------------*/
|
|
}
|
|
|
|
void sw_rasterizer::draw_polygon_wire(const polygon& p,
|
|
unsigned long col) const {
|
|
for(unsigned i=0; i<p.card(); i++) {
|
|
line((int)p[i][X], (int)p[i][Y],
|
|
(int)p[(i+1)%p.card()][X], (int)p[(i+1)%p.card()][Y], col);
|
|
}
|
|
}
|
|
|
|
void sw_rasterizer::draw_polyeder_wire(const polyeder& p,
|
|
unsigned long col) const {
|
|
/* for(unsigned i=0; i<p.card(); i++) {
|
|
int oldx, oldy;
|
|
int firstx, firsty;
|
|
|
|
oldx=oldy=firstx=firsty=0;
|
|
|
|
for(unsigned j=0; j<p[i].card(); j++) {
|
|
if(oldx)
|
|
line(oldx, oldy, (int)p[i][j][X], (int)p[i][j][Y], col);
|
|
|
|
oldx=(int)p[i][j][X], oldy=(int)p[i][j][Y];
|
|
|
|
if(j==0)
|
|
firstx=(int)p[i][j][X], firsty=(int)p[i][j][Y];
|
|
}
|
|
|
|
line(oldx, oldy, firstx, firsty, col);
|
|
}*/
|
|
for(unsigned i=0; i<p.card(); i++) {
|
|
for(unsigned j=0; j<p[i].card(); j++) {
|
|
line((int)p[i][j][X], (int)p[i][j][Y],
|
|
(int)p[i][(j+1)%p.card()][X],
|
|
(int)p[i][(j+1)%p.card()][Y], col);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \todo Ein funktionierendes z-buffering und texturemapping usw.
|
|
* Aktuell ist ein Prototyp-Code für einen z-Buffer drin,
|
|
* aber der funktioniert aus irgendeinem Grund nicht richtig.
|
|
*/
|
|
void sw_rasterizer::draw_polygon_flat(const polygon& p,
|
|
unsigned long col) const {
|
|
int top=0, bottom=0, o_top=0;
|
|
int start_left, end_left;
|
|
int start_right, end_right;
|
|
|
|
/* Clipping..... */
|
|
/* Sutherland-Hodgman */
|
|
polygon clipped=p.clip_2d(screen_p);
|
|
|
|
// Sind nach dem Clipping weniger als 3 Vertices übrig, so ist das
|
|
// Polygon nicht mehr im sichtbaren Bereich und darf nicht gezeichnet
|
|
// werden.
|
|
if(clipped.card()<3)
|
|
return;
|
|
|
|
// oberes und unterstes Vertex finden...
|
|
// außerdem den oberen Vertex fuer die erste rechte und linke Kante
|
|
for(unsigned i=1; i<clipped.card(); i++) {
|
|
end_left=end_right=top=(clipped[i][Y]<clipped[top][Y])?i:top;
|
|
bottom=(clipped[i][Y]>clipped[bottom][Y])?i:bottom;
|
|
}
|
|
|
|
for(unsigned i=1; i<p.card(); i++) {
|
|
o_top=(p[i][Y]<p[o_top][Y])?i:o_top;
|
|
}
|
|
|
|
// Startpositionen
|
|
double act_y=clipped[top][Y];
|
|
int act_ceily=(int)ceil(act_y);
|
|
double act_x_l, act_x_r;
|
|
double act_z_l, act_z_r;
|
|
|
|
// !!! Das erste mal wenn act_z ermittelt wird muss ich die Verchiebung
|
|
// auf die Integer Koordinaten (x,y) mit berechnen, da der gezeichnete Punkt
|
|
// nicht exact dem geometrischen entspricht.
|
|
|
|
// calculate gradients (!!!NICHT VOM GECLIPPTEN!!!)
|
|
// nur anwendbar über Werte die über das gesamte Polygon (screenspace)
|
|
// linear interpolierbar sind, also nicht gourard-shading, da diese
|
|
// Werte nur entlang einer Kante linier sind.
|
|
// !!! Ich brauche eine Methode, ein Dreieck zu finden, das einen Punkt
|
|
// oben, den zweiten als linke Seite und den dritten als rechte Seite bildet
|
|
// dazu muss ich die x,y Werte der Puntke analysieren. Die Lage der
|
|
// Punkte ist wichtig, damit die Vorzeichen der Gradienten stimmen, bzw.
|
|
// überhaupt erstmal welche berechnet werden können, es gibt Punkt
|
|
// kombinationen für die die Gradientenberechnung kein Ergebnis liefert.
|
|
// Das ermittelte Dreieck lässt sich dann allerdings zur ermittlung aller
|
|
// Gradienten gebrauchen.
|
|
|
|
// den obersten Vertex raussuchen, dann den davor und den danach.
|
|
// !!!ACHTUNG!!! Bei allen Berechnungen lasse ich im moment einen Fall
|
|
// ganz außer acht und zwar den, wenn das Dreiech zu einer Linie
|
|
// entartet.
|
|
unsigned gr_v0=o_top;
|
|
unsigned gr_v1=(o_top+1)%p.card();
|
|
unsigned gr_v2=(o_top-1<0)?o_top-1+p.card():o_top-1;
|
|
|
|
// der kleinere X soll gr_v1 sein wenn sein Y größer ist.
|
|
if((p[gr_v1][X]>p[gr_v2][X] && p[gr_v1][Y]>=p[gr_v2][Y]) ||
|
|
(p[gr_v1][X]<p[gr_v2][X] && p[gr_v1][Y]<p[gr_v2][Y]))
|
|
swap<unsigned>(gr_v1, gr_v2);
|
|
|
|
double dx21=p[gr_v2][X]-p[gr_v1][X];
|
|
double dx10=p[gr_v1][X]-p[gr_v0][X];
|
|
double dy21=p[gr_v2][Y]-p[gr_v1][Y];
|
|
double dy01=p[gr_v0][Y]-p[gr_v1][Y];
|
|
double d_z21=p[gr_v2][Z]-p[gr_v1][Z];
|
|
double d_z10=p[gr_v1][Z]-p[gr_v0][Z];
|
|
|
|
double dx01=p[gr_v0][X]-p[gr_v1][X];
|
|
double dy10=p[gr_v1][Y]-p[gr_v0][Y];
|
|
|
|
double v3_x=p[gr_v0][X];
|
|
double v4_y=p[gr_v0][Y];
|
|
double v3_y=((dy21*dx01) / dx21) + p[gr_v1][Y];
|
|
double v3_z=((d_z21*dx01) / dx21) + p[gr_v1][Z];
|
|
double v4_x=((dx21*dy01) / dy21) + p[gr_v1][X];
|
|
double v4_z=((d_z21*dy01) / dy21) + p[gr_v1][Z];
|
|
|
|
// zuallererst müsste ich mal überprüfen ob alle drei Punkte in
|
|
// einer Linie liegen, also dx01/dy01 == dx02/dy02 ist...da ich aber
|
|
// noch nicht weiss wie ich diesen Fall behandeln soll ignorier ich
|
|
// ihn im moment und nehme die entstehenden Fehler in kauf.
|
|
|
|
double d_zdx_denominator=0;
|
|
double d_zdy_denominator=0;
|
|
double d_zdx, d_zdy;
|
|
// zuerst dc/dx ermitteln. (einfach wenn y1==y2)
|
|
// zu den Bezeichnern: _x == 1/x, _? == 1/?
|
|
if(p[gr_v0][Y] == p[gr_v1][Y])
|
|
d_zdx=(p[gr_v1][Z]-p[gr_v0][Z]) / (p[gr_v1][X]-p[gr_v0][X]);
|
|
else if(p[gr_v0][Y] == p[gr_v2][Y])
|
|
d_zdx=(p[gr_v2][Z]-p[gr_v0][Z]) / (p[gr_v2][X]-p[gr_v0][X]);
|
|
else if(p[gr_v1][Y] == p[gr_v2][Y])
|
|
d_zdx=(p[gr_v2][Z]-p[gr_v1][Z]) / (p[gr_v2][X]-p[gr_v1][X]);
|
|
else {
|
|
d_zdx_denominator=(dx21*dy01)+(dx10*dy21);
|
|
d_zdx=((d_z21*dy01)+(d_z10*dy21))/d_zdx_denominator;
|
|
}
|
|
|
|
// jetzt dc/dy...(einfach falls es eine Sekrechte gibt.)
|
|
if(p[gr_v0][X] == p[gr_v1][X])
|
|
d_zdy=(p[gr_v1][Z]-p[gr_v0][Z]) / p[gr_v1][Y]-p[gr_v0][Y];
|
|
else if(p[gr_v0][X] == p[gr_v2][X])
|
|
d_zdy=(p[gr_v2][Z]-p[gr_v0][Z]) / p[gr_v2][Y]-p[gr_v0][Y];
|
|
else if(p[gr_v1][X] == p[gr_v2][X])
|
|
d_zdy=(p[gr_v2][Z]-p[gr_v1][Z]) / p[gr_v2][Y]-p[gr_v1][Y];
|
|
else {
|
|
d_zdy_denominator=d_zdx_denominator!=0?-d_zdx_denominator:
|
|
(dy21*dx01)+(dy10*dx21);
|
|
d_zdy=((d_z21*dx01)+(d_z10*dx21))/d_zdy_denominator;
|
|
}
|
|
|
|
/* if(!strncmp(p.get_id(), "DEBUG", 29)) {
|
|
cout << "---Polygon: " << &p << "----------\n";
|
|
|
|
for(unsigned i=0; i<p.card(); i++) {
|
|
cout << "p[" << i << "][X]: " << p[i][X] << ", ";
|
|
cout << "p[" << i << "][Y]: " << p[i][Y] << ", ";
|
|
cout << "p[" << i << "][1/Z]: " << p[i][Z] << ", ";
|
|
cout << "p[" << i << "][Z]: " << 1/p[i][Z] << "\n";
|
|
}
|
|
for(unsigned i=0; i<clipped.card(); i++) {
|
|
cout << "clipped[" << i << "][X]: " << clipped[i][X] << ", ";
|
|
cout << "clipped[" << i << "][Y]: " << clipped[i][Y] << ", ";
|
|
cout << "clipped[" << i << "][1/Z]: " << clipped[i][Z] << ", ";
|
|
cout << "clipped[" << i << "][Z]: " << 1/clipped[i][Z] << "\n";
|
|
}
|
|
cout << "gr_v0: " << gr_v0 << " | ";
|
|
cout << "gr_v0[X]: " << p[gr_v0][X] << " | ";
|
|
cout << "gr_v0[Y]: " << p[gr_v0][Y] << " | ";
|
|
cout << "gr_v0[Z]: " << p[gr_v0][Z] << "\n";
|
|
cout << "gr_v1: " << gr_v1 << " | ";
|
|
cout << "gr_v1[X]: " << p[gr_v1][X] << " | ";
|
|
cout << "gr_v1[Y]: " << p[gr_v1][Y] << " | ";
|
|
cout << "gr_v1[Z]: " << p[gr_v1][Z] << "\n";
|
|
cout << "gr_v2: " << gr_v2 << " | ";
|
|
cout << "gr_v2[X]: " << p[gr_v2][X] << " | ";
|
|
cout << "gr_v2[Y]: " << p[gr_v2][Y] << " | ";
|
|
cout << "gr_v2[Z]: " << p[gr_v2][Z] << "\n";
|
|
cout << "d_zdx: " << d_zdx << "\n";
|
|
cout << "d_zdy: " << d_zdy << "\n";
|
|
cout << "-------------------------------\n";
|
|
} */
|
|
|
|
//if(!strncmp(p.get_id(), "DEBUG", 29)) {
|
|
// solange zeichnen, bis der unterste y erreicht ist
|
|
while(act_ceily < y_size) {
|
|
double x_inc_l, x_inc_r, z_inc_l, z_inc_r;
|
|
|
|
// naechste linke und rechte Kante finden deren hoehe>0 und
|
|
// das linke und rechte x-Increment ermitteln.
|
|
if((int)ceil(clipped[end_left][Y]) == act_ceily) {
|
|
do {
|
|
start_left=end_left;
|
|
if(start_left == bottom) {
|
|
return;
|
|
}
|
|
end_left=(end_left-1<0)?end_left-1+clipped.card():end_left-1;
|
|
} while((int)ceil(clipped[end_left][Y]) == act_ceily);
|
|
|
|
act_y=clipped[start_left][Y];
|
|
act_ceily=(int)ceil(act_y);
|
|
|
|
x_inc_l=(clipped[end_left][X]-clipped[start_left][X])/
|
|
(clipped[end_left][Y]-clipped[start_left][Y]);
|
|
z_inc_l=x_inc_l*d_zdx;
|
|
|
|
act_x_l=clipped[start_left][X];
|
|
// Subpixelkorrektur
|
|
act_x_l+=((double)act_ceily-act_y)*x_inc_l;
|
|
act_z_l=clipped[start_left][Z];
|
|
act_z_l+=((double)act_ceily-act_y)*z_inc_l;
|
|
}
|
|
if((int)ceil(clipped[end_right][Y]) == act_ceily) {
|
|
do {
|
|
start_right=end_right;
|
|
if(start_right == bottom) {
|
|
return;
|
|
}
|
|
end_right=(end_right+1)%clipped.card();
|
|
} while((int)ceil(clipped[end_right][Y]) == act_ceily);
|
|
|
|
act_y=clipped[start_right][Y];
|
|
act_ceily=(int)ceil(act_y);
|
|
|
|
x_inc_r=(clipped[end_right][X]-clipped[start_right][X])/
|
|
(clipped[end_right][Y]-clipped[start_right][Y]);
|
|
z_inc_r=x_inc_r*d_zdx;
|
|
|
|
act_x_r=clipped[start_right][X];
|
|
// Subpixelkorrektur
|
|
act_x_r+=((double)act_ceily-act_y)*x_inc_r;
|
|
act_z_r=clipped[start_right][Z];
|
|
act_z_r+=((double)act_ceily-act_y)*z_inc_r;
|
|
}
|
|
|
|
// bis zu welchem der beiden Vertexe (links o. rechts) muss ich?
|
|
unsigned togo=((int)ceil(clipped[end_left][Y])-act_ceily <=
|
|
(int)ceil(clipped[end_right][Y])-act_ceily)?
|
|
end_left:end_right;
|
|
|
|
for(; act_ceily < (int)ceil(clipped[togo][Y]); act_ceily++) {
|
|
unsigned char* adr=adr_of_point((act_x_l<act_x_r)?
|
|
(int)ceil(act_x_l):
|
|
(int)ceil(act_x_r),
|
|
act_ceily);
|
|
|
|
unsigned len=abs((int)ceil(act_x_r)-(int)ceil(act_x_l));
|
|
int _X=(act_x_l<act_x_r)?(int)ceil(act_x_l):(int)ceil(act_x_r);
|
|
|
|
//double act_z=(act_x_l<act_x_r)?act_z_l:act_z_r;
|
|
double act_row_z=(act_x_l<act_x_r)?act_z_l:act_z_r;
|
|
|
|
for(unsigned i=0; i<len; i++) {
|
|
double _Z=1/act_row_z;
|
|
//if(zbuf[_X+i][act_ceily] > _Z) {
|
|
draw_point_at_paddress(&adr, col);
|
|
zbuf[_X+i][act_ceily]=_Z;
|
|
//}
|
|
// if(!strncmp(p.get_id(), "DEBUG", 29)) {
|
|
// printf("%03ld,%03ld,%10.7f ", _X+i, act_ceily, act_row_z);
|
|
// }
|
|
act_row_z+=d_zdx;
|
|
}
|
|
|
|
act_x_l+=x_inc_l;
|
|
act_x_r+=x_inc_r;
|
|
act_z_l+=z_inc_l;
|
|
act_z_l+=d_zdy;
|
|
act_z_r+=z_inc_r;
|
|
act_z_r+=d_zdy;
|
|
|
|
// if(!strncmp(p.get_id(), "DEBUG", 29)) {
|
|
// cout << "\n";
|
|
// }
|
|
}
|
|
}
|
|
//}
|
|
}
|