mirror of
https://github.com/KranX/Vangers.git
synced 2025-12-01 07:25:28 +07:00
758 lines
16 KiB
C++
758 lines
16 KiB
C++
#include "../src/global.h"
|
|
|
|
#include "3d_shape.h"
|
|
|
|
#include "../src/common.h"
|
|
|
|
#include "../src/terra/vmap.h"
|
|
#include "../src/terra/world.h"
|
|
#include "../src/terra/render.h"
|
|
|
|
#include "../src/3d/3d_math.h"
|
|
#include "../src/3d/3dgraph.h"
|
|
|
|
#include "missed.h"
|
|
|
|
//#define _SHAPE_
|
|
|
|
#ifdef _SURMAP_
|
|
extern int DepthShow;
|
|
#else
|
|
int DepthShow;
|
|
#endif
|
|
|
|
void S3Danalyze(void);
|
|
|
|
#define COLOR_OFFSET 128
|
|
#define COLOR_SHIFT 3
|
|
|
|
int shape_control(int code);
|
|
void load_shape(char* name,int x,int y);
|
|
void view_shape();
|
|
|
|
int shape_size;
|
|
int shape_shift;
|
|
unsigned char* upper_buffer;
|
|
unsigned char* lower_buffer;
|
|
int shape_x,shape_y;
|
|
int shape_x_avr;
|
|
int shape_y_avr;
|
|
int shape_z_avr;
|
|
|
|
|
|
int shape_offset;
|
|
double shape_scale_x = 1;
|
|
double shape_scale_y = 1;
|
|
double shape_scale_z = 1;
|
|
|
|
int catch_log;
|
|
DBM A_shape(1,-1,-1,DIAGONAL);
|
|
DBM A_shape_inv(1,-1,1,DIAGONAL);
|
|
Model shape;
|
|
|
|
int shape_control(int code)
|
|
{
|
|
if(!catch_log)
|
|
return 0;
|
|
|
|
switch(code){
|
|
case SDLK_ESCAPE:
|
|
catch_log = 0;
|
|
break;
|
|
|
|
case SDLK_SPACE:
|
|
A_shape = DBM(1,-1,-1,DIAGONAL);
|
|
A_shape_inv = DBM(1,-1,1,DIAGONAL);
|
|
if(XKey.Pressed(SDLK_LCTRL))
|
|
shape_scale_x = shape_scale_y = shape_scale_z = 1;
|
|
break;
|
|
|
|
case SDLK_RETURN:
|
|
shape.height_project();
|
|
catch_log = 0;
|
|
#ifdef _SURMAP_
|
|
S3Danalyze();
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
int rotate_step;
|
|
int move_step;
|
|
int alt = XKey.Pressed(SDLK_LCTRL);
|
|
double scale_step;
|
|
if(XKey.Pressed(SDLK_LSHIFT)){
|
|
move_step = 20;
|
|
rotate_step = Pi/8;
|
|
scale_step = 1.1;
|
|
}
|
|
else{
|
|
move_step = 1;
|
|
rotate_step = Pi/256;
|
|
scale_step = 1.001;
|
|
}
|
|
|
|
if(XKey.Pressed(SDLK_DELETE)){
|
|
A_shape = DBM(-rotate_step,Z_AXIS)*A_shape;
|
|
A_shape_inv *= DBM(rotate_step,Z_AXIS);
|
|
}
|
|
//@caiiiycuk: was VK_NEXT
|
|
if(XKey.Pressed(SDLK_RETURN2)){
|
|
A_shape = DBM(rotate_step,Z_AXIS)*A_shape;
|
|
A_shape_inv *= DBM(-rotate_step,Z_AXIS);
|
|
}
|
|
|
|
if(XKey.Pressed(SDLK_HOME)){
|
|
A_shape = DBM(-rotate_step,X_AXIS)*A_shape;
|
|
A_shape_inv *= DBM(rotate_step,X_AXIS);
|
|
}
|
|
if(XKey.Pressed(SDLK_END)){
|
|
A_shape = DBM(rotate_step,X_AXIS)*A_shape;
|
|
A_shape_inv *= DBM(-rotate_step,X_AXIS);
|
|
}
|
|
|
|
if(XKey.Pressed(SDLK_INSERT)){
|
|
A_shape = DBM(rotate_step,Y_AXIS)*A_shape;
|
|
A_shape_inv *= DBM(-rotate_step,Y_AXIS);
|
|
}
|
|
if(XKey.Pressed(SDLK_PRIOR)){
|
|
A_shape = DBM(-rotate_step,Y_AXIS)*A_shape;
|
|
A_shape_inv *= DBM(rotate_step,Y_AXIS);
|
|
}
|
|
|
|
if(XKey.Pressed(SDLK_EQUALS) || XKey.Pressed(SDLK_KP_PLUS)){
|
|
if(!alt){
|
|
shape_scale_x *= scale_step;
|
|
shape_scale_y *= scale_step;
|
|
}
|
|
shape_scale_z *= scale_step;
|
|
}
|
|
if(XKey.Pressed(SDLK_MINUS) || XKey.Pressed(SDLK_KP_MINUS)){
|
|
if(!alt){
|
|
shape_scale_x /= scale_step;
|
|
shape_scale_y /= scale_step;
|
|
}
|
|
shape_scale_z /= scale_step;
|
|
}
|
|
|
|
if(XKey.Pressed(SDLK_UP))
|
|
if(alt)
|
|
shape_scale_y *= scale_step;
|
|
else
|
|
shape.y_off -= move_step;
|
|
if(XKey.Pressed(SDLK_DOWN))
|
|
if(alt)
|
|
shape_scale_y /= scale_step;
|
|
else
|
|
shape.y_off += move_step;
|
|
if(XKey.Pressed(SDLK_LEFT))
|
|
if(alt)
|
|
shape_scale_x /= scale_step;
|
|
else
|
|
shape.x_off -= move_step;
|
|
if(XKey.Pressed(SDLK_RIGHT))
|
|
if(alt)
|
|
shape_scale_x *= scale_step;
|
|
else
|
|
shape.x_off += move_step;
|
|
|
|
#ifdef _SURMAP_
|
|
shape.x_off &= clip_mask_x;
|
|
shape.y_off &= clip_mask_y;
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
void load_shape(char* name,int x,int y)
|
|
{
|
|
XStream c3d(name,XS_IN);
|
|
XBuffer buf(c3d.size());
|
|
c3d.read(buf.address(),c3d.size());
|
|
c3d.close();
|
|
shape.loadC3D(buf);
|
|
|
|
shape.x_off = x;
|
|
shape.y_off = y;
|
|
shape.z_off = 128;
|
|
|
|
catch_log = 1;
|
|
|
|
#ifdef _SHAPE_
|
|
upper_buffer = new unsigned char[1024*1024];
|
|
lower_buffer = new unsigned char[1024*1024];
|
|
#endif
|
|
}
|
|
#ifndef _SURMAP_
|
|
void prepare_shape(int mode,char* name,int new_size)
|
|
{
|
|
char* c3d_name = ALLOC(strlen(name) + 1,char);
|
|
strlwr(name);
|
|
strcpy(c3d_name,name);
|
|
strcpy(strstr(c3d_name,"asc"),"c3d");
|
|
|
|
if(mode & SHAPE_QUIT_IF_EXIST){
|
|
XStream c3d(0);
|
|
if(c3d.open(c3d_name,XS_IN)){
|
|
int version;
|
|
c3d > version;
|
|
if(version == C3D_VERSION_3){
|
|
XCon < "\nFile \"" < name < "\" has already been converted.\n";
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
shape.loadASC(name);
|
|
|
|
double scale_mul = 1;
|
|
if(mode & SHAPE_SCALE)
|
|
scale_mul = new_size/(double)(mode & SHAPE_RELATIVE ? 100 : shape.rmax);
|
|
|
|
Vector offset = Vector(shape.x_off,shape.y_off,shape.z_off);
|
|
if(mode & SHAPE_LOAD_PARAMS){
|
|
XStream f(0);
|
|
if(f.open("shape.prm",XS_IN)){
|
|
Parser prm_in("shape.prm");
|
|
prm_in.search_name("scale_mul:");
|
|
scale_mul = prm_in.get_int();
|
|
|
|
prm_in.search_name("x_offset:");
|
|
offset.x = prm_in.get_int();
|
|
prm_in.search_name("y_offset:");
|
|
offset.y = prm_in.get_int();
|
|
offset.z = 0;
|
|
}
|
|
}
|
|
|
|
XStream prm_out("shape.prm",XS_OUT);
|
|
prm_out.SetDigits(8);
|
|
|
|
XCon < "\nConverting ASC to C3D: " < name < "\n";
|
|
prm_out < "\nConverting ASC to C3D: " < name < "\n";
|
|
|
|
XCon < "Faces: " <= shape.num_poly < "\n";
|
|
prm_out < "Faces: " <= shape.num_poly < "\n";
|
|
XCon < "Vertices: " <= shape.num_vert < "\n";
|
|
prm_out < "Vertices: " <= shape.num_vert < "\n";
|
|
|
|
XCon < "Original bound radius: " <= shape.rmax < "\n";
|
|
prm_out < "Original bound radius: " <= shape.rmax < "\n";
|
|
|
|
|
|
shape.set_colors(COLORS_IDS::BODY,0,0);
|
|
|
|
if(mode & SHAPE_MOVE)
|
|
shape.move(-offset);
|
|
shape.make_normals();
|
|
shape.pre_sorting();
|
|
shape.scale(scale_mul,1);
|
|
|
|
XCon < "Obtained bound radius: " <= shape.rmax < "\n";
|
|
prm_out < "Obtained bound radius: " <= shape.rmax < "\n";
|
|
|
|
prm_out < "scale_mul: " <= scale_mul < "\n";
|
|
prm_out < "x_offset: " <= offset.x < "\n";
|
|
prm_out < "y_offset: " <= offset.y < "\n";
|
|
|
|
XStream fout(c3d_name,XS_OUT);
|
|
shape.saveC3D(fout);
|
|
|
|
delete c3d_name;
|
|
}
|
|
#endif
|
|
void release_shape()
|
|
{
|
|
shape.free();
|
|
if(upper_buffer){
|
|
delete upper_buffer;
|
|
delete lower_buffer;
|
|
}
|
|
}
|
|
void view_shape()
|
|
{
|
|
if(!catch_log)
|
|
return;
|
|
#ifdef _SHAPE_
|
|
shape.height_project();
|
|
shape.draw_big();
|
|
#else
|
|
shape.draw_big();
|
|
#endif
|
|
}
|
|
void Model::draw_big()
|
|
{
|
|
int x = getDistX(x_off,ViewX);
|
|
int y = getDistY(y_off,ViewY);
|
|
if(DepthShow){
|
|
DBV R(x,y,0);
|
|
R *= A_g2s;
|
|
CentrX = round(R.x);
|
|
CentrY = round(R.y);
|
|
CentrZ = ViewZ + round(R.z);
|
|
}
|
|
else{
|
|
float co = Cos(TurnAngle);
|
|
float si = Sin(TurnAngle);
|
|
CentrX = round(x*co - y*si);
|
|
CentrY = round(x*si + y*co);
|
|
CentrZ = ViewZ;
|
|
}
|
|
|
|
A_convert = A_g2s*A_shape*DBM(shape_scale_x,0,0,
|
|
0,shape_scale_y,0,
|
|
0,0,shape_scale_z);
|
|
Refl = A_shape_inv*Light;
|
|
|
|
int direct;
|
|
Polygon** sort_poly;
|
|
double vx = -A_convert.a[6];
|
|
double vy = -A_convert.a[7];
|
|
double vz = -A_convert.a[8];
|
|
if(fabs(vz) >= fabs(vy))
|
|
if(fabs(vz) >= fabs(vx)){
|
|
sort_poly = sorted_polygons[Z_AXIS];
|
|
direct = SIGN(vz);
|
|
}
|
|
else{
|
|
sort_poly = sorted_polygons[X_AXIS];
|
|
direct = -SIGN(vx);
|
|
}
|
|
else
|
|
if(fabs(vx) > fabs(vy)){
|
|
sort_poly = sorted_polygons[X_AXIS];
|
|
direct = -SIGN(vx);
|
|
}
|
|
else{
|
|
sort_poly = sorted_polygons[Y_AXIS];
|
|
direct = -SIGN(vy);
|
|
}
|
|
|
|
for(register int i = 0;i < num_vert;i++)
|
|
vertices[i].convert_big();
|
|
|
|
int i;
|
|
for(i = 0;i < num_norm;i++)
|
|
normals[i].fast_calc_intensity();
|
|
|
|
if(direct > 0){
|
|
for(i = 0;i < num_poly;i++)
|
|
sort_poly[i] -> draw_gouraud_big();
|
|
}
|
|
else{
|
|
for(i = num_poly - 1;i >= 0;i--)
|
|
sort_poly[i] -> draw_gouraud_big();
|
|
}
|
|
}
|
|
void Vertex::convert_big()
|
|
{
|
|
turned = A_convert*DBV(x,y,z);
|
|
// int zz = CentrZ + turned.z;
|
|
// if(zz <= 0)
|
|
// zz = 1;
|
|
// xscr = (turned.x + CentrX)*focus/(zz) + ScreenCX;
|
|
// yscr = (turned.y + CentrY)*focus/(zz) + ScreenCY;
|
|
xscr = turned.x + CentrX + ScreenCX;
|
|
yscr = turned.y + CentrY + ScreenCY;
|
|
}
|
|
void Polygon::draw_gouraud_big()
|
|
{
|
|
#ifdef COMPACT_3D
|
|
const num_vert = 3;
|
|
#endif
|
|
#define NEXT_LEFT(p) ((p) == beg ? end : (p) - 1)
|
|
#define NEXT_RIGHT(p) ((p) == end ? beg : (p) + 1)
|
|
|
|
int xl,xr,al,ar,bl,br,d,where,Y;
|
|
int cl,cr,ckl,ckr;
|
|
int cf,cfk;
|
|
int x1,x2,len;
|
|
Vertex *lfv,*rfv,*ltv,*rtv;
|
|
Vertex **lto,**rto;
|
|
Vertex **beg,**curr,**up,**end;
|
|
Normal *lfn,*rfn,*ltn,*rtn;
|
|
unsigned char* vp;
|
|
|
|
beg = up = curr = vertices;
|
|
end = vertices + num_vert - 1;
|
|
curr++;
|
|
int t;
|
|
int x_left = (*beg) -> xscr;
|
|
int x_right = x_left;
|
|
int y_up = (*beg) -> yscr;
|
|
int y_down = y_up;
|
|
for(;curr <= end;curr++){
|
|
if(y_up > (t = (*curr) -> yscr)){
|
|
up = curr;
|
|
y_up = t;
|
|
}
|
|
if(y_down < t)
|
|
y_down = t;
|
|
if(x_left > (t = (*curr) -> xscr))
|
|
x_left = t;
|
|
if(x_right < t)
|
|
x_right = t;
|
|
}
|
|
|
|
if(y_down < VcutUp || y_up > VcutDown ||
|
|
x_right < UcutLeft || x_left > UcutRight)
|
|
return;
|
|
|
|
rfv = lfv = *up;
|
|
rfn = lfn = normals[up - beg];
|
|
|
|
lto = NEXT_LEFT(up);
|
|
ltv = *lto;
|
|
ltn = normals[lto - beg];
|
|
|
|
rto = NEXT_RIGHT(up);
|
|
rtv = *rto;
|
|
rtn = normals[rto - beg];
|
|
|
|
Y = lfv -> yscr; xl = lfv -> xscr;
|
|
al = ltv -> xscr - xl; bl = ltv -> yscr - Y;
|
|
ar = rtv -> xscr - xl; br = rtv -> yscr - Y;
|
|
xr = xl = (xl << 16) + (1 << 15);
|
|
|
|
cl = lfn -> I_8;
|
|
ckl = ltn -> I_8 - cl;
|
|
ckr = rtn -> I_8 - cl;
|
|
cr = cl <<= 7;
|
|
|
|
if(bl){
|
|
DIV16(al,bl);
|
|
ckl = (ckl << 7)/bl;
|
|
}
|
|
else
|
|
al <<= 16;
|
|
|
|
if(br){
|
|
DIV16(ar,br);
|
|
ckr = (ckr << 7)/br;
|
|
}
|
|
else
|
|
ar <<= 16;
|
|
|
|
vp = XGR_VIDEOBUF + Y*XGR_MAXX;
|
|
while(1){
|
|
if(bl > br){
|
|
d = br;
|
|
where = 0;
|
|
}
|
|
else{
|
|
d = bl;
|
|
where = 1;
|
|
}
|
|
while(d-- > 0){
|
|
x1 = xl >> 16;
|
|
x2 = xr >> 16;
|
|
if(x1 > x2)
|
|
return;
|
|
if(x1 < x2){
|
|
if(Y >= VcutUp && Y < VcutDown &&
|
|
x2 >= UcutLeft && x1 < UcutRight){
|
|
len = x2 - x1;
|
|
cf = cl;
|
|
cfk = (cr - cl)/len;
|
|
if(x1 < UcutLeft){
|
|
cf += cfk*(UcutLeft - x1);
|
|
x1 = UcutLeft;
|
|
len = x2 - x1;
|
|
}
|
|
if(x2 >= UcutRight){
|
|
x2 = UcutRight;
|
|
len = x2 - x1;
|
|
}
|
|
vp += x1;
|
|
while(len--){
|
|
*(vp++) = COLOR_OFFSET + (cf >> COLOR_SHIFT + 7);
|
|
cf += cfk;
|
|
}
|
|
vp -= x2;
|
|
}
|
|
}
|
|
Y++;
|
|
vp += XGR_MAXX;
|
|
|
|
xl += al;
|
|
xr += ar;
|
|
|
|
cl += ckl;
|
|
cr += ckr;
|
|
}
|
|
if(where){
|
|
if(ltv == rtv) return;
|
|
lfv = ltv;
|
|
lfn = ltn;
|
|
lto = NEXT_LEFT(lto);
|
|
ltv = *lto;
|
|
ltn = normals[lto - beg];
|
|
|
|
br -= bl;
|
|
|
|
xl = lfv -> xscr;
|
|
al = ltv -> xscr - xl;
|
|
bl = ltv -> yscr - Y;
|
|
xl = (xl << 16) + (1 << 15);
|
|
|
|
cl = lfn -> I_8;
|
|
ckl = ltn -> I_8 - cl;
|
|
cl <<= 7;
|
|
|
|
if(bl){
|
|
DIV16(al,bl);
|
|
ckl = (ckl << 7)/bl;
|
|
}
|
|
else{
|
|
al <<= 16;
|
|
}
|
|
}
|
|
else {
|
|
if(rtv == ltv) return;
|
|
rfv = rtv;
|
|
rfn = rtn;
|
|
rto = NEXT_RIGHT(rto);
|
|
rtv = *rto;
|
|
rtn = normals[rto - beg];
|
|
|
|
bl -= br;
|
|
|
|
xr = rfv -> xscr;
|
|
ar = rtv -> xscr - xr;
|
|
br = rtv -> yscr - Y;
|
|
xr = (xr << 16) + (1 << 15);
|
|
|
|
cr = rfn -> I_8;
|
|
ckr = rtn -> I_8 - cr;
|
|
cr <<= 7;
|
|
|
|
if(br){
|
|
DIV16(ar,br);
|
|
ckr = (ckr << 7)/br;
|
|
}
|
|
else
|
|
ar <<= 16;
|
|
}
|
|
}
|
|
}
|
|
/*******************************************************************************
|
|
Height projection
|
|
*******************************************************************************/
|
|
void Model::height_project()
|
|
{
|
|
int x,x_min = INT_INF,x_max = -INT_INF;
|
|
int y,y_min = INT_INF,y_max = -INT_INF;
|
|
int z,z_min = INT_INF,z_max = -INT_INF;
|
|
A_convert = A_shape*DBM(shape_scale_x,0,0,
|
|
0,shape_scale_y,0,
|
|
0,0,shape_scale_z);
|
|
|
|
for(int i = 0;i < num_vert;i++){
|
|
vertices[i].turned = A_convert*DBV(vertices[i].x,vertices[i].y,vertices[i].z);
|
|
if((x = vertices[i].turned.x) < x_min)
|
|
x_min = x;
|
|
if((x = vertices[i].turned.x) > x_max)
|
|
x_max = x;
|
|
if((y = vertices[i].turned.y) < y_min)
|
|
y_min = y;
|
|
if((y = vertices[i].turned.y) > y_max)
|
|
y_max = y;
|
|
if((z = -vertices[i].turned.z) < z_min)
|
|
z_min = z;
|
|
if((z = vertices[i].turned.z) > z_max)
|
|
z_max = z;
|
|
}
|
|
|
|
shape_offset = max(x_max - x_min,y_max - y_min)/2 + 2;
|
|
shape_size = max(x_max - x_min,y_max - y_min) + 2;
|
|
shape_shift = BitSR(shape_size) + 1;
|
|
|
|
shape_x = x_off + x_min - 1;
|
|
shape_y = y_off + y_min;
|
|
|
|
shape_x_avr = (x_max - x_min)/2;
|
|
shape_y_avr = (y_max - y_min)/2;
|
|
shape_z_avr = (z_max - z_min)/2 + 1;
|
|
|
|
#ifndef _SHAPE_
|
|
upper_buffer = new unsigned char[shape_size << shape_shift];
|
|
lower_buffer = new unsigned char[shape_size << shape_shift];
|
|
#endif
|
|
memset(upper_buffer,0,shape_size << shape_shift);
|
|
memset(lower_buffer,255,shape_size << shape_shift);
|
|
|
|
int i;
|
|
for(i = 0;i < num_vert;i++){
|
|
vertices[i].xscr = vertices[i].turned.x - x_min;
|
|
vertices[i].yscr = vertices[i].turned.y - y_min;
|
|
vertices[i].turned.z = -vertices[i].turned.z - z_min + 1;
|
|
}
|
|
|
|
for(i = 0;i < num_poly;i++)
|
|
polygons[i].height_project();
|
|
|
|
#ifdef _SHAPE_
|
|
c_putspr(shape_x,shape_y,1 << shape_shift,shape_size,upper_buffer,BLACK_FON);
|
|
// c_putspr(shape_x,shape_y - shape_size/2 - 2,1 << shape_shift,shape_size,upper_buffer,BLACK_FON);
|
|
// c_putspr(shape_x,shape_y + shape_size/2 + 2,1 << shape_shift,shape_size,lower_buffer,BLACK_FON);
|
|
#endif
|
|
}
|
|
void Polygon::height_project()
|
|
{
|
|
#ifdef COMPACT_3D
|
|
const num_vert = 3;
|
|
#endif
|
|
#define NEXT_LEFT(p) ((p) == beg ? end : (p) - 1)
|
|
#define NEXT_RIGHT(p) ((p) == end ? beg : (p) + 1)
|
|
|
|
int xl,xr,al,ar,bl,br,d,where,Y;
|
|
int cl,cr,ckl,ckr;
|
|
int cf,cfk,z;
|
|
int x1,x2,len,swap_log;
|
|
Vertex *lfv,*rfv,*ltv,*rtv;
|
|
Vertex **lto,**rto;
|
|
Vertex **beg,**curr,**up,**end;
|
|
unsigned char *up_vp;
|
|
unsigned char *lo_vp;
|
|
|
|
beg = up = curr = vertices;
|
|
end = vertices + num_vert - 1;
|
|
curr++;
|
|
for(;curr <= end;curr++)
|
|
if((*up) -> yscr > (*curr) -> yscr)
|
|
up = curr;
|
|
|
|
rfv = lfv = *up;
|
|
|
|
lto = NEXT_LEFT(up);
|
|
ltv = *lto;
|
|
|
|
rto = NEXT_RIGHT(up);
|
|
rtv = *rto;
|
|
|
|
Y = lfv -> yscr; xl = lfv -> xscr;
|
|
al = ltv -> xscr - xl; bl = ltv -> yscr - Y;
|
|
ar = rtv -> xscr - xl; br = rtv -> yscr - Y;
|
|
xr = xl = (xl << 16) + (1 << 15);
|
|
|
|
cl = lfv -> turned.z;
|
|
ckl = ltv -> turned.z - cl;
|
|
ckr = rtv -> turned.z - cl;
|
|
cr = cl <<= 16;
|
|
|
|
if(bl){
|
|
DIV16(al,bl);
|
|
DIV16(ckl,bl);
|
|
}
|
|
|
|
if(br){
|
|
DIV16(ar,br);
|
|
DIV16(ckr,br);
|
|
}
|
|
|
|
up_vp = upper_buffer + (Y << shape_shift);
|
|
lo_vp = lower_buffer + (Y << shape_shift);
|
|
|
|
while(1){
|
|
if(bl > br){
|
|
d = br;
|
|
where = 0;
|
|
}
|
|
else{
|
|
d = bl;
|
|
where = 1;
|
|
}
|
|
while(d-- > 0){
|
|
x1 = xl >> 16;
|
|
x2 = xr >> 16;
|
|
if(x1 != x2){
|
|
if(x1 > x2){
|
|
SWAP(x1,x2);
|
|
SWAP(cl,cr);
|
|
swap_log = 1;
|
|
}
|
|
else
|
|
swap_log = 0;
|
|
len = x2 - x1;
|
|
cf = cl;
|
|
cfk = (cr - cl)/len;
|
|
up_vp += x1;
|
|
lo_vp += x1;
|
|
while(len--){
|
|
z = cf >> 16;
|
|
if(z > 0 && z < 256){
|
|
if(*up_vp < z)
|
|
*up_vp = z;
|
|
if(*lo_vp > z)
|
|
*lo_vp = z;
|
|
}
|
|
#ifdef _FOUT_
|
|
else
|
|
fout < "High project: Over/under-flow: " <= z < "\n";
|
|
#endif
|
|
cf += cfk;
|
|
up_vp++;
|
|
lo_vp++;
|
|
}
|
|
up_vp -= x2;
|
|
lo_vp -= x2;
|
|
if(swap_log)
|
|
SWAP(cl,cr);
|
|
}
|
|
Y++;
|
|
up_vp += 1 << shape_shift;
|
|
lo_vp += 1 << shape_shift;
|
|
|
|
xl += al;
|
|
xr += ar;
|
|
|
|
cl += ckl;
|
|
cr += ckr;
|
|
}
|
|
if(where){
|
|
if(ltv == rtv) return;
|
|
lfv = ltv;
|
|
lto = NEXT_LEFT(lto);
|
|
ltv = *lto;
|
|
|
|
br -= bl;
|
|
|
|
xl = lfv -> xscr;
|
|
al = ltv -> xscr - xl;
|
|
bl = ltv -> yscr - Y;
|
|
xl = (xl << 16) + (1 << 15);
|
|
|
|
cl = lfv -> turned.z;
|
|
ckl = ltv -> turned.z - cl;
|
|
cl <<= 16;
|
|
|
|
if(bl){
|
|
DIV16(al,bl);
|
|
DIV16(ckl,bl);
|
|
}
|
|
}
|
|
else {
|
|
if(rtv == ltv) return;
|
|
rfv = rtv;
|
|
rto = NEXT_RIGHT(rto);
|
|
rtv = *rto;
|
|
|
|
bl -= br;
|
|
|
|
xr = rfv -> xscr;
|
|
ar = rtv -> xscr - xr;
|
|
br = rtv -> yscr - Y;
|
|
xr = (xr << 16) + (1 << 15);
|
|
|
|
cr = rfv -> turned.z;
|
|
ckr = rtv -> turned.z - cr;
|
|
cr <<= 16;
|
|
|
|
if(br){
|
|
DIV16(ar,br);
|
|
DIV16(ckr,br);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|