home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 21
/
CD_ASCQ_21_040595.iso
/
dos
/
graphic
/
font3d11
/
f3d_src
/
build.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-12
|
18KB
|
498 lines
//=================================================================================================
// Build.CPP
//-------------------------------------------------------------------------------------------------
//
// Copyright (c) 1994 by Todd A. Prater
// All rights reserved.
//
//=================================================================================================
#include <stdlib.h>
#include <fstream.h>
#include "Config.H"
#include "Vector.H"
#include "TrueType.H"
#include "Geometry.H"
#include "Build.H"
#define IGNORE 2
#define INSIDE 1
#define OUTSIDE 0
// ******************************************************
// NOTE: Please excuse the debugging code
// ******************************************************
//===========================================================================================================
// PolygonizeContour
//-----------------------------------------------------------------------------------------------------------
//===========================================================================================================
void PolygonizeContour(TTFont& font,
USHORT glyphnum,
USHORT contournum,
USHORT resolution,
DOUBLE depth,
POLYGON& polygon )
{
ULONG i,j;
ULONG polyi;
ULONG offcount;
ULONG consecutiveoffcount;
INT lastwasoff;
VECTOR cp1,cp2,cp3,cur_point,prev_point,next_point;
DOUBLE tstep;
if (font.NumContours(glyphnum)<1)
return;
if (contournum>=font.NumContours(glyphnum))
return;
if(polygon.numpoints>0)
{
delete polygon.pointlist;
polygon.numpoints=0;
}
lastwasoff=0;
consecutiveoffcount=0;
offcount=0;
for(i=0;i<font.NumPoints(glyphnum,contournum);i++)
{
// if (font.FontPointType(glyphnum,contournum,i)==ON_CURVE) cout<<i<<": ON"<<endl;
// else cout<<i<<": OFF"<<endl;
if(font.FontPointType(glyphnum,contournum,i)==OFF_CURVE)
{
offcount++;
if(lastwasoff)
consecutiveoffcount++;
lastwasoff=1;
}
else
lastwasoff=0;
}
polygon.numpoints = font.NumPoints(glyphnum,contournum) + offcount*(resolution-2) + consecutiveoffcount;
polygon.pointlist = new VECTOR[polygon.numpoints+40]; // Temporary fix (give some playing room...)
polyi=0;
// pointcount = font.NumPoints(glyphnum,contournum);
for(i=0;i<font.NumPoints(glyphnum,contournum);i++)
{
if (font.FontPointType(glyphnum,contournum,i)==ON_CURVE)
{
//cout<<"OnCURVE: "<<i<<endl;
polygon.pointlist[polyi] = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(), depth);
polyi++;
}
else
{
//cout<<"OffCURVE: "<<i<<endl;
if(font.FontPointType(glyphnum,contournum,i-1)==ON_CURVE)
{
cp1 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i-1)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,i-1)/(DOUBLE)font.UnitsPerEm(), depth);
}
else
{
cp1 = VECTOR(((DOUBLE)font.FontPointX(glyphnum,contournum,i-1)+(DOUBLE)font.FontPointX(glyphnum,contournum,i))/2/(DOUBLE)font.UnitsPerEm(),
((DOUBLE)font.FontPointY(glyphnum,contournum,i-1)+(DOUBLE)font.FontPointY(glyphnum,contournum,i))/2/(DOUBLE)font.UnitsPerEm(), depth);
}
cp2 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(), depth);
if (i==(font.NumPoints(glyphnum,contournum)-1))
{
//cout<<"THE LAST ONE"<<endl;
cp3 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,0)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,0)/(DOUBLE)font.UnitsPerEm(), depth);
}
else
{
if(font.FontPointType(glyphnum,contournum,i+1)==ON_CURVE)
{
cp3 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i+1)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,i+1)/(DOUBLE)font.UnitsPerEm(), depth);
i++;
}
else
{
cp3 = VECTOR(((DOUBLE)font.FontPointX(glyphnum,contournum,i)+(DOUBLE)font.FontPointX(glyphnum,contournum,i+1))/2/(DOUBLE)font.UnitsPerEm(),
((DOUBLE)font.FontPointY(glyphnum,contournum,i)+(DOUBLE)font.FontPointY(glyphnum,contournum,i+1))/2/(DOUBLE)font.UnitsPerEm(), depth);
}
}
tstep = 1.0/(DOUBLE)resolution;
for(j=0;j<resolution;j++)
{
polygon.pointlist[polyi] = ApproximateQuadraticSpline(cp1,cp2,cp3,tstep*(j+1));
polyi++;
}
}
}
if ( (polygon.pointlist[polyi-1].x==polygon.pointlist[0].x)
&& (polygon.pointlist[polyi-1].y==polygon.pointlist[0].y))
{
//cout<<"LAST IS FIRST"<<endl;
polyi--; //temporary fix....
}
polygon.numpoints = polyi;
polygon.orientation = polygon.findOrientation();
//cout<<polygon<<"P";
}
//===========================================================================================================
// TriangulateFace
//-----------------------------------------------------------------------------------------------------------
//===========================================================================================================
void TriangulateFace (TTFont& font,
USHORT glyphnum,
USHORT resolution,
DOUBLE shrinkFactor,
LIST<TRIANGLE>& triangleList)
{
int i,j,k;
BOOLEAN isAPair;
SHORT contourCount;
POLYGON* polyarray;
POLYGON* shrunkpolyarray;
BYTEPTR* relationship;
contourCount = font.NumContours(glyphnum);
if (contourCount<1) return;
polyarray = new POLYGON[contourCount];
if (polyarray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
shrunkpolyarray=new POLYGON[contourCount];
if (shrunkpolyarray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
relationship = new BYTEPTR[contourCount];
if (relationship==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
for (i=0;i<contourCount;i++)
{
relationship[i] = new BYTE[contourCount];
if (relationship[i]==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
}
for (i=0;i<contourCount;i++)
{
PolygonizeContour(font,glyphnum,i,resolution,0.0,polyarray[i]);
if (shrinkFactor>0.0)
polyarray[i].Shrink(shrunkpolyarray[i],shrinkFactor);
}
for (i=0;i<contourCount;i++)
for (j=0;j<contourCount;j++)
if (i==j)
relationship[i][j]=IGNORE;
else if (polyarray[j].isInside(polyarray[i]))
relationship[i][j]=INSIDE;
else
relationship[i][j]=OUTSIDE;
for (i=0;i<contourCount;i++)
{
if (polyarray[i].orientation==CLOCKWISE)
{
for (j=0;j<contourCount;j++)
{
isAPair=FALSE;
if (relationship[i][j]==INSIDE && polyarray[j].orientation==COUNTER_CLOCKWISE)
{
isAPair=TRUE;
for (k=0;k<contourCount;k++)
{
if (k==j || k==i || relationship[k][j]==IGNORE) continue;
if (relationship[k][j]==INSIDE)
{
if (relationship[i][k]==INSIDE)
{
isAPair=FALSE;
exit;
}
}
else
continue;
}
}
if (isAPair)
{
if (shrinkFactor>0.0)
shrunkpolyarray[i].Combine(shrunkpolyarray[j]);
else
polyarray[i].Combine(polyarray[j]);
relationship[i][j]=IGNORE;
}
}
}
}
for (i=0;i<contourCount;i++)
{
if (polyarray[i].orientation==CLOCKWISE)
{
if (shrinkFactor>0.0)
shrunkpolyarray[i].Triangulate(triangleList);
else
polyarray[i].Triangulate(triangleList);
}
}
for (i=0;i<contourCount;i++)
{
delete polyarray[i].pointlist;
delete shrunkpolyarray[i].pointlist;
delete relationship[i];
}
delete polyarray;
delete shrunkpolyarray;
delete relationship;
}
//===========================================================================================================
// TriangulateEdges
//-----------------------------------------------------------------------------------------------------------
//===========================================================================================================
void TriangulateEdges(TTFont& font,
USHORT glyphnum,
USHORT resolution,
INT effects,
DOUBLE frontDepth,
DOUBLE backDepth,
DOUBLE faceShrink,
DOUBLE edgeShrink,
DOUBLE angleThreshold,
LIST<TRIANGLE>& edgeList,
LIST<TRIANGLE>& bevelList)
{
INT i,j;
TRIANGLE* t1;
TRIANGLE* t2;
TRIANGLE* t3;
TRIANGLE* t4;
TRIANGLE* t5;
TRIANGLE* t6;
VECTOR tt1,tt2,tt3,tt4;
VECTOR previous,current1,current2,next;
VECTOR shrunkCurrent1,shrunkCurrent2;
VECTOR previousFacet,currentFacet,nextFacet;
VECTOR previousFacetNormal,currentFacetNormal,nextFacetNormal;
VECTOR averageNormal1,averageNormal2;
VECTOR frontBevelNormal1,frontBevelNormal2,backBevelNormal1,backBevelNormal2;
VECTOR p1,p2,p3,p4,p5,p6,p7,p8;
ULONG numberOfPoints;
SHORT contourCount;
POLYGON* polyarray;
POLYGON* shrunkPolyarray;
VECTOR zDir(0,0,1);
DOUBLE angle1,angle2;
BOOLEAN doBevels=TRUE;
contourCount = font.NumContours(glyphnum);
if (contourCount<1) return;
polyarray = new POLYGON[contourCount];
if (polyarray==NULL)
{
cout<<"ERROR: Out of memory."<<endl;
exit(1);
}
if (faceShrink==0.0 && edgeShrink==0.0) doBevels=FALSE;
if (doBevels)
{
shrunkPolyarray = new POLYGON[contourCount];
if (shrunkPolyarray==NULL)
{
cout<<"ERROR: Out of memory."<<endl;
exit(1);
}
}
for (i=0;i<contourCount;i++)
{
PolygonizeContour(font,glyphnum,i,resolution,0.0,polyarray[i]);
if (doBevels) polyarray[i].Shrink(shrunkPolyarray[i],faceShrink);
}
for (i=0;i<contourCount;i++)
{
numberOfPoints = polyarray[i].numpoints;
for (j=0;j<numberOfPoints;j++)
{
if (j==numberOfPoints-2)
{
previous = polyarray[i].pointlist[j-1];
current1 = polyarray[i].pointlist[j];
if (doBevels) shrunkCurrent1 = shrunkPolyarray[i].pointlist[j];
current2 = polyarray[i].pointlist[j+1];
if (doBevels) shrunkCurrent2 = shrunkPolyarray[i].pointlist[j+1];
next = polyarray[i].pointlist[0];
}
else if (j==numberOfPoints-1)
{
previous = polyarray[i].pointlist[j-1];
current1 = polyarray[i].pointlist[j];
if (doBevels) shrunkCurrent1 = shrunkPolyarray[i].pointlist[j];
current2 = polyarray[i].pointlist[0];
if (doBevels) shrunkCurrent2 = shrunkPolyarray[i].pointlist[0];
next = polyarray[i].pointlist[1];
}
else if (j==0)
{
previous = polyarray[i].pointlist[numberOfPoints-1];
current1 = polyarray[i].pointlist[j];
if (doBevels) shrunkCurrent1 = shrunkPolyarray[i].pointlist[j];
current2 = polyarray[i].pointlist[j+1];
if (doBevels) shrunkCurrent2 = shrunkPolyarray[i].pointlist[j+1];
next = polyarray[i].pointlist[j+2];
}
else
{
previous = polyarray[i].pointlist[j-1];
current1 = polyarray[i].pointlist[j];
if (doBevels) shrunkCurrent1 = shrunkPolyarray[i].pointlist[j];
current2 = polyarray[i].pointlist[j+1];
if (doBevels) shrunkCurrent2 = shrunkPolyarray[i].pointlist[j+1];
next = polyarray[i].pointlist[j+2];
}
previousFacet = ~(current1-previous);
currentFacet = ~(current2-current1);
nextFacet = ~(next-current2);
previousFacetNormal = zDir^previousFacet;
currentFacetNormal = zDir^currentFacet;
nextFacetNormal = zDir^nextFacet;
angle1 = acos(previousFacetNormal%currentFacetNormal);
angle2 = acos(currentFacetNormal%nextFacetNormal);
if (angle1<angleThreshold)
averageNormal1 = ~(previousFacetNormal+currentFacetNormal);
else
averageNormal1 = currentFacetNormal;
tt1 = zDir*edgeShrink;
tt2 = averageNormal1*faceShrink;
tt3 = tt1+tt2;
tt4 = tt2-tt1;
if (doBevels) frontBevelNormal1 = ~(tt3);
if (doBevels) backBevelNormal1 = ~(tt4);
if (angle2<angleThreshold)
averageNormal2 = ~(currentFacetNormal+nextFacetNormal);
else
averageNormal2 = currentFacetNormal;
if (doBevels) frontBevelNormal2 = ~(zDir*edgeShrink + averageNormal2*faceShrink);
if (doBevels) backBevelNormal2 = ~(-zDir*edgeShrink + averageNormal2*faceShrink);
if (doBevels) p1 = shrunkCurrent1; p1.z=frontDepth;
if (doBevels) p2 = shrunkCurrent2; p2.z=frontDepth;
p3 = current1 ; p3.z=frontDepth-edgeShrink;
p4 = current2 ; p4.z=frontDepth-edgeShrink;
p5 = current1 ; p5.z=backDepth+edgeShrink;
p6 = current2 ; p6.z=backDepth+edgeShrink;
if (doBevels) p7 = shrunkCurrent1; p7.z=backDepth;
if (doBevels) p8 = shrunkCurrent2; p8.z=backDepth;
t3 = new TRIANGLE(p3,p5,p6,averageNormal1,averageNormal1,averageNormal2);
if (t3==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t4 = new TRIANGLE(p3,p6,p4,averageNormal1,averageNormal2,averageNormal2);
if (t4==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
if (doBevels)
{
if (effects==BEVEL)
{
t1 = new TRIANGLE(p1,p2,p3,frontBevelNormal1,frontBevelNormal2,frontBevelNormal1);
if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t2 = new TRIANGLE(p2,p3,p4,frontBevelNormal2,frontBevelNormal1,frontBevelNormal2);
if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t5 = new TRIANGLE(p5,p7,p6,backBevelNormal1,backBevelNormal1,backBevelNormal2);
if (t5==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t6 = new TRIANGLE(p7,p8,p6,backBevelNormal1,backBevelNormal2,backBevelNormal2);
if (t6==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
}
else
{
t1 = new TRIANGLE(p1,p2,p3,zDir,zDir,averageNormal1);
if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t2 = new TRIANGLE(p2,p3,p4,zDir,averageNormal1,averageNormal2);
if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t5 = new TRIANGLE(p5,p7,p6,averageNormal1,-zDir,averageNormal2);
if (t5==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t6 = new TRIANGLE(p7,p8,p6,-zDir,-zDir,averageNormal2);
if (t6==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
}
}
edgeList.Add(t3);
edgeList.Add(t4);
if (doBevels)
{
bevelList.Add(t1);
bevelList.Add(t2);
bevelList.Add(t5);
bevelList.Add(t6);
}
}
}
for (i=0;i<contourCount;i++)
{
delete polyarray[i].pointlist;
if (doBevels) delete shrunkPolyarray[i].pointlist;
}
delete polyarray;
if (doBevels) delete shrunkPolyarray;
}