// Copyright (c) 1999 Philip A. Hardin (pahardin@cs.utexas.edu) // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License v2 or later. #include "panel3d.h" /*=========================================================================*/ void panel3d::SetNormalAndConvexity(const pt3d pts[]) { isConvex= true; if (ptNums.Num() >=3) { // compute normal // use Newell's formulation (Foley, Van Dam, Feiner, & Hughes, pp. 477) normal= pt3d(0,0,0); // Remember, ptNums[0] is the same as ptNums[ptNums.Num()-1], // so we have to be careful below: int j= ptNums.Num()-2; forii(ptNums.Num()-1) { const pt3d& pt1= pts[ptNums[j]]; const pt3d& pt2= pts[ptNums[i]]; normal.x += (pt1.y - pt2.y) *(pt1.z + pt2.z); normal.y += (pt1.z - pt2.z) *(pt1.x + pt2.x); normal.z += (pt1.x - pt2.x) *(pt1.y + pt2.y); j =i; } normal.Normalize(); // Remember, ptNums[0] is the same as ptNums[ptNums.Num()-1], // so we have to be careful below: fori(ptNums.Num()-1) { j= (i+1) % (ptNums.Num()-1); // index of second point number int k= (i+2) % (ptNums.Num()-1); // index of third point number // compute the normal for this particular sequence of three points pt3d norm3= (pts[ptNums[j]]-pts[ptNums[i]]).CrossProd( pts[ptNums[k]]-pts[ptNums[j]]); // if the normal for these 3 pts is in the opposite direction as // the official normal for the polygon, then either these 3 pts form // a concave bend, so we know that this polygon is _not_ convex! if (norm3.Dot(normal) <0) isConvex= false; } } } /*-------------------------------------------------------------------------*/ /* In: srcPtNums = array of point numbers which define this panel, terminated by a negative value Out: srcPtNums = points one element past the terminating negative value Reads an initial number that indicates if the panel is single-sided (zero) or double-sided (non-zero). Then reads point numbers which define the panel until a negative point number is seen. The number of pt nums should equal the number of points in the panel. */ void panel3d::Init(int *&srcPtNums, pt3d pts[]) { if (ptNums.Num() >0) ptNums.Empty(); doubleSided= *(srcPtNums++); while (*srcPtNums >=0) ptNums.Add(*srcPtNums++); ptNums.Add(ptNums[0]); srcPtNums++; // advance past negative value SetNormalAndConvexity(pts); } /*-------------------------------------------------------------------------*/ // The region2d must have at least 2 sides, or else the panel3d will // simply be empty. panel3d::panel3d(const region2d& rgn, fastPts& pts, const pt3d& offset, const ang3d& ang, const pt3d& scale, bool isDoubleSided) { pt3d pt; int ptNum,firstPtNum; doubleSided= isDoubleSided; if (rgn.numSides >=2) { forii(rgn.numSides) { pt.x= rgn.sides[i].pt.x; pt.y= rgn.sides[i].pt.y; pt.z= 0; ptNum= pts.Add((pt*scale >> ang) +offset); if (i==0) firstPtNum= ptNum; ptNums.Add(ptNum); } ptNums.Add(firstPtNum); SetNormalAndConvexity(pts.Array()); } } /*-------------------------------------------------------------------------*/ panel3d::panel3d(const panel3d& p, pt3d panelPts[], fastPts& pts, const pt3d& offset, const ang3d& ang, const pt3d& scale) { doubleSided= p.doubleSided; forii(p.ptNums.Num()) { pt3d *pt= &panelPts[p.ptNums[i]]; int ptNum= pts.Add( ((*pt)*scale >> ang) +offset); ptNums.Add(ptNum); } SetNormalAndConvexity(pts.Array()); }