1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035 |
- #import "qedefs.h"
- @implementation SetBrush
- /*
- ==================
- textureAxisFromPlane
- ==================
- */
- #if 1
- vec3_t baseaxis[18] =
- {
- {0,0,1}, {1,0,0}, {0,-1,0}, // floor
- {0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling
- {1,0,0}, {0,1,0}, {0,0,-1}, // west wall
- {-1,0,0}, {0,1,0}, {0,0,-1}, // east wall
- {0,1,0}, {1,0,0}, {0,0,-1}, // south wall
- {0,-1,0}, {1,0,0}, {0,0,-1} // north wall
- };
- #else
- vec3_t baseaxis[18] =
- {
- {0,0,1}, {1,0,0}, {0,-1,0}, // floor
- {0,0,-1}, {1,0,0}, {0,1,0}, // ceiling
- {1,0,0}, {0,1,0}, {0,0,-1}, // west wall
- {-1,0,0}, {0,-1,0}, {0,0,-1}, // east wall
- {0,1,0}, {-1,0,0}, {0,0,-1}, // south wall
- {0,-1,0}, {1,0,0}, {0,0,-1} // north wall
- };
- #endif
- float TextureAxisFromPlane(plane_t *pln, float *xv, float *yv)
- {
- int bestaxis;
- float dot,best;
- int i;
-
- best = 0;
- bestaxis = 0;
-
- for (i=0 ; i<6 ; i++)
- {
- dot = DotProduct (pln->normal, baseaxis[i*3]);
- if (dot > best)
- {
- best = dot;
- bestaxis = i;
- }
- }
-
- VectorCopy (baseaxis[bestaxis*3+1], xv);
- VectorCopy (baseaxis[bestaxis*3+2], yv);
-
- return lightaxis[bestaxis>>1];
- }
- #define BOGUS_RANGE 18000
- /*
- =================
- CheckFace
- Note: this will not catch 0 area polygons
- =================
- */
- void CheckFace (face_t *f)
- {
- int i, j;
- float *p1, *p2;
- float d, edgedist;
- vec3_t dir, edgenormal;
- winding_t *w;
-
- w = f->w;
- if (!w)
- Error ("CheckFace: no winding");
-
- if (w->numpoints < 3)
- Error ("CheckFace: %i points",w->numpoints);
-
- for (i=0 ; i<w->numpoints ; i++)
- {
- p1 = w->points[i];
- for (j=0 ; j<3 ; j++)
- if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
- Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
- j = i+1 == w->numpoints ? 0 : i+1;
-
- // check the point is on the face plane
- d = DotProduct (p1, f->plane.normal) - f->plane.dist;
- if (d < -ON_EPSILON || d > ON_EPSILON)
- Error ("CheckFace: point off plane");
-
- // check the edge isn't degenerate
- p2 = w->points[j];
- VectorSubtract (p2, p1, dir);
-
- if (VectorLength (dir) < ON_EPSILON)
- Error ("CheckFace: degenerate edge");
-
- CrossProduct (f->plane.normal, dir, edgenormal);
- VectorNormalize (edgenormal);
- edgedist = DotProduct (p1, edgenormal);
- edgedist += ON_EPSILON;
-
- // all other points must be on front side
- for (j=0 ; j<w->numpoints ; j++)
- {
- if (j == i)
- continue;
- d = DotProduct (w->points[j], edgenormal);
- if (d > edgedist)
- Error ("CheckFace: non-convex");
- }
- }
- }
- /*
- =============================================================================
- TURN PLANES INTO GROUPS OF FACES
- =============================================================================
- */
- /*
- ==================
- NewWinding
- ==================
- */
- winding_t *NewWinding (int points)
- {
- winding_t *w;
- int size;
-
- if (points > MAX_POINTS_ON_WINDING)
- Error ("NewWinding: %i points", points);
-
- size = (int)((winding_t *)0)->points[points];
- w = malloc (size);
- memset (w, 0, size);
-
- return w;
- }
- /*
- ==================
- CopyWinding
- ==================
- */
- winding_t *CopyWinding (winding_t *w)
- {
- int size;
- winding_t *c;
-
- size = (int)((winding_t *)0)->points[w->numpoints];
- c = malloc (size);
- memcpy (c, w, size);
- return c;
- }
- /*
- ==================
- ClipWinding
- Clips the winding to the plane, returning the new winding on the positive side
- Frees the input winding.
- ==================
- */
- winding_t *ClipWinding (winding_t *in, plane_t *split)
- {
- float dists[MAX_POINTS_ON_WINDING];
- int sides[MAX_POINTS_ON_WINDING];
- int counts[3];
- float dot;
- int i, j;
- float *p1, *p2, *mid;
- winding_t *neww;
- int maxpts;
-
- counts[0] = counts[1] = counts[2] = 0;
- // determine sides for each point
- for (i=0 ; i<in->numpoints ; i++)
- {
- dot = DotProduct (in->points[i], split->normal);
- dot -= split->dist;
- dists[i] = dot;
- if (dot > ON_EPSILON)
- sides[i] = SIDE_FRONT;
- else if (dot < -ON_EPSILON)
- sides[i] = SIDE_BACK;
- else
- {
- sides[i] = SIDE_ON;
- }
- counts[sides[i]]++;
- }
- sides[i] = sides[0];
- dists[i] = dists[0];
-
- if (!counts[0] && !counts[1])
- return in;
-
- if (!counts[0])
- {
- free (in);
- return NULL;
- }
- if (!counts[1])
- return in;
-
- maxpts = in->numpoints+4; // can't use counts[0]+2 because
- // of fp grouping errors
- neww = NewWinding (maxpts);
-
- for (i=0 ; i<in->numpoints ; i++)
- {
- p1 = in->points[i];
-
- mid = neww->points[neww->numpoints];
- if (sides[i] == SIDE_FRONT || sides[i] == SIDE_ON)
- {
- VectorCopy (p1, mid);
- mid[3] = p1[3];
- mid[4] = p1[4];
- neww->numpoints++;
- if (sides[i] == SIDE_ON)
- continue;
- mid = neww->points[neww->numpoints];
- }
-
- if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
- continue;
-
- // generate a split point
- if (i == in->numpoints - 1)
- p2 = in->points[0];
- else
- p2 = p1 + 5;
-
- neww->numpoints++;
-
- dot = dists[i] / (dists[i]-dists[i+1]);
- for (j=0 ; j<3 ; j++)
- { // avoid round off error when possible
- if (split->normal[j] == 1)
- mid[j] = split->dist;
- else if (split->normal[j] == -1)
- mid[j] = -split->dist;
- mid[j] = p1[j] + dot*(p2[j]-p1[j]);
- }
- mid[3] = p1[3] + dot*(p2[3]-p1[3]);
- mid[4] = p1[4] + dot*(p2[4]-p1[4]);
- }
- if (neww->numpoints > maxpts)
- Error ("ClipWinding: points exceeded estimate");
- // free the original winding
- free (in);
-
- return neww;
- }
- /*
- =================
- BasePolyForPlane
- There has GOT to be a better way of doing this...
- =================
- */
- winding_t *BasePolyForPlane (face_t *f)
- {
- int i, x;
- float max, v;
- vec3_t org, vright, vup;
- vec3_t xaxis, yaxis;
- winding_t *w;
- texturedef_t *td;
- plane_t *p;
- float ang, sinv, cosv;
- float s, t, ns, nt;
- p = &f->plane;
-
- // find the major axis
- max = -BOGUS_RANGE;
- x = -1;
- for (i=0 ; i<3; i++)
- {
- v = fabs(p->normal[i]);
- if (v > max)
- {
- x = i;
- max = v;
- }
- }
- if (x==-1)
- Error ("BasePolyForPlane: no axis found");
-
- VectorCopy (vec3_origin, vup);
- switch (x)
- {
- case 0:
- case 1:
- vup[2] = 1;
- break;
- case 2:
- vup[0] = 1;
- break;
- }
- v = DotProduct (vup, p->normal);
- VectorMA (vup, -v, p->normal, vup);
- VectorNormalize (vup);
-
- VectorScale (p->normal, p->dist, org);
-
- CrossProduct (vup, p->normal, vright);
-
- VectorScale (vup, 8192, vup);
- VectorScale (vright, 8192, vright);
- // project a really big axis aligned box onto the plane
- w = NewWinding (4);
- w->numpoints = 4;
-
- VectorSubtract (org, vright, w->points[0]);
- VectorAdd (w->points[0], vup, w->points[0]);
-
- VectorAdd (org, vright, w->points[1]);
- VectorAdd (w->points[1], vup, w->points[1]);
-
- VectorAdd (org, vright, w->points[2]);
- VectorSubtract (w->points[2], vup, w->points[2]);
-
- VectorSubtract (org, vright, w->points[3]);
- VectorSubtract (w->points[3], vup, w->points[3]);
-
- // set texture values
- f->light = TextureAxisFromPlane(&f->plane, xaxis, yaxis);
- td = &f->texture;
-
- // rotate axis
- ang = td->rotate / 180 * M_PI;
- sinv = sin(ang);
- cosv = cos(ang);
-
- if (!td->scale[0])
- td->scale[0] = 1;
- if (!td->scale[1])
- td->scale[1] = 1;
- for (i=0 ; i<4 ; i++)
- {
- s = DotProduct (w->points[i], xaxis);
- t = DotProduct (w->points[i], yaxis);
- ns = cosv * s - sinv * t;
- nt = sinv * s + cosv * t;
- w->points[i][3] = ns/td->scale[0] + td->shift[0];
- w->points[i][4] = nt/td->scale[1] + td->shift[1];
- }
-
- return w;
- }
- /*
- ===========
- calcWindings
- recalc the faces and mins / maxs from the planes
- If a face has a NULL winding, it is an overconstraining plane and
- can be removed.
- ===========
- */
- - calcWindings
- {
- int i,j, k;
- float v;
- face_t *f;
- winding_t *w;
- plane_t plane;
- vec3_t t1, t2, t3;
- BOOL useplane[MAX_FACES];
-
- bmins[0] = bmins[1] = bmins[2] = 99999;
- bmaxs[0] = bmaxs[1] = bmaxs[2] = -99999;
- invalid = NO;
-
- [self freeWindings];
-
- for (i=0 ; i<MAX_FACES ; i++)
- {
- f = &faces[i];
-
- // calc a plane from the points
- for (j=0 ; j<3 ; j++)
- {
- t1[j] = f->planepts[0][j] - f->planepts[1][j];
- t2[j] = f->planepts[2][j] - f->planepts[1][j];
- t3[j] = f->planepts[1][j];
- }
-
- CrossProduct(t1,t2, f->plane.normal);
- if (VectorCompare (f->plane.normal, vec3_origin))
- {
- useplane[i] = NO;
- break;
- }
- VectorNormalize (f->plane.normal);
- f->plane.dist = DotProduct (t3, f->plane.normal);
-
- // if the plane duplicates another plane, ignore it
- // (assume it is a brush being edited that will be fixed)
- useplane[i] = YES;
- for (j=0 ; j< i ; j++)
- {
- if ( f->plane.normal[0] == faces[j].plane.normal[0]
- && f->plane.normal[1] == faces[j].plane.normal[1]
- && f->plane.normal[2] == faces[j].plane.normal[2]
- && f->plane.dist == faces[j].plane.dist )
- {
- useplane[i] = NO;
- break;
- }
- }
-
- }
-
- for (i=0 ; i<numfaces ; i++)
- {
- if (!useplane[i])
- continue; // duplicate plane
-
- f = &faces[i];
- w = BasePolyForPlane (f);
- for (j=0 ; j<numfaces && w ; j++)
- {
- if (j == i)
- continue;
- // flip the plane, because we want to keep the back side
- VectorSubtract (vec3_origin, faces[j].plane.normal, plane.normal);
- plane.dist = -faces[j].plane.dist;
-
- w = ClipWinding (w, &plane);
- }
- f->w = w;
- if (w)
- {
- CheckFace (f);
- for (j=0 ; j<w->numpoints ; j++)
- {
- for (k=0 ; k<3 ; k++)
- {
- v = w->points[j][k];
- if (fabs(v - rint(v)) < FP_EPSILON)
- v = w->points[j][k] = rint(v);
- if (v < bmins[k])
- bmins[k] = v;
- if (v > bmaxs[k])
- bmaxs[k] = v;
- }
- }
- }
- }
- if (bmins[0] == 99999)
- {
- invalid = YES;
- VectorCopy (vec3_origin, bmins);
- VectorCopy (vec3_origin, bmaxs);
- return nil;
- }
-
- return self;
- }
- //============================================================================
- /*
- ===========
- initOwner:::
- ===========
- */
- - initOwner: own mins:(float *)mins maxs:(float *)maxs texture:(texturedef_t *)tex
- {
- [super init];
- parent = own;
-
- [self setTexturedef: tex];
- [self setMins: mins maxs: maxs];
- return self;
- }
- - setMins:(float *)mins maxs:(float *)maxs
- {
- int i, j;
- vec3_t pts[4][2];
-
- for (i=0 ; i<3 ; i++)
- {
- if (maxs[i] - mins[i] <= 0)
- {
- VectorCopy (mins, bmins);
- VectorCopy (maxs, bmaxs);
- invalid = YES;
- numfaces = 0;
- return self;
- }
- }
-
- pts[0][0][0] = mins[0];
- pts[0][0][1] = mins[1];
-
- pts[1][0][0] = mins[0];
- pts[1][0][1] = maxs[1];
-
- pts[2][0][0] = maxs[0];
- pts[2][0][1] = maxs[1];
-
- pts[3][0][0] = maxs[0];
- pts[3][0][1] = mins[1];
-
- for (i=0 ; i<4 ; i++)
- {
- pts[i][0][2] = mins[2];
- pts[i][1][0] = pts[i][0][0];
- pts[i][1][1] = pts[i][0][1];
- pts[i][1][2] = maxs[2];
- }
-
- numfaces = 6;
- for (i=0 ; i<4 ; i++)
- {
- j = (i+1)%4;
- faces[i].planepts[0][0] = pts[j][1][0];
- faces[i].planepts[0][1] = pts[j][1][1];
- faces[i].planepts[0][2] = pts[j][1][2];
-
- faces[i].planepts[1][0] = pts[i][1][0];
- faces[i].planepts[1][1] = pts[i][1][1];
- faces[i].planepts[1][2] = pts[i][1][2];
-
- faces[i].planepts[2][0] = pts[i][0][0];
- faces[i].planepts[2][1] = pts[i][0][1];
- faces[i].planepts[2][2] = pts[i][0][2];
- }
-
- faces[4].planepts[0][0] = pts[0][1][0];
- faces[4].planepts[0][1] = pts[0][1][1];
- faces[4].planepts[0][2] = pts[0][1][2];
- faces[4].planepts[1][0] = pts[1][1][0];
- faces[4].planepts[1][1] = pts[1][1][1];
- faces[4].planepts[1][2] = pts[1][1][2];
- faces[4].planepts[2][0] = pts[2][1][0];
- faces[4].planepts[2][1] = pts[2][1][1];
- faces[4].planepts[2][2] = pts[2][1][2];
-
- faces[5].planepts[0][0] = pts[2][0][0];
- faces[5].planepts[0][1] = pts[2][0][1];
- faces[5].planepts[0][2] = pts[2][0][2];
- faces[5].planepts[1][0] = pts[1][0][0];
- faces[5].planepts[1][1] = pts[1][0][1];
- faces[5].planepts[1][2] = pts[1][0][2];
- faces[5].planepts[2][0] = pts[0][0][0];
- faces[5].planepts[2][1] = pts[0][0][1];
- faces[5].planepts[2][2] = pts[0][0][2];
-
- [self calcWindings];
- return self;
- }
- - parent
- {
- return parent;
- }
- - setParent: (id)p
- {
- parent = p;
- return self;
- }
- - setEntityColor: (vec3_t)color
- {
- VectorCopy (color, entitycolor);
- return self;
- }
- - freeWindings
- {
- int i;
-
- for (i=0 ; i<MAX_FACES ; i++)
- if (faces[i].w)
- {
- free (faces[i].w);
- faces[i].w = NULL;
- }
- return self;
- }
- - copyFromZone:(NXZone *)zone
- {
- id new;
-
- [self freeWindings];
- new = [super copyFromZone: zone];
-
- [self calcWindings];
- [new calcWindings];
-
- return new;
- }
- - free
- {
- [self freeWindings];
- return [super free];
- }
- /*
- ===========
- initOwner: fromTokens
- ===========
- */
- int numsb;
- - initFromTokens: own
- {
- face_t *f;
- int i,j;
- [self init];
-
- parent = own;
-
- f = faces;
- numfaces = 0;
- do
- {
- if (!GetToken (true))
- break;
- if (!strcmp (token, "}") )
- break;
-
- for (i=0 ; i<3 ; i++)
- {
- if (i != 0)
- GetToken (true);
- if (strcmp (token, "(") )
- Error ("parsing map file");
-
- for (j=0 ; j<3 ; j++)
- {
- GetToken (false);
- f->planepts[i][j] = atoi(token);
- }
-
- GetToken (false);
- if (strcmp (token, ")") )
- Error ("parsing map file");
- }
- GetToken (false);
- strcpy (f->texture.texture, token);
- GetToken (false);
- f->texture.shift[0] = atof(token);
- GetToken (false);
- f->texture.shift[1] = atof(token);
- GetToken (false);
- f->texture.rotate = atof(token);
- GetToken (false);
- f->texture.scale[0] = atof(token);
- GetToken (false);
- f->texture.scale[1] = atof(token);
-
- #if 0
- flags = atoi(token);
-
- flags &= 7;
- f->texture.rotate = 0;
- f->texture.scale[0] = 1;
- f->texture.scale[1] = 1;
- #define TEX_FLIPAXIS 1
- #define TEX_FLIPS 2
- #define TEX_FLIPT 4
- if (flags & TEX_FLIPAXIS)
- {
- f->texture.rotate = 90;
- if ( !(flags & TEX_FLIPT) )
- f->texture.scale[0] = -1;
- if (flags & TEX_FLIPS)
- f->texture.scale[1] = -1;
- }
- else
- {
- if (flags & TEX_FLIPS)
- f->texture.scale[0] = -1;
- if (flags & TEX_FLIPT)
- f->texture.scale[1] = -1;
- }
- #endif
- f++;
- numfaces++;
- } while (1);
-
- numsb++;
- [self calcWindings];
- return self;
- }
- /*
- ===========
- writeToFILE
- ===========
- */
- - writeToFILE: (FILE *)f region: (BOOL)reg
- {
- int i,j;
- face_t *fa;
- texturedef_t *td;
-
- if (reg && regioned)
- return self;
- fprintf (f, "{\n");
- for (i=0 ; i<numfaces ; i++)
- {
- fa = &faces[i];
- for (j=0 ; j<3 ; j++)
- fprintf (f,"( %d %d %d ) ", (int)fa->planepts[j][0], (int)fa->planepts[j][1], (int)fa->planepts[j][2]);
- td = &fa->texture;
- fprintf (f,"%s %d %d %d %f %f\n", td->texture, (int)td->shift[0], (int)td->shift[1], (int)td->rotate, td->scale[0], td->scale[1]);
- }
- fprintf (f, "}\n");
-
- return self;
- }
- /*
- ==============================================================================
- INTERACTION
- ==============================================================================
- */
- - getMins: (vec3_t)mins maxs: (vec3_t)maxs
- {
- VectorCopy (bmins, mins);
- VectorCopy (bmaxs, maxs);
- return self;
- }
- - (BOOL)selected
- {
- return selected;
- }
- - setSelected: (BOOL)s
- {
- selected = s;
- return self;
- }
- - (BOOL)regioned
- {
- return regioned;
- }
- - setRegioned: (BOOL)s
- {
- regioned = s;
- return self;
- }
- /*
- ===========
- setTexturedef
- ===========
- */
- - setTexturedef: (texturedef_t *)tex
- {
- int i;
-
- for (i=0 ; i<MAX_FACES ; i++)
- {
- faces[i].texture = *tex;
- faces[i].qtexture = NULL; // recache next render
- }
-
- [self calcWindings]; // in case texture coords changed
- return self;
- }
- - setTexturedef: (texturedef_t *)tex forFace:(int)f
- {
- if ( (unsigned)f > numfaces)
- Error ("setTexturedef:forFace: bad face number %i",f);
-
- faces[f].texture = *tex;
- faces[f].qtexture = NULL; // recache next render
- [self calcWindings]; // in case texture coords changed
- return self;
- }
- /*
- ===========
- texturedef
- ===========
- */
- - (texturedef_t *)texturedef
- {
- return &faces[0].texture;
- }
- - (texturedef_t *)texturedefForFace: (int)f
- {
- return &faces[f].texture;
- }
- /*
- ===========
- removeIfInvalid
- So created veneers don't stay around
- ===========
- */
- - removeIfInvalid
- {
- int i, j;
-
- for (i=0 ; i<numfaces ; i++)
- {
- if (faces[i].w)
- continue;
- for (j=i+1 ; j<numfaces ; j++)
- faces[j-1] = faces[j];
- i--;
- numfaces--;
- }
- for ( ; i<MAX_FACES ; i++)
- faces[i].w = NULL;
-
- if (numfaces<4)
- {
- invalid = YES;
- [self remove];
- return nil;
- }
- return self;
- }
- /*
- ===========
- containsPoint
- ===========
- */
- - (BOOL)containsPoint: (vec3_t)pt
- {
- int i;
-
- for (i=0 ; i<numfaces ; i++)
- if (DotProduct (faces[i].plane.normal, pt) >= faces[i].plane.dist)
- return NO;
- return YES;
- }
- /*
- ===========
- clipRay
- ===========
- */
- - clipRay: (vec3_t)p1 : (vec3_t) p2
- :(vec3_t)frontpoint : (int *)f_face
- :(vec3_t)backpoint : (int *)b_face
- {
- int frontface, backface;
- int i, j;
- face_t *f;
- float d1, d2, m;
- float *start;
-
- start = p1;
- frontface = -2;
- backface = -2;
-
- f = faces;
- for (i=0 ; i<numfaces ; i++, f++)
- {
- if (!f->w)
- continue; // clipped off plane
- d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
- d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
- if (d1 >= 0 && d2 >= 0)
- { // the entire ray is in front of the polytope
- *f_face = -1;
- *b_face = -1;
- return self;
- }
- if (d1 > 0 && d2 < 0)
- { // new front plane
- frontface = i;
- m = d1 / (d1-d2);
- for (j=0 ; j<3 ; j++)
- frontpoint[j] = p1[j] + m*(p2[j]-p1[j]);
- p1 = frontpoint;
- }
- if (d1 < 0 && d2 > 0)
- { // new back plane
- backface = i;
- m = d1 / (d1-d2);
- for (j=0 ; j<3 ; j++)
- backpoint[j] = p1[j] + m*(p2[j]-p1[j]);
- p2 = backpoint;
- }
- }
-
- *f_face = frontface;
- *b_face = backface;
-
- return self;
- }
- /*
- ===========
- hitByRay
- ===========
- */
- - hitByRay: (vec3_t)p1 : (vec3_t) p2 : (float *)time : (int *)face
- {
- vec3_t frontpoint, backpoint, dir;
- int frontface, backface;
-
- if (regioned)
- {
- *time = -1;
- *face = -1;
- return self;
- }
-
- [self clipRay: p1 : p2 : frontpoint: &frontface : backpoint : &backface];
-
- if (frontface == -2 && backface == -2)
- { // entire ray is inside the brush, select first face
- *time = 0;
- *face = 0;
- return self;
- }
-
-
- if (frontface < 0)
- { // ray started inside the polytope, don't select it
- *time = -1;
- *face = -1;
- return self;
- }
-
- VectorSubtract (p2, p1, dir);
- VectorNormalize (dir);
- VectorSubtract (frontpoint, p1, frontpoint);
- *time = DotProduct (frontpoint, dir);
- if (*time < 0)
- Error ("hitByRay: negative t");
- *face = frontface;
-
- return self;
- }
- /*
- ==============================================================================
- DRAWING ROUTINES
- ==============================================================================
- */
- BOOL fakebrush;
- - drawConnections
- {
- id obj;
- int c, i;
- vec3_t dest, origin;
- vec3_t mid;
- vec3_t forward, right;
- char *targname;
- vec3_t min, max, temp;
- char targ[64];
-
- strcpy (targ, [parent valueForQKey: "target"]);
- if (!targ || !targ[0])
- return self;
-
- origin[0] = (bmins[0] + bmaxs[0]) /2;
- origin[1] = (bmins[1] + bmaxs[1]) /2;
-
- c = [map_i count];
- for (i=0 ; i<c ; i++)
- {
- obj = [map_i objectAt: i];
- targname = [obj valueForQKey: "targetname"];
- if (strcmp (targ, targname))
- continue;
-
- [[obj objectAt:0] getMins: min maxs: max];
- dest[0] = (min[0] + max[0]) /2;
- dest[1] = (min[1] + max[1]) /2;
-
- XYmoveto (origin);
- XYlineto (dest);
-
- forward[0] = dest[0] - origin[0];
- forward[1] = dest[1] - origin[1];
- forward[2] = 0;
-
- if (!forward[0] && !forward[1])
- continue;
-
- VectorNormalize (forward);
- forward[0] = 8*forward[0];
- forward[1] = 8*forward[1];
- right[0] = forward[1];
- right[1] = -forward[0];
- mid[0] = (dest[0] + origin[0])/2;
- mid[1] = (dest[1] + origin[1])/2;
-
- temp[0] = mid[0] + right[0] - forward[0];
- temp[1] = mid[1] + right[1] - forward[1];
- XYmoveto (temp);
- XYlineto (mid);
- temp[0] = mid[0] - right[0] - forward[0];
- temp[1] = mid[1] - right[1] - forward[1];
- XYlineto (temp);
-
- }
-
- return self;
- }
- - (BOOL)fakeBrush: (SEL)call
- {
- id copy;
- face_t face;
- if (!selected || fakebrush)
- return NO;
-
- if (![clipper_i getFace: &face])
- return NO;
-
- fakebrush = YES;
- copy = [self copy];
- copy = [copy addFace: &face];
- if (copy)
- {
- [copy perform:call];
- [copy free];
- }
- fakebrush = NO;
- return YES;
- }
- /*
- ===========
- XYDrawSelf
- ===========
- */
- - XYDrawSelf
- {
- int i, j;
- winding_t *w;
- vec3_t mid, end, s1, s2;
- char *val;
- float ang;
- id worldent, currentent;
- BOOL keybrush;
- if ([self fakeBrush: @selector(XYDrawSelf)])
- return self;
-
- [xyview_i addToScrollRange: bmins[0] : bmins[1]];
- [xyview_i addToScrollRange: bmaxs[0] : bmaxs[1]];
- worldent = [map_i objectAt: 0];
- currentent = [map_i currentEntity];
-
- if (parent != worldent && self == [parent objectAt: 0])
- keybrush = YES;
- else
- keybrush = NO;
- if (parent != worldent && worldent == currentent)
- linecolor (entitycolor[0], entitycolor[1], entitycolor[2]);
- else if (selected)
- linecolor (1,0,0); // selected
- else if (parent == currentent)
- linecolor (0,0,0); // unselected, but in same entity
- else
- linecolor (0,0.5,0); // other entity green
- if (keybrush)
- [self drawConnections]; // target line
- if (!selected &&
- ( bmaxs[0] < xy_draw_rect.origin.x
- || bmaxs[1] < xy_draw_rect.origin.y
- || bmins[0] > xy_draw_rect.origin.x + xy_draw_rect.size.width
- || bmins[1] > xy_draw_rect.origin.y + xy_draw_rect.size.height) )
- return self; // off view, don't bother
- for (i=0 ; i<numfaces ; i++)
- {
- w = faces[i].w;
- if (!w)
- continue;
- if (DotProduct (faces[i].plane.normal,xy_viewnormal) > -VECTOR_EPSILON)
- continue;
-
- XYmoveto (w->points[w->numpoints-1]);
- for (j=0 ; j<w->numpoints ; j++)
- XYlineto (w->points[j]);
- }
-
- if (keybrush)
- {
- // angle arrow
- val = [parent valueForQKey: "angle"];
- if (val && val[0])
- {
- ang = atof(val) * M_PI / 180;
- if (ang > 0) // negative values are up/down flags
- {
- mid[0] = (bmins[0]+bmaxs[0])/2;
- mid[1] = (bmins[1]+bmaxs[1])/2;
-
- end[0] = mid[0] + 16*cos(ang);
- end[1] = mid[1] + 16*sin(ang);
-
- s1[0] = mid[0] + 12*cos(ang+0.4);
- s1[1] = mid[1] + 12*sin(ang+0.4);
-
- s2[0] = mid[0] + 12*cos(ang-0.4);
- s2[1] = mid[1] + 12*sin(ang-0.4);
-
- XYmoveto ( mid);
- XYlineto ( end );
- XYmoveto ( s1);
- XYlineto ( end );
- XYlineto ( s2 );
- }
- }
- }
-
- return self;
- }
- /*
- ===========
- ZDrawSelf
- ===========
- */
- - ZDrawSelf
- {
- int i;
- vec3_t p1, p2;
- vec3_t frontpoint, backpoint;
- int frontface, backface;
- qtexture_t *q;
-
- if ([self fakeBrush: @selector(ZDrawSelf)])
- return self;
- [zview_i addToHeightRange: bmins[2]];
- [zview_i addToHeightRange: bmaxs[2]];
-
- if (selected)
- {
- PSmoveto (1, bmaxs[2]);
- PSlineto (23, bmaxs[2]);
- PSlineto (23, bmins[2]);
- PSlineto (1, bmins[2]);
- PSlineto (1, bmaxs[2]);
- PSsetrgbcolor (1,0,0);
- PSstroke ();
- }
- [zview_i getPoint: (NXPoint *)p1];
-
- for (i=0 ; i<2 ; i++)
- if (bmins[i] >= p1[i] || bmaxs[i] <= p1[i])
- return self;
-
- p1[2] = 4096;
- p2[0] = p1[0];
- p2[1] = p1[1];
- p2[2] = -4096;
- [self clipRay: p1 : p2 : frontpoint: &frontface : backpoint : &backface];
- if (frontface == -1 || backface == -1)
- return self;
-
- q = TEX_ForName (faces[frontface].texture.texture);
-
- PSmoveto (-8, frontpoint[2]);
- PSlineto (8, frontpoint[2]);
- PSlineto (8, backpoint[2]);
- PSlineto (-8, backpoint[2]);
- PSlineto (-8, frontpoint[2]);
-
- PSsetrgbcolor (q->flatcolor.chan[0]/255.0
- , q->flatcolor.chan[1]/255.0
- , q->flatcolor.chan[2]/255.0);
- PSfill ();
- PSmoveto (-12, frontpoint[2]);
- PSlineto (12, frontpoint[2]);
- PSlineto (12, backpoint[2]);
- PSlineto (-12, backpoint[2]);
- PSlineto (-12, frontpoint[2]);
-
- PSsetrgbcolor (0,0,0);
- PSstroke ();
-
- return self;
- }
- /*
- ===========
- CameraDrawSelf
- ===========
- */
- - CameraDrawSelf
- {
- int i, j;
- winding_t *w;
- id worldent, currentent;
-
- if ([self fakeBrush: @selector(CameraDrawSelf)])
- return self;
-
- worldent = [map_i objectAt: 0];
- currentent = [map_i currentEntity];
- if (parent != worldent && worldent == currentent)
- linecolor (entitycolor[0], entitycolor[1], entitycolor[2]);
- else if (selected)
- linecolor (1,0,0);
- else if (parent == [map_i currentEntity])
- linecolor (0,0,0);
- else
- linecolor (0,0.5,0);
- for (i=0 ; i<numfaces ; i++)
- {
- w = faces[i].w;
- if (!w)
- continue;
- CameraMoveto (w->points[w->numpoints-1]);
- for (j=0 ; j<w->numpoints ; j++)
- CameraLineto (w->points[j]);
- }
- return self;
- }
- /*
- ===========
- XYRenderSelf
- ===========
- */
- - XYRenderSelf
- {
- int i;
-
- if ([self fakeBrush: @selector(XYRenderSelf)])
- return self;
-
- for (i=0 ; i<numfaces ; i++)
- REN_DrawXYFace (&faces[i]);
-
- return self;
- }
- /*
- ===========
- CameraRenderSelf
- ===========
- */
- - CameraRenderSelf
- {
- int i;
- BOOL olddraw;
- extern qtexture_t badtex;
- pixel32_t p;
- if ([self fakeBrush: @selector(CameraRenderSelf)])
- return self;
- // hack to draw entity boxes as single flat color
- if ( ![parent modifiable] )
- {
- olddraw = r_drawflat;
- r_drawflat = YES;
- p = badtex.flatcolor;
- badtex.flatcolor.chan[0] = entitycolor[0]*255;
- badtex.flatcolor.chan[1] = entitycolor[1]*255;
- badtex.flatcolor.chan[2] = entitycolor[2]*255;
- for (i=0 ; i<numfaces ; i++)
- REN_DrawCameraFace (&faces[i]);
- badtex.flatcolor = p;
- r_drawflat = olddraw;
- }
- else
- {
- for (i=0 ; i<numfaces ; i++)
- REN_DrawCameraFace (&faces[i]);
- }
-
- return self;
- }
- /*
- ==============================================================================
- SINGLE BRUSH ACTIONS
- ==============================================================================
- */
- face_t *dragface, *dragface2;
- int numcontrolpoints;
- float *controlpoints[MAX_FACES*3];
- - (BOOL)checkModifiable
- {
- // int i;
- if ( [parent modifiable] )
- return YES;
-
- // don't stretch spawned entities, move all points
- #if 0
- numcontrolpoints = numfaces*3;
-
- for (i=0 ; i<numcontrolpoints ; i++)
- controlpoints[i] = faces[i/3].planepts[i%3];
- #endif
- return NO;
- }
- - getZdragface: (vec3_t)dragpoint
- {
- int i, j;
- float d;
-
- if (![self checkModifiable])
- return self;
- numcontrolpoints = 0;
- for (i=0 ; i<numfaces ; i++)
- {
- if (!faces[i].w)
- continue;
- if (faces[i].plane.normal[2] == 1)
- d = dragpoint[2] - faces[i].plane.dist;
- else if (faces[i].plane.normal[2] == -1)
- d = -faces[i].plane.dist - dragpoint[2];
- else
- continue;
-
- if (d <= 0)
- continue;
-
- for (j=0 ; j<3 ; j++)
- {
- controlpoints[numcontrolpoints] = faces[i].planepts[j];
- numcontrolpoints++;
- }
- }
-
- return self;
- }
- - getXYdragface: (vec3_t)dragpoint
- {
- int i,j;
- float d;
- numcontrolpoints = 0;
- if (![self checkModifiable])
- return self;
-
- for (i=0 ; i<numfaces ; i++)
- {
- if (!faces[i].w)
- continue;
- if (faces[i].plane.normal[2])
- continue;
- d = DotProduct(faces[i].plane.normal, dragpoint) - faces[i].plane.dist;
- if (d <= 0)
- continue;
- for (j=0 ; j<3 ; j++)
- {
- controlpoints[numcontrolpoints] = faces[i].planepts[j];
- numcontrolpoints++;
- }
- }
-
- return self;
- }
- - getXYShearPoints: (vec3_t)dragpoint
- {
- int i,j, k;
- int facectl;
- float d;
- int numdragplanes;
- BOOL dragplane[MAX_FACES];
- winding_t *w;
- face_t *f;
- BOOL onplane[MAX_POINTS_ON_WINDING];
-
- if (![self checkModifiable])
- return self;
- numcontrolpoints = 0;
- numdragplanes = 0;
- for (i=0 ; i<numfaces ; i++)
- {
- dragplane[i] = NO;
- if (!faces[i].w)
- continue;
- // if (faces[i].plane.normal[2])
- // continue;
- d = DotProduct(faces[i].plane.normal, dragpoint) - faces[i].plane.dist;
- if (d <= -ON_EPSILON)
- continue;
- dragplane[i] = YES;
- numdragplanes++;
- }
-
- // find faces that just share an edge with a drag plane
- for (i=0 ; i<numfaces ; i++)
- {
- f = &faces[i];
- w = f->w;
- if (!w)
- continue;
- if (dragplane[i] && numdragplanes == 1)
- {
- for (j=0 ; j<3 ; j++)
- {
- controlpoints[numcontrolpoints] = faces[i].planepts[j];
- numcontrolpoints++;
- }
- continue;
- }
- if (!dragplane[i] && numdragplanes > 1)
- continue;
-
- facectl = 0;
- for (j=0 ; j<w->numpoints ; j++)
- {
- onplane[j] = NO;
- for (k=0 ; k<numfaces ; k++)
- {
- if (!dragplane[k])
- continue;
- if (k == i)
- continue;
- d = DotProduct (w->points[j], faces[k].plane.normal)
- - faces[k].plane.dist;
- if (fabs(d) > ON_EPSILON)
- continue;
- onplane[j] = YES;
- facectl++;
- break;
- }
- }
- if (facectl == 0)
- continue;
-
- // find one or two static points to go with the controlpoints
- // and change the plane points
- k = 0;
- for (j=0 ; j<w->numpoints ; j++)
- {
- if (!onplane[j])
- continue;
- if (facectl >= 2 && !onplane[(j+1)%w->numpoints])
- continue;
- if (facectl == 3 && !onplane[(j+2)%w->numpoints])
- continue;
- VectorCopy (w->points[j], f->planepts[k]);
- controlpoints[numcontrolpoints] = f->planepts[k];
- numcontrolpoints++;
- k++;
- if (facectl >= 2)
- {
- VectorCopy (w->points[(j+1)%w->numpoints], f->planepts[k]);
- controlpoints[numcontrolpoints] = f->planepts[k];
- numcontrolpoints++;
- k++;
- }
- if (facectl == 3)
- {
- VectorCopy (w->points[(j+2)%w->numpoints], f->planepts[k]);
- controlpoints[numcontrolpoints] = f->planepts[k];
- numcontrolpoints++;
- k++;
- }
- break;
- }
-
- for ( ; j<w->numpoints && k != 3 ; j++)
- if (!onplane[j])
- {
- VectorCopy (w->points[j], f->planepts[k]);
- k++;
- }
-
- for (j=0 ; j<w->numpoints && k != 3 ; j++)
- if (!onplane[j])
- {
- VectorCopy (w->points[j], f->planepts[k]);
- k++;
- }
-
- if (k != 3)
- {
- // Error ("getXYShearPoints: didn't get three points on plane");
- numcontrolpoints = 0;
- return self;
- }
-
- for (j=0 ; j<3 ; j++)
- for (k=0 ; k<3 ; k++)
- f->planepts[j][k] = rint(f->planepts[j][k]);
- }
-
- return self;
- }
- /*
- ==============================================================================
- MULTIPLE BRUSH ACTIONS
- ==============================================================================
- */
- vec3_t region_min, region_max;
- /*
- ===========
- newRegion
- Set the regioned flag based on if the object is containted in region_min/max
- ===========
- */
- - newRegion
- {
- int i;
- char *name;
-
- // filter away entities
- if (parent != [map_i objectAt: 0])
- {
- if (filter_entities)
- {
- regioned = YES;
- return self;
- }
-
- name = [parent valueForQKey: "classname"];
-
- if ( (filter_light && !strncmp(name,"light",5) )
- || (filter_path && !strncmp(name,"path",4) ) )
- {
- regioned = YES;
- return self;
- }
- }
- else if (filter_world)
- {
- regioned = YES;
- return self;
- }
-
- if (filter_clip_brushes && !strcasecmp(faces[0].texture.texture, "clip"))
- {
- regioned = YES;
- return self;
- }
-
- if (filter_water_brushes && faces[0].texture.texture[0] == '*')
- {
- regioned = YES;
- return self;
- }
-
- for (i=0 ; i<3 ; i++)
- {
- if (region_min[i] >= bmaxs[i] || region_max[i] <= bmins[i])
- {
- if (selected)
- [self deselect];
- regioned = YES;
- return self;
- }
- }
-
- regioned = NO;
- return self;
- }
- vec3_t select_min, select_max;
- - selectPartial
- {
- int i;
- for (i=0 ; i<3 ; i++)
- if (select_min[i] >= bmaxs[i] || select_max[i] <= bmins[i])
- return self;
- selected = YES;
- return self;
- }
- - selectComplete
- {
- int i;
- for (i=0 ; i<3 ; i++)
- if (select_min[i] > bmins[i] || select_max[i] < bmaxs[i])
- return self;
- selected = YES;
- return self;
- }
- - regionPartial
- {
- int i;
- for (i=0 ; i<3 ; i++)
- if (select_min[i] >= bmaxs[i] || select_max[i] <= bmins[i])
- return self;
- selected = YES;
- return self;
- }
- - regionComplete
- {
- int i;
- for (i=0 ; i<3 ; i++)
- if (select_min[i] > bmins[i] || select_max[i] < bmaxs[i])
- return self;
- selected = YES;
- return self;
- }
- id sb_newowner;
- - moveToEntity
- {
- id eclass;
- float *c;
-
- [parent removeObject: self];
- parent = sb_newowner;
-
- // hack to allow them to be copied to another map
- if ( [parent respondsTo:@selector(valueForQKey:)])
- {
- eclass = [entity_classes_i classForName: [parent valueForQKey: "classname"]];
- c = [eclass drawColor];
- [self setEntityColor: c];
- }
-
- [parent addObject: self];
- return self;
- }
- vec3_t sb_translate;
- - translate
- {
- int i, j;
-
- // move the planes
- for (i=0; i<numfaces ; i++)
- for (j=0 ; j<3 ; j++)
- {
- VectorAdd (faces[i].planepts[j], sb_translate, faces[i].planepts[j]);
- }
- [self calcWindings];
-
- return self;
- }
- vec3_t sb_mins, sb_maxs;
- - addToBBox
- {
- int k;
-
- if (numfaces < 4)
- return self;
- for (k=0 ; k<3 ; k++)
- {
- if (bmins[k] < sb_mins[k])
- sb_mins[k] = bmins[k];
- if (bmaxs[k] > sb_maxs[k])
- sb_maxs[k] = bmaxs[k];
- }
- return self;
- }
- - flushTextures
- { // call when texture palette changes
- int i;
-
- for (i=0 ; i<MAX_FACES ; i++)
- faces[i].qtexture = NULL;
-
- [self calcWindings];
- return self;
- }
- - select
- {
- [map_i setCurrentEntity: parent];
- selected = YES;
- return self;
- }
- - deselect
- {
- selected = NO;
- // the last selected brush determines
- if (invalid)
- printf ("WARNING: deselected invalid brush\n");
- [map_i setCurrentMinZ: bmins[2]];
- [map_i setCurrentMaxZ: bmaxs[2]];
-
- return self;
- }
- - remove
- {
- // the last selected brush determines
- if (!invalid)
- {
- [map_i setCurrentMinZ: bmins[2]];
- [map_i setCurrentMaxZ: bmaxs[2]];
- }
- [parent removeObject: self];
- [self free];
- return nil;
- }
- vec3_t sel_x, sel_y, sel_z;
- vec3_t sel_org;
- - transform
- {
- int i,j;
- vec3_t old;
- float *p;
-
- for (i=0 ; i<numfaces ; i++)
- for (j=0 ; j<3 ; j++)
- {
- p = faces[i].planepts[j];
- VectorCopy (p, old);
- VectorSubtract (old, sel_org, old);
- p[0] = DotProduct (old, sel_x);
- p[1] = DotProduct (old, sel_y);
- p[2] = DotProduct (old, sel_z);
- VectorAdd (p, sel_org, p);
- }
-
- [self calcWindings];
- return self;
- }
- - flipNormals // used after an inside-out transform (flip x/y/z)
- {
- int i;
- vec3_t temp;
-
- for (i=0 ; i<numfaces ; i++)
- {
- VectorCopy (faces[i].planepts[0], temp);
- VectorCopy (faces[i].planepts[2], faces[i].planepts[0]);
- VectorCopy (temp, faces[i].planepts[2]);
- }
- [self calcWindings];
- return self;
- }
- - carveByClipper
- {
- face_t face;
-
- if (![clipper_i getFace: &face])
- return self;
-
- [self addFace: &face];
-
- return self;
- }
- - takeCurrentTexture
- {
- texturedef_t td;
-
- [texturepalette_i getTextureDef: &td];
- [self setTexturedef: &td];
-
- return self;
- }
- float sb_floor_dir, sb_floor_dist;
- - feetToFloor
- {
- float oldz;
- vec3_t p1, p2;
- int frontface, backface;
- vec3_t frontpoint, backpoint;
- float dist;
-
- [cameraview_i getOrigin: p1];
- VectorCopy (p1, p2);
- oldz = p1[2] - 48;
-
- p1[2] = 4096;
- p2[2] = -4096;
- [self clipRay: p1 : p2 : frontpoint : &frontface : backpoint : &backface];
- if (frontface == -1)
- return self;
- dist = frontpoint[2] - oldz;
-
- if (sb_floor_dir == 1)
- {
- if (dist > 0 && dist < sb_floor_dist)
- sb_floor_dist = dist;
- }
- else
- {
- if (dist < 0 && dist > sb_floor_dist)
- sb_floor_dist = dist;
- }
- return self;
- }
- /*
- ===============================================================================
- BRUSH SUBTRACTION
- ===============================================================================
- */
- vec3_t carvemin, carvemax;
- int numcarvefaces;
- face_t *carvefaces;
- id carve_in, carve_out;
- // returns the new brush formed after the addition of the given plane
- // nil is returned if it faced all of the original setbrush
- - addFace: (face_t *)f
- {
- if (numfaces == MAX_FACES)
- Error ("addFace: numfaces == MAX_FACES");
-
- faces[numfaces] = *f;
- faces[numfaces].texture = faces[0].texture;
- faces[numfaces].qtexture = NULL;
- faces[numfaces].w = NULL;
- numfaces++;
- [self calcWindings];
-
- // remove any degenerate faces
- return [self removeIfInvalid];
- }
- - clipByFace: (face_t *)fa front:(id *)f back:(id *)b
- {
- id front, back;
- face_t fb;
- vec3_t temp;
-
- fb = *fa;
- VectorCopy (fb.planepts[0], temp);
- VectorCopy (fb.planepts[2], fb.planepts[0]);
- VectorCopy (temp, fb.planepts[2]);
-
- front = [self copy];
- back = [self copy];
- *b = [back addFace: fa];
- *f = [front addFace: &fb];
-
- return self;
- }
- - carve
- {
- int i;
- id front, back;
-
- #if 0
- if ( (i = NXMallocCheck()) )
- Error ("MallocCheck failure");
- #endif
-
- // check bboxes
- for (i=0 ; i<3 ; i++)
- if (bmins[i] >= carvemax[i] || bmaxs[i] <= carvemin[i])
- {
- [carve_out addObject: self];
- return self;
- }
- // carve by the planes
- back = self;
- for (i=0 ; i<numcarvefaces ; i++)
- {
- [back clipByFace: &carvefaces[i] front:&front back:&back];
- if (front)
- [carve_out addObject: front];
- if (!back)
- return nil; // nothing completely inside
- }
-
- [carve_in addObject: back];
- return self;
- }
- /*
- ==================
- setCarveVars
- ==================
- */
- - setCarveVars
- {
- VectorCopy (bmins, carvemin);
- VectorCopy (bmaxs, carvemax);
- numcarvefaces = numfaces;
- carvefaces = faces;
-
- return self;
- }
- - (int) getNumBrushFaces
- {
- return numfaces;
- }
- - (face_t *) getBrushFace: (int)which
- {
- return &faces[which];
- }
- @end
|