2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #define MAX_LSTYLES 256
31 edgeshare_t edgeshare[MAX_MAP_EDGES];
33 int facelinks[MAX_MAP_FACES];
34 int planelinks[2][MAX_MAP_PLANES];
41 void LinkPlaneFaces (void)
47 for (i=0 ; i<numfaces ; i++, f++)
49 facelinks[i] = planelinks[f->side][f->planenum];
50 planelinks[f->side][f->planenum] = i;
66 for (i=0 ; i<numfaces ; i++, f++)
68 for (j=0 ; j<f->numedges ; j++)
70 k = dsurfedges[f->firstedge + j];
82 if (e->faces[0] && e->faces[1])
84 // determine if coplanar
85 if (e->faces[0]->planenum == e->faces[1]->planenum)
93 =================================================================
97 =================================================================
100 typedef struct triedge_s
105 struct triangle_s *tri;
108 typedef struct triangle_s
113 #define MAX_TRI_POINTS 1024
114 #define MAX_TRI_EDGES (MAX_TRI_POINTS*6)
115 #define MAX_TRI_TRIS (MAX_TRI_POINTS*2)
123 triedge_t *edgematrix[MAX_TRI_POINTS][MAX_TRI_POINTS];
124 patch_t *points[MAX_TRI_POINTS];
125 triedge_t edges[MAX_TRI_EDGES];
126 triangle_t tris[MAX_TRI_TRIS];
134 triangulation_t *AllocTriangulation (dplane_t *plane)
138 t = malloc(sizeof(triangulation_t));
145 // memset (t->edgematrix, 0, sizeof(t->edgematrix));
155 void FreeTriangulation (triangulation_t *tr)
161 triedge_t *FindEdge (triangulation_t *trian, int p0, int p1)
168 if (trian->edgematrix[p0][p1])
169 return trian->edgematrix[p0][p1];
171 if (trian->numedges > MAX_TRI_EDGES-2)
172 Error ("trian->numedges > MAX_TRI_EDGES-2");
174 VectorSubtract (trian->points[p1]->origin, trian->points[p0]->origin, v1);
175 VectorNormalize (v1, v1);
176 CrossProduct (v1, trian->plane->normal, normal);
177 dist = DotProduct (trian->points[p0]->origin, normal);
179 e = &trian->edges[trian->numedges];
183 VectorCopy (normal, e->normal);
186 trian->edgematrix[p0][p1] = e;
188 be = &trian->edges[trian->numedges];
192 VectorSubtract (vec3_origin, normal, be->normal);
195 trian->edgematrix[p1][p0] = be;
200 triangle_t *AllocTriangle (triangulation_t *trian)
204 if (trian->numtris >= MAX_TRI_TRIS)
205 Error ("trian->numtris >= MAX_TRI_TRIS");
207 t = &trian->tris[trian->numtris];
218 void TriEdge_r (triangulation_t *trian, triedge_t *e)
227 return; // allready connected by someone
229 // find the point with the best angle
230 p0 = trian->points[e->p0]->origin;
231 p1 = trian->points[e->p1]->origin;
233 for (i=0 ; i< trian->numpoints ; i++)
235 p = trian->points[i]->origin;
236 // a 0 dist will form a degenerate triangle
237 if (DotProduct(p, e->normal) - e->dist < 0)
238 continue; // behind edge
239 VectorSubtract (p0, p, v1);
240 VectorSubtract (p1, p, v2);
241 if (!VectorNormalize (v1,v1))
243 if (!VectorNormalize (v2,v2))
245 ang = DotProduct (v1, v2);
253 return; // edge doesn't match anything
255 // make a new triangle
256 nt = AllocTriangle (trian);
258 nt->edges[1] = FindEdge (trian, e->p1, bestp);
259 nt->edges[2] = FindEdge (trian, bestp, e->p0);
260 for (i=0 ; i<3 ; i++)
261 nt->edges[i]->tri = nt;
262 TriEdge_r (trian, FindEdge (trian, bestp, e->p1));
263 TriEdge_r (trian, FindEdge (trian, e->p0, bestp));
271 void TriangulatePoints (triangulation_t *trian)
279 if (trian->numpoints < 2)
282 // find the two closest points
284 for (i=0 ; i<trian->numpoints ; i++)
286 p1 = trian->points[i]->origin;
287 for (j=i+1 ; j<trian->numpoints ; j++)
289 p2 = trian->points[j]->origin;
290 VectorSubtract (p2, p1, v1);
291 d = VectorLength (v1);
301 e = FindEdge (trian, bp1, bp2);
302 e2 = FindEdge (trian, bp2, bp1);
303 TriEdge_r (trian, e);
304 TriEdge_r (trian, e2);
309 AddPointToTriangulation
312 void AddPointToTriangulation (patch_t *patch, triangulation_t *trian)
316 pnum = trian->numpoints;
317 if (pnum == MAX_TRI_POINTS)
318 Error ("trian->numpoints == MAX_TRI_POINTS");
319 trian->points[pnum] = patch;
328 void LerpTriangle (triangulation_t *trian, triangle_t *t, vec3_t point, vec3_t color)
330 patch_t *p1, *p2, *p3;
332 float x, y, x1, y1, x2, y2;
334 p1 = trian->points[t->edges[0]->p0];
335 p2 = trian->points[t->edges[1]->p0];
336 p3 = trian->points[t->edges[2]->p0];
338 VectorCopy (p1->totallight, base);
339 VectorSubtract (p2->totallight, base, d1);
340 VectorSubtract (p3->totallight, base, d2);
342 x = DotProduct (point, t->edges[0]->normal) - t->edges[0]->dist;
343 y = DotProduct (point, t->edges[2]->normal) - t->edges[2]->dist;
346 y1 = DotProduct (p2->origin, t->edges[2]->normal) - t->edges[2]->dist;
348 x2 = DotProduct (p3->origin, t->edges[0]->normal) - t->edges[0]->dist;
351 if (fabs(y1)<ON_EPSILON || fabs(x2)<ON_EPSILON)
353 VectorCopy (base, color);
357 VectorMA (base, x/x2, d2, color);
358 VectorMA (color, y/y1, d1, color);
361 qboolean PointInTriangle (vec3_t point, triangle_t *t)
367 for (i=0 ; i<3 ; i++)
370 d = DotProduct (e->normal, point) - e->dist;
372 return false; // not inside
383 void SampleTriangulation (vec3_t point, triangulation_t *trian, vec3_t color)
392 if (trian->numpoints == 0)
397 if (trian->numpoints == 1)
399 VectorCopy (trian->points[0]->totallight, color);
403 // search for triangles
404 for (t = trian->tris, j=0 ; j < trian->numtris ; t++, j++)
406 if (!PointInTriangle (point, t))
410 LerpTriangle (trian, t, point, color);
414 // search for exterior edge
415 for (e=trian->edges, j=0 ; j< trian->numedges ; e++, j++)
418 continue; // not an exterior edge
420 d = DotProduct (point, e->normal) - e->dist;
422 continue; // not in front of edge
424 p0 = trian->points[e->p0];
425 p1 = trian->points[e->p1];
427 VectorSubtract (p1->origin, p0->origin, v1);
428 VectorNormalize (v1, v1);
429 VectorSubtract (point, p0->origin, v2);
430 d = DotProduct (v2, v1);
435 for (i=0 ; i<3 ; i++)
436 color[i] = p0->totallight[i] + d * (p1->totallight[i] - p0->totallight[i]);
440 // search for nearest point
443 for (j=0 ; j<trian->numpoints ; j++)
445 p0 = trian->points[j];
446 VectorSubtract (point, p0->origin, v1);
447 d = VectorLength (v1);
456 Error ("SampleTriangulation: no points");
458 VectorCopy (p1->totallight, color);
462 =================================================================
464 LIGHTMAP SAMPLE GENERATION
466 =================================================================
470 #define SINGLEMAP (64*64*4)
478 vec3_t surfpt[SINGLEMAP];
480 vec3_t modelorg; // for origined bmodels
483 vec3_t worldtotex[2]; // s = (world - texorg) . worldtotex[0]
484 vec3_t textoworld[2]; // world = texorg + s * textoworld[0]
486 vec_t exactmins[2], exactmaxs[2];
488 int texmins[2], texsize[2];
498 Fills in s->texmins[] and s->texsize[]
499 also sets exactmins[] and exactmaxs[]
502 void CalcFaceExtents (lightinfo_t *l)
505 vec_t mins[2], maxs[2], val;
513 mins[0] = mins[1] = 999999;
514 maxs[0] = maxs[1] = -99999;
516 tex = &texinfo[s->texinfo];
518 for (i=0 ; i<s->numedges ; i++)
520 e = dsurfedges[s->firstedge+i];
522 v = dvertexes + dedges[e].v[0];
524 v = dvertexes + dedges[-e].v[1];
526 // VectorAdd (v->point, l->modelorg, vt);
527 VectorCopy (v->point, vt);
529 for (j=0 ; j<2 ; j++)
531 val = DotProduct (vt, tex->vecs[j]) + tex->vecs[j][3];
539 for (i=0 ; i<2 ; i++)
541 l->exactmins[i] = mins[i];
542 l->exactmaxs[i] = maxs[i];
544 mins[i] = floor(mins[i]/16);
545 maxs[i] = ceil(maxs[i]/16);
547 l->texmins[i] = mins[i];
548 l->texsize[i] = maxs[i] - mins[i];
549 if (l->texsize[0] * l->texsize[1] > SINGLEMAP/4) // div 4 for extrasamples
550 Error ("Surface to large to map");
558 Fills in texorg, worldtotex. and textoworld
561 void CalcFaceVectors (lightinfo_t *l)
570 tex = &texinfo[l->face->texinfo];
572 // convert from float to double
573 for (i=0 ; i<2 ; i++)
574 for (j=0 ; j<3 ; j++)
575 l->worldtotex[i][j] = tex->vecs[i][j];
577 // calculate a normal to the texture axis. points can be moved along this
578 // without changing their S/T
579 texnormal[0] = tex->vecs[1][1]*tex->vecs[0][2]
580 - tex->vecs[1][2]*tex->vecs[0][1];
581 texnormal[1] = tex->vecs[1][2]*tex->vecs[0][0]
582 - tex->vecs[1][0]*tex->vecs[0][2];
583 texnormal[2] = tex->vecs[1][0]*tex->vecs[0][1]
584 - tex->vecs[1][1]*tex->vecs[0][0];
585 VectorNormalize (texnormal, texnormal);
587 // flip it towards plane normal
588 distscale = DotProduct (texnormal, l->facenormal);
591 Sys_FPrintf( SYS_VRB, "WARNING: Texture axis perpendicular to face\n");
596 distscale = -distscale;
597 VectorSubtract (vec3_origin, texnormal, texnormal);
600 // distscale is the ratio of the distance along the texture normal to
601 // the distance along the plane normal
602 distscale = 1/distscale;
604 for (i=0 ; i<2 ; i++)
606 len = VectorLength (l->worldtotex[i]);
607 dist = DotProduct (l->worldtotex[i], l->facenormal);
609 VectorMA (l->worldtotex[i], -dist, texnormal, l->textoworld[i]);
610 VectorScale (l->textoworld[i], (1/len)*(1/len), l->textoworld[i]);
614 // calculate texorg on the texture plane
615 for (i=0 ; i<3 ; i++)
616 l->texorg[i] = -tex->vecs[0][3]* l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i];
618 // project back to the face plane
619 dist = DotProduct (l->texorg, l->facenormal) - l->facedist - 1;
621 VectorMA (l->texorg, -dist, texnormal, l->texorg);
623 // compensate for org'd bmodels
624 VectorAdd (l->texorg, l->modelorg, l->texorg);
626 // total sample count
629 l->numsurfpt = w * h;
636 For each texture aligned grid point, back project onto the plane
637 to get the world xyz value of the sample point
640 void CalcPoints (lightinfo_t *l, float sofs, float tofs)
645 vec_t starts, startt, us, ut;
652 mids = (l->exactmaxs[0] + l->exactmins[0])/2;
653 midt = (l->exactmaxs[1] + l->exactmins[1])/2;
655 for (j=0 ; j<3 ; j++)
656 facemid[j] = l->texorg[j] + l->textoworld[0][j]*mids + l->textoworld[1][j]*midt;
660 l->numsurfpt = w * h;
662 starts = l->texmins[0]*16;
663 startt = l->texmins[1]*16;
667 for (t=0 ; t<h ; t++)
669 for (s=0 ; s<w ; s++, surf+=3)
671 us = starts + (s+sofs)*step;
672 ut = startt + (t+tofs)*step;
675 // if a line can be traced from surf to facemid, the point is good
676 for (i=0 ; i<6 ; i++)
678 // calculate texture point
679 for (j=0 ; j<3 ; j++)
680 surf[j] = l->texorg[j] + l->textoworld[0][j]*us
681 + l->textoworld[1][j]*ut;
683 leaf = Rad_PointInLeaf (surf);
684 if (leaf->contents != CONTENTS_SOLID)
686 if (!TestLine_r (0, facemid, surf))
728 //==============================================================
732 #define MAX_STYLES 32
738 int stylenums[MAX_STYLES];
739 float *samples[MAX_STYLES];
742 directlight_t *directlights[MAX_MAP_LEAFS];
743 facelight_t facelight[MAX_MAP_FACES];
751 entity_t *FindTargetEntity (char *target)
756 for (i=0 ; i<num_entities ; i++)
758 n = ValueForKey (&entities[i], "targetname");
759 if (!strcmp (n, target))
766 //#define DIRECT_LIGHT 3000
767 #define DIRECT_LIGHT 3
774 void CreateDirectLights (void)
792 for (i=0, p=patches ; i< (int) num_patches ; i++, p++)
794 if (p->totallight[0] < DIRECT_LIGHT
795 && p->totallight[1] < DIRECT_LIGHT
796 && p->totallight[2] < DIRECT_LIGHT)
800 dl = malloc(sizeof(directlight_t));
801 memset (dl, 0, sizeof(*dl));
803 VectorCopy (p->origin, dl->origin);
805 leaf = Rad_PointInLeaf (dl->origin);
806 cluster = leaf->cluster;
807 dl->next = directlights[cluster];
808 directlights[cluster] = dl;
810 dl->type = emit_surface;
811 VectorCopy (p->plane->normal, dl->normal);
813 dl->intensity = ColorNormalize (p->totallight, dl->color);
814 dl->intensity *= p->area * direct_scale;
815 VectorClear (p->totallight); // all sent now
821 for (i=0 ; i<num_entities ; i++)
824 name = ValueForKey (e, "classname");
825 if (strncmp (name, "light", 5))
829 dl = malloc(sizeof(directlight_t));
830 memset (dl, 0, sizeof(*dl));
832 GetVectorForKey (e, "origin", dl->origin);
833 dl->style = FloatForKey (e, "_style");
835 dl->style = FloatForKey (e, "style");
836 if (dl->style < 0 || dl->style >= MAX_LSTYLES)
839 leaf = Rad_PointInLeaf (dl->origin);
840 cluster = leaf->cluster;
842 dl->next = directlights[cluster];
843 directlights[cluster] = dl;
845 intensity = FloatForKey (e, "light");
847 intensity = FloatForKey (e, "_light");
850 _color = ValueForKey (e, "_color");
851 if (_color && _color[0])
853 sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]);
854 ColorNormalize (dl->color, dl->color);
857 dl->color[0] = dl->color[1] = dl->color[2] = 1.0;
858 dl->intensity = intensity*entity_scale;
859 dl->type = emit_point;
861 target = ValueForKey (e, "target");
863 if (!strcmp (name, "light_spot") || target[0])
865 dl->type = emit_spotlight;
866 dl->stopdot = FloatForKey (e, "_cone");
869 dl->stopdot = cos(dl->stopdot/180*3.14159);
871 { // point towards target
872 e2 = FindTargetEntity (target);
874 Sys_Printf ("WARNING: light at (%i %i %i) has missing target\n",
875 (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]);
878 GetVectorForKey (e2, "origin", dest);
879 VectorSubtract (dest, dl->origin, dl->normal);
880 VectorNormalize (dl->normal, dl->normal);
884 { // point down angle
885 angle = FloatForKey (e, "angle");
886 if (angle == ANGLE_UP)
888 dl->normal[0] = dl->normal[1] = 0;
891 else if (angle == ANGLE_DOWN)
893 dl->normal[0] = dl->normal[1] = 0;
899 dl->normal[0] = cos (angle/180*3.14159);
900 dl->normal[1] = sin (angle/180*3.14159);
906 Sys_FPrintf( SYS_VRB, "%i direct lights\n", numdlights);
913 Lightscale is the normalizer for multisampling
916 void GatherSampleLight (vec3_t pos, vec3_t normal,
917 float **styletable, int offset, int mapsize, float lightscale)
921 byte pvs[(MAX_MAP_LEAFS+7)/8];
928 // get the PVS for the pos to limit the number of checks
929 if (!PvsForOrigin (pos, pvs))
934 for (i = 0 ; i<dvis->numclusters ; i++)
936 if ( ! (pvs[ i>>3] & (1<<(i&7))) )
939 for (l=directlights[i] ; l ; l=l->next)
941 VectorSubtract (l->origin, pos, delta);
942 dist = VectorNormalize (delta, delta);
943 dot = DotProduct (delta, normal);
945 continue; // behind sample surface
951 scale = (l->intensity - dist) * dot;
955 dot2 = -DotProduct (delta, l->normal);
957 goto skipadd; // behind light surface
958 scale = (l->intensity / (dist*dist) ) * dot * dot2;
963 dot2 = -DotProduct (delta, l->normal);
964 if (dot2 <= l->stopdot)
965 goto skipadd; // outside light cone
966 scale = (l->intensity - dist) * dot;
969 Error ("Bad l->type");
972 if (TestLine_r (0, pos, l->origin))
973 continue; // occluded
978 // if this style doesn't have a table yet, allocate one
979 if (!styletable[l->style])
981 styletable[l->style] = malloc (mapsize);
982 memset (styletable[l->style], 0, mapsize);
985 dest = styletable[l->style] + offset;
986 // add some light to it
987 VectorMA (dest, scale*lightscale, l->color, dest);
999 Take the sample's collected light and
1000 add it back into the apropriate patch
1001 for the radiosity pass.
1003 The sample is added to all patches that might include
1004 any part of it. They are counted and averaged, so it
1005 doesn't generate extra light.
1008 void AddSampleToPatch (vec3_t pos, vec3_t color, int facenum)
1016 if (color[0] + color[1] + color[2] < 3)
1019 for (patch = face_patches[facenum] ; patch ; patch=patch->next)
1021 // see if the point is in this patch (roughly)
1022 WindingBounds (patch->winding, mins, maxs);
1023 for (i=0 ; i<3 ; i++)
1025 if (mins[i] > pos[i] + 16)
1027 if (maxs[i] < pos[i] - 16)
1031 // add the sample to the patch
1033 VectorAdd (patch->samplelight, color, patch->samplelight);
1045 float sampleofs[5][2] =
1046 { {0,0}, {-0.25, -0.25}, {0.25, -0.25}, {0.25, 0.25}, {-0.25, 0.25} };
1049 void BuildFacelights (int facenum)
1053 float *styletable[MAX_LSTYLES];
1061 f = &dfaces[facenum];
1063 if ( texinfo[f->texinfo].flags & (SURF_WARP|SURF_SKY) )
1064 return; // non-lit texture
1066 memset (styletable,0, sizeof(styletable));
1072 for (i=0 ; i<numsamples ; i++)
1074 memset (&l[i], 0, sizeof(l[i]));
1075 l[i].surfnum = facenum;
1077 VectorCopy (dplanes[f->planenum].normal, l[i].facenormal);
1078 l[i].facedist = dplanes[f->planenum].dist;
1081 VectorSubtract (vec3_origin, l[i].facenormal, l[i].facenormal);
1082 l[i].facedist = -l[i].facedist;
1085 // get the origin offset for rotating bmodels
1086 VectorCopy (face_offset[facenum], l[i].modelorg);
1088 CalcFaceVectors (&l[i]);
1089 CalcFaceExtents (&l[i]);
1090 CalcPoints (&l[i], sampleofs[i][0], sampleofs[i][1]);
1093 tablesize = l[0].numsurfpt * sizeof(vec3_t);
1094 styletable[0] = malloc(tablesize);
1095 memset (styletable[0], 0, tablesize);
1097 fl = &facelight[facenum];
1098 fl->numsamples = l[0].numsurfpt;
1099 fl->origins = malloc (tablesize);
1100 memcpy (fl->origins, l[0].surfpt, tablesize);
1102 for (i=0 ; i<l[0].numsurfpt ; i++)
1104 for (j=0 ; j<numsamples ; j++)
1106 GatherSampleLight (l[j].surfpt[i], l[0].facenormal, styletable,
1107 i*3, tablesize, 1.0/numsamples);
1110 // contribute the sample to one or more patches
1111 AddSampleToPatch (l[0].surfpt[i], styletable[0]+i*3, facenum);
1114 // average up the direct light on each patch for radiosity
1115 for (patch = face_patches[facenum] ; patch ; patch=patch->next)
1119 VectorScale (patch->samplelight, 1.0/patch->samples, patch->samplelight);
1123 // printf ("patch with no samples\n");
1127 for (i=0 ; i<MAX_LSTYLES ; i++)
1131 if (fl->numstyles == MAX_STYLES)
1133 fl->samples[fl->numstyles] = styletable[i];
1134 fl->stylenums[fl->numstyles] = i;
1138 // the light from DIRECT_LIGHTS is sent out, but the
1139 // texture itself should still be full bright
1141 if (face_patches[facenum]->baselight[0] >= DIRECT_LIGHT ||
1142 face_patches[facenum]->baselight[1] >= DIRECT_LIGHT ||
1143 face_patches[facenum]->baselight[2] >= DIRECT_LIGHT
1146 spot = fl->samples[0];
1147 for (i=0 ; i<l[0].numsurfpt ; i++, spot+=3)
1149 VectorAdd (spot, face_patches[facenum]->baselight, spot);
1159 Add the indirect lighting on top of the direct
1160 lighting and save into final map format
1163 void FinalLightFace (int facenum)
1169 triangulation_t *trian;
1175 vec3_t facemins, facemaxs;
1177 f = &dfaces[facenum];
1178 fl = &facelight[facenum];
1180 if ( texinfo[f->texinfo].flags & (SURF_WARP|SURF_SKY) )
1181 return; // non-lit texture
1184 f->lightofs = lightdatasize;
1185 lightdatasize += fl->numstyles*(fl->numsamples*3);
1187 // add green sentinals between lightmaps
1189 lightdatasize += 64*3;
1190 for (i=0 ; i<64 ; i++)
1191 dlightdata[lightdatasize-(i+1)*3 + 1] = 255;
1194 if (lightdatasize > MAX_MAP_LIGHTING)
1195 Error ("MAX_MAP_LIGHTING");
1199 f->styles[1] = f->styles[2] = f->styles[3] = 0xff;
1202 // set up the triangulation
1206 ClearBounds (facemins, facemaxs);
1207 for (i=0 ; i<f->numedges ; i++)
1211 ednum = dsurfedges[f->firstedge+i];
1213 AddPointToBounds (dvertexes[dedges[ednum].v[0]].point,
1214 facemins, facemaxs);
1216 AddPointToBounds (dvertexes[dedges[-ednum].v[1]].point,
1217 facemins, facemaxs);
1220 trian = AllocTriangulation (&dplanes[f->planenum]);
1222 // for all faces on the plane, add the nearby patches
1223 // to the triangulation
1224 for (pfacenum = planelinks[f->side][f->planenum]
1225 ; pfacenum ; pfacenum = facelinks[pfacenum])
1227 for (patch = face_patches[pfacenum] ; patch ; patch=patch->next)
1229 for (i=0 ; i < 3 ; i++)
1231 if (facemins[i] - patch->origin[i] > subdiv*2)
1233 if (patch->origin[i] - facemaxs[i] > subdiv*2)
1237 continue; // not needed for this face
1238 AddPointToTriangulation (patch, trian);
1241 for (i=0 ; i<trian->numpoints ; i++)
1242 memset (trian->edgematrix[i], 0, trian->numpoints*sizeof(trian->edgematrix[0][0]) );
1243 TriangulatePoints (trian);
1247 // sample the triangulation
1250 // _minlight allows models that have faces that would not be
1251 // illuminated to receive a mottled light pattern instead of
1253 minlight = FloatForKey (face_entity[facenum], "_minlight") * 128;
1255 dest = &dlightdata[f->lightofs];
1257 if (fl->numstyles > MAXLIGHTMAPS)
1259 fl->numstyles = MAXLIGHTMAPS;
1260 Sys_Printf ("face with too many lightstyles: (%f %f %f)\n",
1261 face_patches[facenum]->origin[0],
1262 face_patches[facenum]->origin[1],
1263 face_patches[facenum]->origin[2]
1267 for (st=0 ; st<fl->numstyles ; st++)
1269 f->styles[st] = fl->stylenums[st];
1270 for (j=0 ; j<fl->numsamples ; j++)
1272 VectorCopy ( (fl->samples[st]+j*3), lb);
1273 if (numbounce > 0 && st == 0)
1277 SampleTriangulation (fl->origins + j*3, trian, add);
1278 VectorAdd (lb, add, lb);
1280 // add an ambient term if desired
1285 VectorScale (lb, lightscale, lb);
1287 // we need to clamp without allowing hue to change
1288 for (k=0 ; k<3 ; k++)
1298 newmax = 0; // roundoff problems
1299 if (newmax < minlight)
1301 newmax = minlight + (rand()%48);
1303 if (newmax > maxlight)
1306 for (k=0 ; k<3 ; k++)
1308 *dest++ = lb[k]*newmax/max;
1314 FreeTriangulation (trian);