home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
oct93
/
graphics
/
graphtal.lha
/
Graphtal
/
FlatDevice.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-17
|
6KB
|
242 lines
/*
* FlatDevice.C - zBuffer device driver.
*
* Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
* University of Berne, Switzerland
* All rights reserved.
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
*/
#include "FlatDevice.h"
#include "Polygon.h"
#include "Sphere.h"
static const int defaultConeResolution = 5;
static const int defaultSphereResolution = 4;
//___________________________________________________________ PolyWithColor
class PolyWithColor {
friend class FlatDevice;
public:
PolyWithColor()
: p(NULL) {}
PolyWithColor(Polygon* poly, const Color& color)
: p(poly), c(color) {}
~PolyWithColor() { if (p) delete p; }
private:
Polygon* p;
Color c;
};
typedef PolyWithColor* PolyWithColorPtr;
declareList(PolyWithColorList, PolyWithColorPtr);
implementList(PolyWithColorList, PolyWithColorPtr);
//___________________________________________________________ FlatDevice
FlatDevice::FlatDevice(Options* options)
: DeviceDriver(options), polys(NULL)
{
coneResolution = (theOptions->coneResolution <= 0)
? defaultConeResolution
: theOptions->coneResolution;
sphereResolution = (theOptions->sphereResolution <= 0)
? defaultSphereResolution
: theOptions->sphereResolution;
/*
* Make up table for cone generation.
*/
sintable = new real[coneResolution];
costable = new real[coneResolution];
real alpha;
for (register int i=0; i<coneResolution; i++) {
alpha = (2*M_PI*i)/coneResolution;
SinCos(alpha, sintable[i], costable[i]);
}
top = new Vector[coneResolution];
bottom = new Vector[coneResolution];
/*
* Generate unit sphere.
*/
unitSphere = Sphere::tesselation(Vector(0,0,0), 1, sphereResolution);
/*
* Initialize z-buffer renderer
*/
zBuffer = new Z_Buffer(new ViewTransform(theOptions->eye,
theOptions->lookat,
theOptions->up, theOptions->fov,
theOptions->resX, theOptions->resY),
"Image rendered with graphtal",
theOptions->oname);
}
FlatDevice::~FlatDevice()
{
delete [] sintable;
delete [] costable;
delete [] top;
delete [] bottom;
for (register long i=0; i<unitSphere->count(); i++)
delete unitSphere->item(i);
delete unitSphere;
delete zBuffer;
StringTable_Iterator macroItr(macroNames);
while(macroItr.more()){
PolyWithColorList* polyList = (PolyWithColorList*) macroItr.cur_value();
for (i = 0; i<polyList->count(); i++)
delete polyList->item(i);
delete polyList;
macroItr.next();
}
}
void FlatDevice::begin(){}
void FlatDevice::end(const BoundingBox&)
{
if (theOptions->verbose)
cerr << "primitives: "<< zBuffer->primitives() << '\n';
zBuffer->writePixmap();
}
void FlatDevice::cylinder(const Vector& p1, const Vector& p2, real r)
{
cone(p1, r, p2, r);
}
void FlatDevice::cone(const Vector& p1, real r1, const Vector& p2, real r2)
{
Vector axis = p2 - p1;
/*
* Degenerated cone?
*/
if (axis.normalize() == 0)
return;
Vector u, v;
/*
* Find 2 vectors normal to cone axis and to each other.
*/
u[0] = -axis[1]; u[1] = axis[0]; u[2] = 0;
if (u.normalize() == 0) {
u[0] = axis[2]; u[1] = 0; u[2] = -axis[0];
u.normalize();
}
v = axis*u;
Vector d;
for (register int i=0; i<coneResolution; i++) {
d = costable[i]*u + sintable[i]*v;
*(bottom+i) = p1 + d*r1;
*(top+i) = p2 + d*r2;
}
for (i=0; i<coneResolution; i++) {
if (definingMacro) {
Polygon* p = new Polygon(*(bottom+i), *(top+i),
*(top+((i+1)%coneResolution)),
*(bottom+((i+1)%coneResolution)));
PolyWithColor* pwc = new PolyWithColor(p, currentColor);
polys->append(pwc);
}
else
zBuffer->renderRectangle(currentColor,
*(bottom+i), *(top+i),
*(top+((i+1)%coneResolution)),
*(bottom+((i+1)%coneResolution)));
}
}
void FlatDevice::polygon(Polygon* p)
{
if (definingMacro) {
PolyWithColor* pwc = new PolyWithColor(p, currentColor);
polys->append(pwc);
}
else
zBuffer->renderPolygon(currentColor, p);
}
void FlatDevice::sphere(const Vector& pos, real r)
{
/*
* Transform the unit sphere to radius r and position pos.
*/
for (register long i=0; i<unitSphere->count(); i++) {
Polygon* p = unitSphere->item(i);
Polygon* transformedPoly = new Polygon(p->numVertices());
for (register long j=0; j<p->numVertices(); j++)
transformedPoly->addVertex(p->vertex(j)*r+pos);
if (definingMacro) {
PolyWithColor* pwc = new PolyWithColor(transformedPoly, currentColor);
polys->append(pwc);
}
else
zBuffer->renderPolygon(currentColor, transformedPoly);
}
}
void FlatDevice::color(const Color& color)
{
currentColor = color;
}
void FlatDevice::beginMacro(const rcString& macroName)
{
definingMacro = 1;
currentMacroName = macroName;
polys = new PolyWithColorList(100);
}
void FlatDevice::endMacro()
{
definingMacro = 0;
macroNames.find_and_replace(currentMacroName, polys);
polys = NULL;
}
void FlatDevice::executeMacro(const rcString& macroName,
const TransMatrix& tmat)
{
anyPtr argument;
if (!macroNames.lookup(macroName, argument))
Error(ERR_PANIC, "FlatDevice::executeMacro: macro "
+ macroName + " does not exist");
PolyWithColorList* polyList = (PolyWithColorList*) argument;
for (register long i=0; i<polyList->count(); i++) {
Polygon* p = new Polygon(*polyList->item(i)->p);
p->transform(tmat);
if (definingMacro) {
PolyWithColor* pwc = new PolyWithColor(p, polyList->item(i)->c);
polys->append(pwc);
}
else
zBuffer->renderPolygon(polyList->item(i)->c, p);
}
}