1 NOTE: this patch set is autogenerated from the "singlepatches" subdirectory of nexuiz/trunk/misc.
3 Do not commit changes to THIS!
6 sh mergepatches.sh > gtkradiant-nexuiz-patchset.diff
7 before committing new singlepatches!
11 Index: libs/picomodel/pm_obj.c
12 ===================================================================
13 --- libs/picomodel/pm_obj.c (revision 290)
14 +++ libs/picomodel/pm_obj.c (working copy)
20 static int _obj_mtl_load( picoModel_t *model )
22 - //picoShader_t *curShader = NULL;
23 + picoShader_t *curShader = NULL;
25 picoByte_t *mtlBuffer;
28 /* get next token in material file */
29 if (_pico_parse( p,1 ) == NULL)
34 /* skip empty lines */
35 if (p->token == NULL || !strlen( p->token ))
37 else if (!_pico_stricmp(p->token,"map_kd"))
40 + picoShader_t *shader;
42 /* pointer to current shader must be valid */
43 if (curShader == NULL)
45 _pico_printf( PICO_ERROR,"Missing material map name in MTL, line %d.",p->curLine);
46 _obj_mtl_error_return;
48 + /* create a new pico shader */
49 + shader = PicoNewShader( model );
51 + _obj_mtl_error_return;
52 /* set shader map name */
53 PicoSetShaderMapName( shader,mapName );
56 /* return with success */
62 * loads a wavefront obj model file.
64 PicoSetModelFileName( model,fileName );
66 /* try loading the materials; we don't handle the result */
69 _obj_mtl_load( model );
76 + else if (!_pico_stricmp(p->token,"usemtl"))
78 + picoShader_t *shader;
81 + /* get material name */
82 + name = _pico_parse( p,0 );
84 + /* validate material name */
85 + if (name == NULL || !strlen(name))
87 + _pico_printf( PICO_ERROR,"Missing material name in OBJ, line %d.",p->curLine);
91 + shader = PicoFindShader( model, name, 1 );
94 + _pico_printf( PICO_ERROR,"Undefined material name in OBJ, line %d. Making a default shader.",p->curLine);
96 + /* create a new pico shader */
97 + shader = PicoNewShader( model );
100 + PicoSetShaderName( shader,name );
101 + PicoSetShaderMapName( shader,name );
102 + PicoSetSurfaceShader( curSurface, shader );
107 + PicoSetSurfaceShader( curSurface, shader );
111 /* skip unparsed rest of line and continue */
112 _pico_parse_skip_rest( p );
114 Index: radiant/map.cpp
115 ===================================================================
116 --- radiant/map.cpp (revision 304)
117 +++ radiant/map.cpp (working copy)
118 @@ -270,6 +270,100 @@
122 +void Map_DoTargetFix(entity_t *e, const char *target, int num_ents, CPtrArray *ents, GPtrArray *new_ents)
126 + char newtarget[128];
127 + entity_t *e_target;
129 + qboolean targetnameFound = FALSE;
130 + qboolean targetFound = FALSE;
131 + qboolean colliding = FALSE;
138 + target = g_strdup(target);
140 + // check the current map entities for an actual collision
141 + for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
144 + !strcmp(target, ValueForKey(e_target, "target"))
146 + !strcmp(target, ValueForKey(e_target, "killtarget"))
149 + // make sure the collision is not between two imported entities
150 + for(j=0; j<(int)new_ents->len; j++)
152 + if(e_target == g_ptr_array_index(new_ents, j))
154 + targetFound = true;
155 + goto no_collision_yet_1;
163 + !strcmp(target, ValueForKey(e_target, "targetname"))
166 + // make sure the collision is not between two imported entities
167 + for(j=0; j<(int)new_ents->len; j++)
169 + if(e_target == g_ptr_array_index(new_ents, j))
171 + targetnameFound = true;
172 + goto no_collision_yet_2;
181 + // find the matching targeted entity(s)
182 + if(colliding && targetFound && targetnameFound)
184 + // We got a collision
185 + // first look for a non-conflicting target name
186 + id = GetUniqueTargetId(1);
187 + sprintf(newtarget, "t%i", id);
189 + for(j=num_ents-1; j>0; j--)
191 + e_target = (entity_t*)ents->GetAt(j);
192 + if(e_target != NULL)
194 + const char *targetname = ValueForKey(e_target, "targetname");
195 + if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
197 + SetKeyValue(e_target, "targetname", newtarget);
199 + targetname = ValueForKey(e_target, "target");
200 + if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
202 + SetKeyValue(e_target, "target", newtarget);
204 + targetname = ValueForKey(e_target, "killtarget");
205 + if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
207 + SetKeyValue(e_target, "killtarget", newtarget);
216 /*!\todo Possibly make the import Undo-friendly by calling Undo_End for new brushes and ents */
217 void Map_ImportEntities(CPtrArray *ents, bool bAddSelected = false)
219 @@ -466,60 +560,27 @@
223 - // fix target/targetname collisions
224 - if ((g_PrefsDlg.m_bDoTargetFix) && (strcmp(ValueForKey(e, "target"), "") != 0))
226 - GPtrArray *t_ents = g_ptr_array_new();
227 - entity_t *e_target;
228 - const char *target = ValueForKey(e, "target");
229 - qboolean bCollision=FALSE;
230 + // keep a list of ents added to avoid testing collisions against them
231 + g_ptr_array_add(new_ents, (gpointer)e);
233 - // check the current map entities for an actual collision
234 - for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
236 - if(!strcmp(target, ValueForKey(e_target, "target")))
239 - // make sure the collision is not between two imported entities
240 - for(j=0; j<(int)new_ents->len; j++)
242 - if(e_target == g_ptr_array_index(new_ents, j))
243 - bCollision = FALSE;
248 - // find the matching targeted entity(s)
251 - for(j=num_ents-1; j>0; j--)
253 - e_target = (entity_t*)ents->GetAt(j);
254 - if(e_target != NULL && e_target != e)
256 - const char *targetname = ValueForKey(e_target, "targetname");
257 - if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
258 - g_ptr_array_add(t_ents, (gpointer)e_target);
261 - if(t_ents->len > 0)
263 - // link the first to get a unique target/targetname
264 - Entity_Connect(e, (entity_t*)g_ptr_array_index(t_ents,0));
265 - // set the targetname of the rest of them manually
266 - for(j = 1; j < (int)t_ents->len; j++)
267 - SetKeyValue( (entity_t*)g_ptr_array_index(t_ents, j), "targetname", ValueForKey(e, "target") );
269 - g_ptr_array_free(t_ents, FALSE);
273 // add the entity to the end of the entity list
274 Entity_AddToList(e, &entities);
275 g_qeglobals.d_num_entities++;
277 - // keep a list of ents added to avoid testing collisions against them
278 - g_ptr_array_add(new_ents, (gpointer)e);
279 + // fix target/targetname collisions
280 + if (g_PrefsDlg.m_bDoTargetFix)
282 + const char *target;
284 + target = ValueForKey(e, "target");
285 + Map_DoTargetFix(e, target, num_ents, ents, new_ents);
287 + target = ValueForKey(e, "killtarget");
288 + Map_DoTargetFix(e, target, num_ents, ents, new_ents);
290 + target = ValueForKey(e, "targetname");
291 + Map_DoTargetFix(e, target, num_ents, ents, new_ents);
295 g_ptr_array_free(new_ents, FALSE);
296 Index: radiant/drag.cpp
297 ===================================================================
298 --- radiant/drag.cpp (revision 304)
299 +++ radiant/drag.cpp (working copy)
304 -void UpdateTarget(vec3_t origin, vec3_t dir)
311 - t = Test_Ray (origin, dir, 0);
316 - pe = t.brush->owner;
321 - // is this the first?
322 - if (peLink != NULL)
325 - // Get the target id from out current target
326 - // if there is no id, make one
328 - i = IntForKey(pe, "target");
331 - i = GetUniqueTargetId(1);
332 - sprintf(sz, "%d", i);
334 - SetKeyValue(pe, "target", sz);
337 - // set the target # into our src
339 - sprintf(sz, "%d", i);
340 - SetKeyValue(peLink, "targetname", sz);
342 - Sys_UpdateWindows(W_ENTITY);
346 - // promote the target to the src
355 Index: radiant/xywindow.cpp
356 ===================================================================
357 --- radiant/xywindow.cpp (revision 304)
358 +++ radiant/xywindow.cpp (working copy)
359 @@ -270,16 +270,17 @@
360 void DrawPathLines (void)
364 + vec3_t mid, mid1, v;
368 - vec3_t dir, s1, s2;
369 + vec3_t dir, s1, s2, dirortho;
373 const char *ent_target[MAX_MAP_ENTITIES];
374 entity_t *ent_entity[MAX_MAP_ENTITIES];
377 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
380 ent_entity[num_entities] = te;
383 + ent_target[num_entities] = ValueForKey (te, "killtarget");
384 + if (ent_target[num_entities][0])
386 + ent_entity[num_entities] = te;
391 for (se = entities.next ; se != &entities ; se = se->next)
393 if (sb == &se->brushes)
396 + for (i=0 ; i<3 ; i++)
397 + mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
399 for (k=0 ; k<num_entities ; k++)
401 if (strcmp (ent_target[k], psz))
402 @@ -318,14 +328,20 @@
403 if (tb == &te->brushes)
406 - for (i=0 ; i<3 ; i++)
407 - mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
409 + if(!strcmp(ValueForKey(te, "target"), psz))
411 + if(!strcmp(ValueForKey(te, "killtarget"), psz))
414 for (i=0 ; i<3 ; i++)
415 mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
417 VectorSubtract (mid1, mid, dir);
418 len = VectorNormalize (dir, dir);
419 + dirortho[0] = -dir[1];
420 + dirortho[1] = dir[0];
422 s1[0] = -dir[1]*8 + dir[0]*8;
423 s2[0] = dir[1]*8 + dir[0]*8;
424 s1[1] = dir[0]*8 + dir[1]*8;
426 qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
430 - qglVertex3fv(mid1);
431 + for(i = -lines + 1; i < lines; i += 2)
433 + VectorMA(mid, i, dirortho, v);
435 + VectorMA(mid1, i, dirortho, v);
439 arrows = (int)(len / 256) + 1;
441 Index: radiant/targetname.cpp
442 ===================================================================
443 --- radiant/targetname.cpp (revision 304)
444 +++ radiant/targetname.cpp (working copy)
447 connects two entities creating a unique target/targetname value
449 -void Entity_Connect(entity_t *e1, entity_t *e2)
450 +void Entity_Connect(entity_t *e1, entity_t *e2, bool kill)
452 const char *maptarget;
454 - int maxtarget=0; // highest t# value in the map
455 + int id=0; // highest t# value in the map
456 entity_t *e; // map entities
463 - for (e=entities.next ; e != &entities ; e=e->next)
465 - maptarget = ValueForKey (e, "target");
466 - if (maptarget && maptarget[0])
468 - int targetnum = atoi(maptarget+1);
469 - if (targetnum > maxtarget)
470 - maxtarget = targetnum;
473 - sprintf (newtarget, "t%i", maxtarget+1);
474 + id = GetUniqueTargetId(1);
475 + sprintf (newtarget, "t%i", id);
478 Sys_Printf("Connecting entities with new target/targetname: %s\n", newtarget);
481 - SetKeyValue (e1, "target", newtarget);
483 + SetKeyValue (e1, "killtarget", newtarget);
485 + SetKeyValue (e1, "target", newtarget);
486 SetKeyValue (e2, "targetname", newtarget);
489 +static int TargetIdForKey(entity_t *pe, const char *key)
491 + const char *p = ValueForKey(pe, key);
496 + return atoi(p + 1);
499 int GetUniqueTargetId(int iHint)
511 for (; pe != NULL && pe != &entities ; pe = pe->next)
513 - i = IntForKey(pe, "target");
516 - iMin = MIN(i, iMin);
517 - iMax = MAX(i, iMax);
521 + i = TargetIdForKey(pe, "target");
522 + iMax = MAX(i, iMax);
525 + i = TargetIdForKey(pe, "targetname");
526 + iMax = MAX(i, iMax);
529 + i = TargetIdForKey(pe, "killtarget");
530 + iMax = MAX(i, iMax);
536 Index: radiant/qe3.cpp
537 ===================================================================
538 --- radiant/qe3.cpp (revision 304)
539 +++ radiant/qe3.cpp (working copy)
541 from the first selected to the secon
544 -void ConnectEntities (void)
545 +void ConnectEntities (bool kill)
553 - target = ValueForKey (e1, "target");
554 + target = ValueForKey (e1, kill ? "killtarget" : "target");
555 if (target && target[0])
556 newtarg = g_strdup(target);
558 @@ -743,12 +743,12 @@
559 if(target && target[0])
560 newtarg = g_strdup(target);
562 - Entity_Connect(e1, e2);
563 + Entity_Connect(e1, e2, kill);
568 - SetKeyValue(e1, "target", newtarg);
569 + SetKeyValue(e1, kill ? "killtarget" : "target", newtarg);
570 SetKeyValue(e2, "targetname", newtarg);
574 ===================================================================
575 --- radiant/qe3.h (revision 304)
576 +++ radiant/qe3.h (working copy)
578 void SelectEdgeByRay (vec3_t org, vec3_t dir);
579 void SelectVertexByRay (vec3_t org, vec3_t dir);
581 -void ConnectEntities (void);
582 +void ConnectEntities (bool kill = false);
584 extern int update_bits;
590 -void Entity_Connect(entity_t *e1, entity_t *e2);
591 +void Entity_Connect(entity_t *e1, entity_t *e2, bool kill = false);
592 int GetUniqueTargetId(int iHint);
595 Index: tools/quake3/q3map2/convert_map.c
596 ===================================================================
597 --- tools/quake3/q3map2/convert_map.c (revision 191)
598 +++ tools/quake3/q3map2/convert_map.c (working copy)
600 #define SNAP_FLOAT_TO_INT 4
601 #define SNAP_INT_TO_FLOAT (1.0 / SNAP_FLOAT_TO_INT)
603 +typedef vec_t vec2_t[2];
605 +static vec_t Det3x3(vec_t a00, vec_t a01, vec_t a02,
606 + vec_t a10, vec_t a11, vec_t a12,
607 + vec_t a20, vec_t a21, vec_t a22)
610 + a00 * (a11 * a22 - a12 * a21)
611 + - a01 * (a10 * a22 - a12 * a20)
612 + + a02 * (a10 * a21 - a11 * a20);
615 +void GetBestSurfaceTriangleMatchForBrushside(side_t *buildSide, bspDrawVert_t *bestVert[3])
617 + bspDrawSurface_t *s;
623 + vec3_t v1v0, v2v0, norm;
624 + bspDrawVert_t *vert[3];
625 + winding_t *polygon;
626 + plane_t *buildPlane = &mapplanes[buildSide->planenum];
629 + // first, start out with NULLs
630 + bestVert[0] = bestVert[1] = bestVert[2] = NULL;
632 + // brute force through all surfaces
633 + for(s = bspDrawSurfaces; s != bspDrawSurfaces + numBSPDrawSurfaces; ++s)
635 + if(s->surfaceType != MST_PLANAR && s->surfaceType != MST_TRIANGLE_SOUP)
637 + if(strcmp(buildSide->shaderInfo->shader, bspShaders[s->shaderNum].shader))
639 + for(t = 0; t + 3 <= s->numIndexes; t += 3)
641 + vert[0] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 0]];
642 + vert[1] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 1]];
643 + vert[2] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 2]];
644 + if(s->surfaceType == MST_PLANAR)
646 + VectorSubtract(vert[0]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
647 + VectorSubtract(vert[1]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
648 + VectorSubtract(vert[2]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
652 + // this is more prone to roundoff errors, but with embedded
653 + // models, there is no better way
654 + VectorSubtract(vert[1]->xyz, vert[0]->xyz, v1v0);
655 + VectorSubtract(vert[2]->xyz, vert[0]->xyz, v2v0);
656 + CrossProduct(v2v0, v1v0, norm);
657 + VectorNormalize(norm, norm);
658 + VectorSubtract(norm, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
660 + if(abs(DotProduct(vert[0]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
661 + if(abs(DotProduct(vert[1]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
662 + if(abs(DotProduct(vert[2]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
663 + // Okay. Correct surface type, correct shader, correct plane. Let's start with the business...
664 + polygon = CopyWinding(buildSide->winding);
665 + for(i = 0; i < 3; ++i)
670 + vec3_t *v1 = &vert[(i+1)%3]->xyz;
671 + vec3_t *v2 = &vert[(i+2)%3]->xyz;
674 + vec3_t sideDirection;
675 + // we now need to generate triNormal and triDist so that they represent the plane spanned by normal and (v2 - v1).
676 + VectorSubtract(*v2, *v1, sideDirection);
677 + CrossProduct(sideDirection, buildPlane->normal, triNormal);
678 + triDist = DotProduct(*v1, triNormal);
679 + ChopWindingInPlace(&polygon, triNormal, triDist, distanceEpsilon);
683 + thisarea = WindingArea(polygon);
686 + if(thisarea > best)
689 + bestVert[0] = vert[0];
690 + bestVert[1] = vert[1];
691 + bestVert[2] = vert[2];
693 + FreeWinding(polygon);
698 + //if(strncmp(buildSide->shaderInfo->shader, "textures/common/", 16))
699 + // fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide->shaderInfo->shader, matches, best);
702 static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
709 + plane_t *buildPlane;
711 + bspDrawVert_t *vert[3];
716 fprintf( f, "\t// brush %d\n", num );
717 fprintf( f, "\t{\n" );
718 + fprintf( f, "\tbrushDef\n" );
719 + fprintf( f, "\t{\n" );
721 /* clear out build brush */
722 for( i = 0; i < buildBrush->numsides; i++ )
725 buildSide = &buildBrush->sides[ i ];
728 + buildPlane = &mapplanes[ buildSide->planenum ];
731 if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
734 + // st-texcoords -> texMat block
735 + // start out with dummy
736 + VectorSet(buildSide->texMat[0], 1/32.0, 0, 0);
737 + VectorSet(buildSide->texMat[1], 0, 1/32.0, 0);
739 + // find surface for this side (by brute force)
741 + // - meshverts point in pairs of three into verts
743 + // - find the triangle that has most in common with our side
744 + GetBestSurfaceTriangleMatchForBrushside(buildSide, vert);
747 + if(vert[0] && vert[1] && vert[2])
751 + vec3_t xy1I, xy1J, xy1K;
752 + vec2_t stI, stJ, stK;
753 + vec_t D, D0, D1, D2;
755 + ComputeAxisBase(buildPlane->normal, texX, texY);
757 + VectorSet(xy1I, DotProduct(vert[0]->xyz, texX), DotProduct(vert[0]->xyz, texY), 1);
758 + VectorSet(xy1J, DotProduct(vert[1]->xyz, texX), DotProduct(vert[1]->xyz, texY), 1);
759 + VectorSet(xy1K, DotProduct(vert[2]->xyz, texX), DotProduct(vert[2]->xyz, texY), 1);
760 + stI[0] = vert[0]->st[0]; stI[1] = vert[0]->st[1];
761 + stJ[0] = vert[1]->st[0]; stJ[1] = vert[1]->st[1];
762 + stK[0] = vert[2]->st[0]; stK[1] = vert[2]->st[1];
764 + // - solve linear equations:
765 + // - (x, y) := xyz . (texX, texY)
766 + // - st[i] = texMat[i][0]*x + texMat[i][1]*y + texMat[i][2]
767 + // (for three vertices)
769 + xy1I[0], xy1I[1], 1,
770 + xy1J[0], xy1J[1], 1,
771 + xy1K[0], xy1K[1], 1
775 + for(i = 0; i < 2; ++i)
778 + stI[i], xy1I[1], 1,
779 + stJ[i], xy1J[1], 1,
783 + xy1I[0], stI[i], 1,
784 + xy1J[0], stJ[i], 1,
788 + xy1I[0], xy1I[1], stI[i],
789 + xy1J[0], xy1J[1], stJ[i],
790 + xy1K[0], xy1K[1], stK[i]
792 + VectorSet(buildSide->texMat[i], D0 / D, D1 / D, D2 / D);
797 + fprintf(stderr, "degenerate triangle found when solving texMat equations for\n(%f %f %f) (%f %f %f) (%f %f %f)\n( %f %f %f )\n( %f %f %f ) -> ( %f %f )\n( %f %f %f ) -> ( %f %f )\n( %f %f %f ) -> ( %f %f )\n",
798 + buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2],
799 + vert[0]->normal[0], vert[0]->normal[1], vert[0]->normal[2],
800 + texX[0], texX[1], texX[2], texY[0], texY[1], texY[2],
801 + vert[0]->xyz[0], vert[0]->xyz[1], vert[0]->xyz[2], xy1I[0], xy1I[1],
802 + vert[1]->xyz[0], vert[1]->xyz[1], vert[1]->xyz[2], xy1J[0], xy1J[1],
803 + vert[2]->xyz[0], vert[2]->xyz[1], vert[2]->xyz[2], xy1K[0], xy1K[1]
807 + if(strncmp(buildSide->shaderInfo->shader, "textures/common/", 16))
808 + fprintf(stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide->shaderInfo->shader);
810 /* get texture name */
811 if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
812 @@ -130,14 +313,21 @@
814 /* print brush side */
815 /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
816 - fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s 0 0 0 0.5 0.5 0 0 0\n",
817 + fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( ( %.8f %.8f %.8f ) ( %.8f %.8f %.8f ) ) %s %d 0 0\n",
818 pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
819 pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
820 pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
822 + buildSide->texMat[0][0], buildSide->texMat[0][1], buildSide->texMat[0][2],
823 + buildSide->texMat[1][0], buildSide->texMat[1][1], buildSide->texMat[1][2],
825 + // DEBUG: valid ? 0 : C_DETAIL
828 + // TODO write brush primitives format here
832 + fprintf( f, "\t}\n" );
833 fprintf( f, "\t}\n\n" );
836 Index: tools/quake3/q3map2/main.c
837 ===================================================================
838 --- tools/quake3/q3map2/main.c (revision 191)
839 +++ tools/quake3/q3map2/main.c (working copy)
841 Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
844 + else if( !strcmp( argv[ i ], "-ne" ) )
846 + normalEpsilon = atof( argv[ i + 1 ] );
848 + Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
850 + else if( !strcmp( argv[ i ], "-de" ) )
852 + distanceEpsilon = atof( argv[ i + 1 ] );
854 + Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
858 /* clean up map name */
859 Index: tools/quake3/q3map2/model.c
860 ===================================================================
861 --- tools/quake3/q3map2/model.c (revision 193)
862 +++ tools/quake3/q3map2/model.c (working copy)
865 picoIndex_t *indexes;
867 + double normalEpsilon_save;
868 + double distanceEpsilon_save;
873 /* ydnar: giant hack land: generate clipping brushes for model triangles */
874 if( si->clipModel || (spawnFlags & 2) ) /* 2nd bit */
876 - vec3_t points[ 3 ], backs[ 3 ];
877 + vec3_t points[ 4 ], backs[ 3 ];
878 vec4_t plane, reverse, pa, pb, pc;
883 @@ -437,90 +438,141 @@
884 /* note: this doesn't work as well as simply using the plane of the triangle, below */
885 for( k = 0; k < 3; k++ )
887 - if( fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 1) % 3 ] ) &&
888 - fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 2) % 3 ] ) )
889 + if( fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 1) % 3 ] ) &&
890 + fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 2) % 3 ] ) )
892 backs[ j ][ k ] += dv->normal[ k ] < 0.0f ? 64.0f : -64.0f;
898 + VectorCopy( points[0], points[3] ); // for cyclic usage
900 /* make plane for triangle */
901 + // div0: add some extra spawnflags:
902 + // 0: snap normals to axial planes for extrusion
903 + // 8: extrude with the original normals
904 + // 16: extrude only with up/down normals (ideal for terrain)
905 + // 24: extrude by distance zero (may need engine changes)
906 if( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) )
909 + float backPlaneDistance = 2;
911 + if(spawnFlags & 8) // use a DOWN normal
913 + if(spawnFlags & 16)
915 + // 24: normal as is, and zero width (broken)
916 + VectorCopy(plane, bestNormal);
921 + VectorCopy(plane, bestNormal);
926 + if(spawnFlags & 16)
928 + // 16: UP/DOWN normal
929 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
934 + if(fabs(plane[0]) > fabs(plane[1])) // x>y
935 + if(fabs(plane[1]) > fabs(plane[2])) // x>y, y>z
936 + VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
938 + if(fabs(plane[0]) > fabs(plane[2])) // x>z, z>=y
939 + VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
941 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
943 + if(fabs(plane[1]) > fabs(plane[2])) // y>z, y>=x
944 + VectorSet(bestNormal, 0, (plane[1] >= 0 ? 1 : -1), 0);
946 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
950 + /* build a brush */
951 + buildBrush = AllocBrush( 48 );
952 + buildBrush->entityNum = mapEntityNum;
953 + buildBrush->original = buildBrush;
954 + buildBrush->contentShader = si;
955 + buildBrush->compileFlags = si->compileFlags;
956 + buildBrush->contentFlags = si->contentFlags;
957 + normalEpsilon_save = normalEpsilon;
958 + distanceEpsilon_save = distanceEpsilon;
959 + if(si->compileFlags & C_STRUCTURAL) // allow forced structural brushes here
961 + buildBrush->detail = qfalse;
963 + // only allow EXACT matches when snapping for these (this is mostly for caulk brushes inside a model)
964 + if(normalEpsilon > 0)
966 + if(distanceEpsilon > 0)
967 + distanceEpsilon = 0;
970 + buildBrush->detail = qtrue;
972 /* regenerate back points */
973 for( j = 0; j < 3; j++ )
976 dv = &ds->verts[ ds->indexes[ i + j ] ];
979 - VectorCopy( dv->xyz, backs[ j ] );
981 - /* find nearest axial to plane normal and push back points opposite */
982 - for( k = 0; k < 3; k++ )
984 - if( fabs( plane[ k ] ) > fabs( plane[ (k + 1) % 3 ] ) &&
985 - fabs( plane[ k ] ) > fabs( plane[ (k + 2) % 3 ] ) )
987 - backs[ j ][ k ] += plane[ k ] < 0.0f ? 64.0f : -64.0f;
992 + // shift by some units
993 + VectorMA(dv->xyz, -64.0f, bestNormal, backs[j]); // 64 prevents roundoff errors a bit
997 /* make back plane */
998 VectorScale( plane, -1.0f, reverse );
999 - reverse[ 3 ] = -(plane[ 3 ] - 1);
1001 - /* make back pyramid point */
1002 - VectorCopy( points[ 0 ], nadir );
1003 - VectorAdd( nadir, points[ 1 ], nadir );
1004 - VectorAdd( nadir, points[ 2 ], nadir );
1005 - VectorScale( nadir, 0.3333333333333f, nadir );
1006 - VectorMA( nadir, -2.0f, plane, nadir );
1008 - /* make 3 more planes */
1009 - //% if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], nadir ) &&
1010 - //% PlaneFromPoints( pb, points[ 1 ], points[ 0 ], nadir ) &&
1011 - //% PlaneFromPoints( pc, points[ 0 ], points[ 2 ], nadir ) )
1012 + reverse[ 3 ] = -plane[ 3 ];
1013 + if((spawnFlags & 24) != 24)
1014 + reverse[3] += DotProduct(bestNormal, plane) * backPlaneDistance;
1015 + // that's at least sqrt(1/3) backPlaneDistance, unless in DOWN mode; in DOWN mode, we are screwed anyway if we encounter a plane that's perpendicular to the xy plane)
1017 if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], backs[ 1 ] ) &&
1018 - PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
1019 - PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
1020 + PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
1021 + PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
1023 - /* build a brush */
1024 - buildBrush = AllocBrush( 48 );
1026 - buildBrush->entityNum = mapEntityNum;
1027 - buildBrush->original = buildBrush;
1028 - buildBrush->contentShader = si;
1029 - buildBrush->compileFlags = si->compileFlags;
1030 - buildBrush->contentFlags = si->contentFlags;
1031 - buildBrush->detail = qtrue;
1033 /* set up brush sides */
1034 buildBrush->numsides = 5;
1035 for( j = 0; j < buildBrush->numsides; j++ )
1036 buildBrush->sides[ j ].shaderInfo = si;
1038 buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
1039 - buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 1, &points[ 2 ] );
1040 - buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 1, &points[ 1 ] );
1041 - buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 1, &points[ 0 ] );
1042 - buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, points );
1044 - /* add to entity */
1045 - if( CreateBrushWindings( buildBrush ) )
1048 - //% EmitBrushes( buildBrush, NULL, NULL );
1049 - buildBrush->next = entities[ mapEntityNum ].brushes;
1050 - entities[ mapEntityNum ].brushes = buildBrush;
1051 - entities[ mapEntityNum ].numBrushes++;
1054 - free( buildBrush );
1055 + buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 2, &points[ 1 ] ); // pa contains points[1] and points[2]
1056 + buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 2, &points[ 0 ] ); // pb contains points[0] and points[1]
1057 + buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 2, &points[ 2 ] ); // pc contains points[2] and points[0] (copied to points[3]
1058 + buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, backs );
1066 + normalEpsilon = normalEpsilon_save;
1067 + distanceEpsilon = distanceEpsilon_save;
1069 + /* add to entity */
1070 + if( CreateBrushWindings( buildBrush ) )
1073 + //% EmitBrushes( buildBrush, NULL, NULL );
1074 + buildBrush->next = entities[ mapEntityNum ].brushes;
1075 + entities[ mapEntityNum ].brushes = buildBrush;
1076 + entities[ mapEntityNum ].numBrushes++;
1079 + free( buildBrush );
1083 Index: tools/quake3/q3map2/map.c
1084 ===================================================================
1085 --- tools/quake3/q3map2/map.c (revision 193)
1086 +++ tools/quake3/q3map2/map.c (working copy)
1088 snaps a plane to normal/distance epsilons
1091 -void SnapPlane( vec3_t normal, vec_t *dist )
1092 +void SnapPlane( vec3_t normal, vec_t *dist, vec3_t center )
1094 // SnapPlane disabled by LordHavoc because it often messes up collision
1095 // brushes made from triangles of embedded models, and it has little effect
1096 @@ -193,7 +193,13 @@
1097 SnapPlane reenabled by namespace because of multiple reports of
1098 q3map2-crashes which were triggered by this patch.
1100 + // div0: ensure the point "center" stays on the plane (actually, this
1101 + // rotates the plane around the point center).
1102 + // if center lies on the plane, it is guaranteed to stay on the plane by
1104 + vec_t centerDist = DotProduct(normal, center);
1105 SnapNormal( normal );
1106 + *dist += (DotProduct(normal, center) - centerDist);
1108 if( fabs( *dist - Q_rint( *dist ) ) < distanceEpsilon )
1109 *dist = Q_rint( *dist );
1111 must be within an epsilon distance of the plane
1114 -int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points )
1115 +int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points ) // NOTE: this has a side effect on the normal. Good or bad?
1119 @@ -215,10 +221,14 @@
1123 + vec3_t centerofweight;
1125 + VectorClear(centerofweight);
1126 + for(i = 0; i < numPoints; ++i)
1127 + VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
1130 /* hash the plane */
1131 - SnapPlane( normal, &dist );
1132 + SnapPlane( normal, &dist, centerofweight );
1133 hash = (PLANE_HASHES - 1) & (int) fabs( dist );
1135 /* search the border bins as well */
1136 @@ -259,7 +269,13 @@
1140 - SnapPlane( normal, &dist );
1141 + vec3_t centerofweight;
1143 + VectorClear(centerofweight);
1144 + for(i = 0; i < numPoints; ++i)
1145 + VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
1147 + SnapPlane( normal, &dist, centerofweight );
1148 for( i = 0, p = mapplanes; i < nummapplanes; i++, p++ )
1150 if( PlaneEqual( p, normal, dist ) )
1151 Index: tools/quake3/q3map2/shaders.c
1152 ===================================================================
1153 --- tools/quake3/q3map2/shaders.c (revision 191)
1154 +++ tools/quake3/q3map2/shaders.c (working copy)
1155 @@ -793,8 +793,14 @@
1158 if( VectorLength( si->color ) <= 0.0f )
1160 ColorNormalize( color, si->color );
1161 - VectorScale( color, (1.0f / count), si->averageColor );
1162 + VectorScale( color, (1.0f / count), si->averageColor );
1166 + VectorCopy( si->color, si->averageColor );
1171 Index: tools/quake3/q3map2/light_ydnar.c
1172 ===================================================================
1173 --- tools/quake3/q3map2/light_ydnar.c (revision 191)
1174 +++ tools/quake3/q3map2/light_ydnar.c (working copy)
1175 @@ -1767,6 +1864,8 @@
1176 float tests[ 4 ][ 2 ] = { { 0.0f, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
1178 float stackLightLuxels[ STACK_LL_SIZE ];
1180 + float *floodlight;
1183 /* bail if this number exceeds the number of raw lightmaps */
1184 @@ -2223,6 +2332,78 @@
1185 FreeTraceLights( &trace );
1187 /* -----------------------------------------------------------------
1189 + ----------------------------------------------------------------- */
1193 + /* walk lightmaps */
1194 + for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
1197 + if( lm->superLuxels[ lightmapNum ] == NULL )
1200 + /* apply floodlight to each luxel */
1201 + for( y = 0; y < lm->sh; y++ )
1203 + for( x = 0; x < lm->sw; x++ )
1206 + cluster = SUPER_CLUSTER( x, y );
1207 + //% if( *cluster < 0 )
1210 + /* get particulars */
1211 + luxel = SUPER_LUXEL( lightmapNum, x, y );
1212 + floodlight = SUPER_FLOODLIGHT( x, y );
1214 + flood[0]=floodlightRGB[0]*floodlightIntensity;
1215 + flood[1]=floodlightRGB[1]*floodlightIntensity;
1216 + flood[2]=floodlightRGB[2]*floodlightIntensity;
1218 + /* scale light value */
1219 + VectorScale( flood, *floodlight, flood );
1220 + luxel[0]+=flood[0];
1221 + luxel[1]+=flood[1];
1222 + luxel[2]+=flood[2];
1224 + if (luxel[3]==0) luxel[3]=1;
1232 + for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
1235 + if( lm->superLuxels[ lightmapNum ] == NULL )
1238 + for( y = 0; y < lm->sh; y++ )
1240 + for( x = 0; x < lm->sw; x++ )
1243 + cluster = SUPER_CLUSTER( x, y );
1244 + //% if( *cluster < 0 )
1247 + /* get particulars */
1248 + luxel = SUPER_LUXEL( lightmapNum, x, y );
1249 + normal = SUPER_NORMAL ( x, y );
1251 + luxel[0]=(normal[0]*127)+127;
1252 + luxel[1]=(normal[1]*127)+127;
1253 + luxel[2]=(normal[2]*127)+127;
1259 + /* -----------------------------------------------------------------
1261 ----------------------------------------------------------------- */
1263 @@ -3587,7 +3768,320 @@
1264 CreateTraceLightsForBounds( mins, maxs, normal, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ], LIGHT_SURFACES, trace );
1267 +/////////////////////////////////////////////////////////////
1269 +#define FLOODLIGHT_CONE_ANGLE 88 /* degrees */
1270 +#define FLOODLIGHT_NUM_ANGLE_STEPS 16
1271 +#define FLOODLIGHT_NUM_ELEVATION_STEPS 4
1272 +#define FLOODLIGHT_NUM_VECTORS (FLOODLIGHT_NUM_ANGLE_STEPS * FLOODLIGHT_NUM_ELEVATION_STEPS)
1274 +static vec3_t floodVectors[ FLOODLIGHT_NUM_VECTORS ];
1275 +static int numFloodVectors = 0;
1277 +void SetupFloodLight( void )
1280 + float angle, elevation, angleStep, elevationStep;
1281 + const char *value;
1282 + double v1,v2,v3,v4,v5;
1285 + Sys_FPrintf( SYS_VRB, "--- SetupFloodLight ---\n" );
1287 + /* calculate angular steps */
1288 + angleStep = DEG2RAD( 360.0f / FLOODLIGHT_NUM_ANGLE_STEPS );
1289 + elevationStep = DEG2RAD( FLOODLIGHT_CONE_ANGLE / FLOODLIGHT_NUM_ELEVATION_STEPS );
1291 + /* iterate angle */
1293 + for( i = 0, angle = 0.0f; i < FLOODLIGHT_NUM_ANGLE_STEPS; i++, angle += angleStep )
1295 + /* iterate elevation */
1296 + for( j = 0, elevation = elevationStep * 0.5f; j < FLOODLIGHT_NUM_ELEVATION_STEPS; j++, elevation += elevationStep )
1298 + floodVectors[ numFloodVectors ][ 0 ] = sin( elevation ) * cos( angle );
1299 + floodVectors[ numFloodVectors ][ 1 ] = sin( elevation ) * sin( angle );
1300 + floodVectors[ numFloodVectors ][ 2 ] = cos( elevation );
1301 + numFloodVectors++;
1305 + /* emit some statistics */
1306 + Sys_FPrintf( SYS_VRB, "%9d numFloodVectors\n", numFloodVectors );
1309 + value = ValueForKey( &entities[ 0 ], "_floodlight" );
1311 + if( value[ 0 ] != '\0' )
1314 + v4=floodlightDistance;
1315 + v5=floodlightIntensity;
1317 + sscanf( value, "%lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5);
1319 + floodlightRGB[0]=v1;
1320 + floodlightRGB[1]=v2;
1321 + floodlightRGB[2]=v3;
1323 + if (VectorLength(floodlightRGB)==0)
1325 + VectorSet(floodlightRGB,240,240,255);
1328 + if (v4<1) v4=1024;
1331 + floodlightDistance=v4;
1332 + floodlightIntensity=v5;
1334 + floodlighty = qtrue;
1335 + Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
1339 + VectorSet(floodlightRGB,240,240,255);
1340 + //floodlighty = qtrue;
1341 + //Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
1343 + VectorNormalize(floodlightRGB,floodlightRGB);
1346 +//27 - lighttracer style ambient occlusion light hack.
1347 +//Kudos to the dirtmapping author for most of this source.
1348 +void FloodLightRawLightmap( int rawLightmapNum )
1350 + int i, x, y, sx, sy, *cluster;
1351 + float *origin, *normal, *floodlight, *floodlight2, average, samples;
1352 + rawLightmap_t *lm;
1353 + surfaceInfo_t *info;
1356 + /* bail if this number exceeds the number of raw lightmaps */
1357 + if( rawLightmapNum >= numRawLightmaps )
1360 + /* get lightmap */
1361 + lm = &rawLightmaps[ rawLightmapNum ];
1363 + memset(&trace,0,sizeof(trace_t));
1365 + trace.testOcclusion = qtrue;
1366 + trace.forceSunlight = qfalse;
1367 + trace.twoSided = qtrue;
1368 + trace.recvShadows = lm->recvShadows;
1369 + trace.numSurfaces = lm->numLightSurfaces;
1370 + trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
1371 + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
1372 + trace.testAll = qfalse;
1373 + trace.distance = 1024;
1375 + /* twosided lighting (may or may not be a good idea for lightmapped stuff) */
1376 + //trace.twoSided = qfalse;
1377 + for( i = 0; i < trace.numSurfaces; i++ )
1380 + info = &surfaceInfos[ trace.surfaces[ i ] ];
1382 + /* check twosidedness */
1383 + if( info->si->twoSided )
1385 + trace.twoSided = qtrue;
1391 + for( y = 0; y < lm->sh; y++ )
1393 + for( x = 0; x < lm->sw; x++ )
1396 + cluster = SUPER_CLUSTER( x, y );
1397 + origin = SUPER_ORIGIN( x, y );
1398 + normal = SUPER_NORMAL( x, y );
1399 + floodlight = SUPER_FLOODLIGHT( x, y );
1401 + /* set default dirt */
1402 + *floodlight = 0.0f;
1404 + /* only look at mapped luxels */
1405 + if( *cluster < 0 )
1408 + /* copy to trace */
1409 + trace.cluster = *cluster;
1410 + VectorCopy( origin, trace.origin );
1411 + VectorCopy( normal, trace.normal );
1416 + *floodlight = FloodLightForSample( &trace );
1420 + /* testing no filtering */
1423 + /* filter "dirt" */
1424 + for( y = 0; y < lm->sh; y++ )
1426 + for( x = 0; x < lm->sw; x++ )
1429 + cluster = SUPER_CLUSTER( x, y );
1430 + floodlight = SUPER_FLOODLIGHT( x, y );
1432 + /* filter dirt by adjacency to unmapped luxels */
1433 + average = *floodlight;
1435 + for( sy = (y - 1); sy <= (y + 1); sy++ )
1437 + if( sy < 0 || sy >= lm->sh )
1440 + for( sx = (x - 1); sx <= (x + 1); sx++ )
1442 + if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
1445 + /* get neighboring luxel */
1446 + cluster = SUPER_CLUSTER( sx, sy );
1447 + floodlight2 = SUPER_FLOODLIGHT( sx, sy );
1448 + if( *cluster < 0 || *floodlight2 <= 0.0f )
1452 + average += *floodlight2;
1457 + if( samples <= 0.0f )
1462 + if( samples <= 0.0f )
1466 + *floodlight = average / samples;
1472 +FloodLightForSample()
1473 +calculates floodlight value for a given sample
1474 +once again, kudos to the dirtmapping coder
1476 +float FloodLightForSample( trace_t *trace )
1480 + float contribution;
1482 + float gatherLight, outLight;
1483 + vec3_t normal, worldUp, myUp, myRt, direction, displacement;
1491 + if( trace == NULL || trace->cluster < 0 )
1496 + dd = floodlightDistance;
1497 + VectorCopy( trace->normal, normal );
1499 + /* check if the normal is aligned to the world-up */
1500 + if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f )
1502 + if( normal[ 2 ] == 1.0f )
1504 + VectorSet( myRt, 1.0f, 0.0f, 0.0f );
1505 + VectorSet( myUp, 0.0f, 1.0f, 0.0f );
1507 + else if( normal[ 2 ] == -1.0f )
1509 + VectorSet( myRt, -1.0f, 0.0f, 0.0f );
1510 + VectorSet( myUp, 0.0f, 1.0f, 0.0f );
1515 + VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
1516 + CrossProduct( normal, worldUp, myRt );
1517 + VectorNormalize( myRt, myRt );
1518 + CrossProduct( myRt, normal, myUp );
1519 + VectorNormalize( myUp, myUp );
1522 + /* iterate through ordered vectors */
1523 + for( i = 0; i < numFloodVectors; i++ )
1525 + if (floodlight_lowquality==qtrue)
1527 + if (rand()%10 != 0 ) continue;
1532 + /* transform vector into tangent space */
1533 + direction[ 0 ] = myRt[ 0 ] * floodVectors[ i ][ 0 ] + myUp[ 0 ] * floodVectors[ i ][ 1 ] + normal[ 0 ] * floodVectors[ i ][ 2 ];
1534 + direction[ 1 ] = myRt[ 1 ] * floodVectors[ i ][ 0 ] + myUp[ 1 ] * floodVectors[ i ][ 1 ] + normal[ 1 ] * floodVectors[ i ][ 2 ];
1535 + direction[ 2 ] = myRt[ 2 ] * floodVectors[ i ][ 0 ] + myUp[ 2 ] * floodVectors[ i ][ 1 ] + normal[ 2 ] * floodVectors[ i ][ 2 ];
1537 + /* set endpoint */
1538 + VectorMA( trace->origin, dd, direction, trace->end );
1540 + //VectorMA( trace->origin, 1, direction, trace->origin );
1542 + SetupTrace( trace );
1544 + TraceLine( trace );
1547 + if (trace->compileFlags & C_SKY )
1549 + contribution=1.0f;
1551 + else if ( trace->opaque )
1553 + VectorSubtract( trace->hit, trace->origin, displacement );
1554 + d=VectorLength( displacement );
1556 + // d=trace->distance;
1557 + //if (d>256) gatherDirt+=1;
1558 + contribution=d/dd;
1559 + if (contribution>1) contribution=1.0f;
1561 + //gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
1564 + gatherLight+=contribution;
1568 + if( gatherLight <= 0.0f )
1574 + gatherLight/=(sub);
1576 + outLight=gatherLight;
1577 + if( outLight > 1.0f )
1580 + /* return to sender */
1584 Index: tools/quake3/q3map2/light.c
1585 ===================================================================
1586 --- tools/quake3/q3map2/light.c (revision 191)
1587 +++ tools/quake3/q3map2/light.c (working copy)
1588 @@ -1378,6 +1378,56 @@
1592 + /////// Floodlighting for point //////////////////
1593 + //do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir
1599 + col[0]=col[1]=col[2]=floodlightIntensity;
1603 + trace.testOcclusion = qtrue;
1604 + trace.forceSunlight = qfalse;
1605 + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
1606 + trace.testAll = qtrue;
1610 + if (q==0) //upper hemisphere
1612 + trace.normal[0]=0;
1613 + trace.normal[1]=0;
1614 + trace.normal[2]=1;
1616 + else //lower hemisphere
1618 + trace.normal[0]=0;
1619 + trace.normal[1]=0;
1620 + trace.normal[2]=-1;
1623 + f = FloodLightForSample(&trace);
1625 + contributions[ numCon ].color[0]=col[0]*f;
1626 + contributions[ numCon ].color[1]=col[1]*f;
1627 + contributions[ numCon ].color[2]=col[2]*f;
1629 + contributions[ numCon ].dir[0]=dir[0];
1630 + contributions[ numCon ].dir[1]=dir[1];
1631 + contributions[ numCon ].dir[2]=dir[2];
1633 + contributions[ numCon ].style = 0;
1635 + /* push average direction around */
1636 + addSize = VectorLength( col );
1637 + VectorMA( gp->dir, addSize, dir, gp->dir );
1640 + /////////////////////
1642 /* normalize to get primary light direction */
1643 VectorNormalize( gp->dir, gp->dir );
1645 @@ -1661,6 +1711,12 @@
1646 RunThreadsOnIndividual( numRawLightmaps, qtrue, DirtyRawLightmap );
1649 + /* floodlight them up */
1652 + Sys_Printf( "--- FloodlightRawLightmap ---\n" );
1653 + RunThreadsOnIndividual( numRawLightmaps, qtrue, FloodLightRawLightmap );
1656 /* ydnar: set up light envelopes */
1657 SetupEnvelopes( qfalse, fast );
1658 @@ -1703,6 +1759,7 @@
1661 VectorClear( ambientColor );
1662 + floodlighty = false;
1664 /* generate diffuse lights */
1666 @@ -2191,6 +2256,21 @@
1668 Sys_Printf( "Enabling Challenge Pro Mode Asstacular Vertex Lighting Mode (tm)\n" );
1670 + else if( !strcmp( argv[ i ], "-floodlight" ) )
1672 + floodlighty = qtrue;
1673 + Sys_Printf( "FloodLighting enabled\n" );
1675 + else if( !strcmp( argv[ i ], "-debugnormals" ) )
1677 + debugnormals = qtrue;
1678 + Sys_Printf( "DebugNormals enabled\n" );
1680 + else if( !strcmp( argv[ i ], "-lowquality" ) )
1682 + floodlight_lowquality = qtrue;
1683 + Sys_Printf( "Low Quality FloodLighting enabled\n" );
1686 /* r7: dirtmapping */
1687 else if( !strcmp( argv[ i ], "-dirty" ) )
1688 @@ -2279,6 +2359,7 @@
1689 /* ydnar: set up optimization */
1692 + SetupFloodLight();
1693 SetupSurfaceLightmaps();
1695 /* initialize the surface facet tracing */
1696 Index: tools/quake3/q3map2/lightmaps_ydnar.c
1697 ===================================================================
1698 --- tools/quake3/q3map2/lightmaps_ydnar.c (revision 191)
1699 +++ tools/quake3/q3map2/lightmaps_ydnar.c (working copy)
1700 @@ -414,6 +414,12 @@
1701 lm->superNormals = safe_malloc( size );
1702 memset( lm->superNormals, 0, size );
1704 + /* allocate floodlight map storage */
1705 + size = lm->sw * lm->sh * SUPER_FLOODLIGHT_SIZE * sizeof( float );
1706 + if( lm->superFloodLight == NULL )
1707 + lm->superFloodLight = safe_malloc( size );
1708 + memset( lm->superFloodLight, 0, size );
1710 /* allocate cluster map storage */
1711 size = lm->sw * lm->sh * sizeof( int );
1712 if( lm->superClusters == NULL )
1713 Index: tools/quake3/q3map2/q3map2.h
1714 ===================================================================
1715 --- tools/quake3/q3map2/q3map2.h (revision 191)
1716 +++ tools/quake3/q3map2/q3map2.h (working copy)
1718 #define SUPER_NORMAL_SIZE 4
1719 #define SUPER_DELUXEL_SIZE 3
1720 #define BSP_DELUXEL_SIZE 3
1721 +#define SUPER_FLOODLIGHT_SIZE 1
1723 #define VERTEX_LUXEL( s, v ) (vertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
1724 #define RAD_VERTEX_LUXEL( s, v )(radVertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
1726 #define SUPER_ORIGIN( x, y ) (lm->superOrigins + ((((y) * lm->sw) + (x)) * SUPER_ORIGIN_SIZE))
1727 #define SUPER_NORMAL( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE))
1728 #define SUPER_DIRT( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE) + 3) /* stash dirtyness in normal[ 3 ] */
1729 +#define SUPER_FLOODLIGHT( x, y ) (lm->superFloodLight + ((((y) * lm->sw) + (x)) * SUPER_FLOODLIGHT_SIZE) )
1733 @@ -1392,6 +1395,7 @@
1735 float *superDeluxels; /* average light direction */
1737 + float *superFloodLight;
1741 @@ -1704,6 +1708,10 @@
1742 float DirtForSample( trace_t *trace );
1743 void DirtyRawLightmap( int num );
1745 +void SetupFloodLight();
1746 +float FloodLightForSample( trace_t *trace );
1747 +void FloodLightRawLightmap( int num );
1749 void IlluminateRawLightmap( int num );
1750 void IlluminateVertexes( int num );
1752 @@ -2098,6 +2106,13 @@
1753 Q_EXTERN float dirtScale Q_ASSIGN( 1.0f );
1754 Q_EXTERN float dirtGain Q_ASSIGN( 1.0f );
1756 +Q_EXTERN qboolean debugnormals Q_ASSIGN( qfalse );
1757 +Q_EXTERN qboolean floodlighty Q_ASSIGN( qfalse );
1758 +Q_EXTERN qboolean floodlight_lowquality Q_ASSIGN( qfalse );
1759 +Q_EXTERN vec3_t floodlightRGB;
1760 +Q_EXTERN float floodlightIntensity Q_ASSIGN( 512 );
1761 +Q_EXTERN float floodlightDistance Q_ASSIGN( 1024 );
1763 Q_EXTERN qboolean dump Q_ASSIGN( qfalse );
1764 Q_EXTERN qboolean debug Q_ASSIGN( qfalse );
1765 Q_EXTERN qboolean debugUnused Q_ASSIGN( qfalse );
1766 Index: tools/quake3/q3map2/game_ja.h
1767 ===================================================================
1768 --- tools/quake3/q3map2/game_ja.h (revision 191)
1769 +++ tools/quake3/q3map2/game_ja.h (working copy)
1771 qfalse, /* wolf lighting model? */
1772 128, /* lightmap width/height */
1773 1.0f, /* lightmap gamma */
1774 + 1.0f, /* lightmap exposure */
1775 1.0f, /* lightmap compensate */
1776 "RBSP", /* bsp file prefix */
1777 1, /* bsp file version */
1778 Index: tools/quake3/q3map2/game_tremulous.h
1779 ===================================================================
1780 --- tools/quake3/q3map2/game_tremulous.h (revision 191)
1781 +++ tools/quake3/q3map2/game_tremulous.h (working copy)
1783 qfalse, /* wolf lighting model? */
1784 128, /* lightmap width/height */
1785 1.0f, /* lightmap gamma */
1786 + 1.0f, /* lightmap exposure */
1787 1.0f, /* lightmap compensate */
1788 "IBSP", /* bsp file prefix */
1789 46, /* bsp file version */
1790 Index: tools/quake3/q3map2/game_wolfet.h
1791 ===================================================================
1792 --- tools/quake3/q3map2/game_wolfet.h (revision 191)
1793 +++ tools/quake3/q3map2/game_wolfet.h (working copy)
1795 qtrue, /* wolf lighting model? */
1796 128, /* lightmap width/height */
1797 1.0f, /* lightmap gamma */
1798 + 1.0f, /* lightmap exposure */
1799 1.0f, /* lightmap compensate */
1800 "IBSP", /* bsp file prefix */
1801 47, /* bsp file version */
1802 Index: tools/quake3/q3map2/game_wolf.h
1803 ===================================================================
1804 --- tools/quake3/q3map2/game_wolf.h (revision 191)
1805 +++ tools/quake3/q3map2/game_wolf.h (working copy)
1807 qtrue, /* wolf lighting model? */
1808 128, /* lightmap width/height */
1809 1.0f, /* lightmap gamma */
1810 + 1.0f, /* lightmap exposure */
1811 1.0f, /* lightmap compensate */
1812 "IBSP", /* bsp file prefix */
1813 47, /* bsp file version */
1814 Index: tools/quake3/q3map2/game_sof2.h
1815 ===================================================================
1816 --- tools/quake3/q3map2/game_sof2.h (revision 191)
1817 +++ tools/quake3/q3map2/game_sof2.h (working copy)
1819 qfalse, /* wolf lighting model? */
1820 128, /* lightmap width/height */
1821 1.0f, /* lightmap gamma */
1822 + 1.0f, /* lightmap exposure */
1823 1.0f, /* lightmap compensate */
1824 "RBSP", /* bsp file prefix */
1825 1, /* bsp file version */
1826 Index: tools/quake3/q3map2/game_etut.h
1827 ===================================================================
1828 --- tools/quake3/q3map2/game_etut.h (revision 191)
1829 +++ tools/quake3/q3map2/game_etut.h (working copy)
1831 qfalse, /* wolf lighting model? */
1832 128, /* lightmap width/height */
1833 2.2f, /* lightmap gamma */
1834 + 1.0f, /* lightmap exposure */
1835 1.0f, /* lightmap compensate */
1836 "IBSP", /* bsp file prefix */
1837 47, /* bsp file version */
1838 Index: tools/quake3/q3map2/game_jk2.h
1839 ===================================================================
1840 --- tools/quake3/q3map2/game_jk2.h (revision 191)
1841 +++ tools/quake3/q3map2/game_jk2.h (working copy)
1843 qfalse, /* wolf lighting model? */
1844 128, /* lightmap width/height */
1845 1.0f, /* lightmap gamma */
1846 + 1.0f, /* lightmap exposure */
1847 1.0f, /* lightmap compensate */
1848 "RBSP", /* bsp file prefix */
1849 1, /* bsp file version */
1850 Index: tools/quake3/q3map2/game_qfusion.h
1851 ===================================================================
1852 --- tools/quake3/q3map2/game_qfusion.h (revision 191)
1853 +++ tools/quake3/q3map2/game_qfusion.h (working copy)
1855 qfalse, /* wolf lighting model? */
1856 512, /* lightmap width/height */
1857 1.0f, /* lightmap gamma */
1858 + 1.0f, /* lightmap exposure */
1859 1.0f, /* lightmap compensate */
1860 "FBSP", /* bsp file prefix */
1861 1, /* bsp file version */
1862 Index: tools/quake3/q3map2/game_tenebrae.h
1863 ===================================================================
1864 --- tools/quake3/q3map2/game_tenebrae.h (revision 191)
1865 +++ tools/quake3/q3map2/game_tenebrae.h (working copy)
1867 qfalse, /* wolf lighting model? */
1868 512, /* lightmap width/height */
1869 2.0f, /* lightmap gamma */
1870 + 1.0f, /* lightmap exposure */
1871 1.0f, /* lightmap compensate */
1872 "IBSP", /* bsp file prefix */
1873 46, /* bsp file version */
1874 Index: tools/quake3/q3map2/game_quake3.h
1875 ===================================================================
1876 --- tools/quake3/q3map2/game_quake3.h (revision 191)
1877 +++ tools/quake3/q3map2/game_quake3.h (working copy)
1879 qfalse, /* wolf lighting model? */
1880 128, /* lightmap width/height */
1881 1.0f, /* lightmap gamma */
1882 + 1.0f, /* lightmap exposure */
1883 1.0f, /* lightmap compensate */
1884 "IBSP", /* bsp file prefix */
1885 46, /* bsp file version */
1886 Index: tools/quake3/q3map2/game_ef.h
1887 ===================================================================
1888 --- tools/quake3/q3map2/game_ef.h (revision 191)
1889 +++ tools/quake3/q3map2/game_ef.h (working copy)
1891 qfalse, /* wolf lighting model? */
1892 128, /* lightmap width/height */
1893 1.0f, /* lightmap gamma */
1894 + 1.0f, /* lightmap exposure */
1895 1.0f, /* lightmap compensate */
1896 "IBSP", /* bsp file prefix */
1897 46, /* bsp file version */
1898 Index: tools/quake3/q3map2/light_ydnar.c
1899 ===================================================================
1900 --- tools/quake3/q3map2/light_ydnar.c (revision 191)
1901 +++ tools/quake3/q3map2/light_ydnar.c (working copy)
1909 /* ydnar: scaling necessary for simulating r_overbrightBits on external lightmaps */
1912 sample[ i ] = pow( sample[ i ] / 255.0f, gamma ) * 255.0f;
1915 + if (lightmapExposure == 1)
1917 + /* clamp with color normalization */
1918 + max = sample[ 0 ];
1919 + if( sample[ 1 ] > max )
1920 + max = sample[ 1 ];
1921 + if( sample[ 2 ] > max )
1922 + max = sample[ 2 ];
1923 + if( max > 255.0f )
1924 + VectorScale( sample, (255.0f / max), sample );
1928 + if (lightmapExposure==0)
1930 + lightmapExposure=1.0f;
1932 + inv=1.f/lightmapExposure;
1935 + max = sample[ 0 ];
1936 + if( sample[ 1 ] > max )
1937 + max = sample[ 1 ];
1938 + if( sample[ 2 ] > max )
1939 + max = sample[ 2 ];
1941 + dif = (1- exp(-max * inv) ) * 255;
1959 - /* clamp with color normalization */
1960 - max = sample[ 0 ];
1961 - if( sample[ 1 ] > max )
1962 - max = sample[ 1 ];
1963 - if( sample[ 2 ] > max )
1964 - max = sample[ 2 ];
1965 - if( max > 255.0f )
1966 - VectorScale( sample, (255.0f / max), sample );
1968 /* compensate for ingame overbrighting/bitshifting */
1969 VectorScale( sample, (1.0f / lightmapCompensate), sample );
1971 Index: tools/quake3/q3map2/light.c
1972 ===================================================================
1973 --- tools/quake3/q3map2/light.c (revision 191)
1974 +++ tools/quake3/q3map2/light.c (working copy)
1975 @@ -1836,6 +1893,14 @@
1979 + else if( !strcmp( argv[ i ], "-exposure" ) )
1981 + f = atof( argv[ i + 1 ] );
1982 + lightmapExposure = f;
1983 + Sys_Printf( "Lighting exposure set to %f\n", lightmapExposure );
1987 else if( !strcmp( argv[ i ], "-compensate" ) )
1989 f = atof( argv[ i + 1 ] );
1990 Index: tools/quake3/q3map2/q3map2.h
1991 ===================================================================
1992 --- tools/quake3/q3map2/q3map2.h (revision 191)
1993 +++ tools/quake3/q3map2/q3map2.h (working copy)
1995 qboolean wolfLight; /* when true, lights work like wolf q3map */
1996 int lightmapSize; /* bsp lightmap width/height */
1997 float lightmapGamma; /* default lightmap gamma */
1998 + float lightmapExposure; /* default lightmap exposure */
1999 float lightmapCompensate; /* default lightmap compensate value */
2000 char *bspIdent; /* 4-letter bsp file prefix */
2001 int bspVersion; /* bsp version to use */
2002 @@ -2117,6 +2132,7 @@
2004 /* ydnar: lightmap gamma/compensation */
2005 Q_EXTERN float lightmapGamma Q_ASSIGN( 1.0f );
2006 +Q_EXTERN float lightmapExposure Q_ASSIGN( 1.0f );
2007 Q_EXTERN float lightmapCompensate Q_ASSIGN( 1.0f );
2009 /* ydnar: for runtime tweaking of falloff tolerance */
2010 Index: tools/quake3/q3map2/light_ydnar.c
2011 ===================================================================
2012 --- tools/quake3/q3map2/light_ydnar.c (revision 191)
2013 +++ tools/quake3/q3map2/light_ydnar.c (working copy)
2016 #define BOGUS_NUDGE -99999.0f
2018 -static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv, vec4_t plane, float pass, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
2019 +static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv, vec4_t plane, float pass, vec3_t stv[ 3 ], vec3_t ttv[ 3 ], vec3_t worldverts[ 3 ] )
2021 int i, x, y, numClusters, *clusters, pointCluster, *cluster;
2022 float *luxel, *origin, *normal, d, lightmapSampleOffset;
2023 @@ -392,6 +428,12 @@
2027 + vec3_t cverts[ 3 ];
2029 + vec4_t sideplane, hostplane;
2034 static float nudges[][ 2 ] =
2036 @@ -485,6 +527,51 @@
2037 /* non axial lightmap projection (explicit xyz) */
2039 VectorCopy( dv->xyz, origin );
2041 + //////////////////////
2042 + //27's test to make sure samples stay within the triangle boundaries
2043 + //1) Test the sample origin to see if it lays on the wrong side of any edge (x/y)
2044 + //2) if it does, nudge it onto the correct side.
2046 + if (worldverts!=NULL)
2050 + VectorCopy(worldverts[j],cverts[j]);
2052 + PlaneFromPoints(hostplane,cverts[0],cverts[1],cverts[2]);
2058 + //build plane using 2 edges and a normal
2061 + VectorCopy(cverts[next],temp);
2062 + VectorAdd(temp,hostplane,temp);
2063 + PlaneFromPoints(sideplane,cverts[i],cverts[ next ], temp);
2065 + //planetest sample point
2066 + e=DotProduct(origin,sideplane);
2071 + //VectorClear(origin);
2072 + //Move the sample point back inside triangle bounds
2073 + origin[0]-=sideplane[0]*(e+1);
2074 + origin[1]-=sideplane[1]*(e+1);
2075 + origin[2]-=sideplane[2]*(e+1);
2077 + VectorClear(origin);
2084 + ////////////////////////
2086 /* planar surfaces have precalculated lightmap vectors for nudging */
2087 if( lm->plane != NULL )
2088 @@ -516,8 +603,13 @@
2090 origin[ lm->axisNum ] += lightmapSampleOffset;
2092 + VectorCopy(origin,origintwo);
2093 + origintwo[0]+=vecs[2][0];
2094 + origintwo[1]+=vecs[2][1];
2095 + origintwo[2]+=vecs[2][2];
2098 - pointCluster = ClusterForPointExtFilter( origin, LUXEL_EPSILON, numClusters, clusters );
2099 + pointCluster = ClusterForPointExtFilter( origintwo, LUXEL_EPSILON, numClusters, clusters );
2101 /* another retarded hack, storing nudge count in luxel[ 1 ] */
2103 @@ -533,14 +625,14 @@
2104 for( i = 0; i < 3; i++ )
2106 /* set nudged point*/
2107 - nudged[ i ] = origin[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
2108 + nudged[ i ] = origintwo[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
2112 /* get pvs cluster */
2113 pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters ); //% + 0.625 );
2114 - if( pointCluster >= 0 )
2115 - VectorCopy( nudged, origin );
2116 + //if( pointCluster >= 0 )
2117 + // VectorCopy( nudged, origin );
2123 VectorMA( dv->xyz, lightmapSampleOffset, dv->normal, nudged );
2124 pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters );
2125 - if( pointCluster >= 0 )
2126 - VectorCopy( nudged, origin );
2127 + //if( pointCluster >= 0 )
2128 + // VectorCopy( nudged, origin );
2133 than the distance between two luxels (thanks jc :)
2136 -static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], vec4_t plane, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
2137 +static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], vec4_t plane, vec3_t stv[ 3 ], vec3_t ttv[ 3 ], vec3_t worldverts[ 3 ] )
2139 bspDrawVert_t mid, *dv2[ 3 ];
2143 /* split the longest edge and map it */
2144 LerpDrawVert( dv[ max ], dv[ (max + 1) % 3 ], &mid );
2145 - MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv );
2146 + MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv, worldverts );
2148 /* push the point up a little bit to account for fp creep (fixme: revisit this) */
2149 //% VectorMA( mid.xyz, 2.0f, mid.normal, mid.xyz );
2150 @@ -653,12 +745,12 @@
2151 /* recurse to first triangle */
2152 VectorCopy( dv, dv2 );
2154 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
2155 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
2157 /* recurse to second triangle */
2158 VectorCopy( dv, dv2 );
2159 dv2[ (max + 1) % 3 ] = ∣
2160 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
2161 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
2168 vec3_t *stv, *ttv, stvStatic[ 3 ], ttvStatic[ 3 ];
2169 + vec3_t worldverts[ 3 ];
2172 /* get plane if possible */
2173 @@ -699,16 +792,20 @@
2177 + VectorCopy( dv[ 0 ]->xyz, worldverts[ 0 ] );
2178 + VectorCopy( dv[ 1 ]->xyz, worldverts[ 1 ] );
2179 + VectorCopy( dv[ 2 ]->xyz, worldverts[ 2 ] );
2181 /* map the vertexes */
2182 - MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
2183 - MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
2184 - MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
2185 + MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, worldverts );
2186 + MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, worldverts );
2187 + MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, worldverts );
2189 /* 2002-11-20: prefer axial triangle edges */
2192 /* subdivide the triangle */
2193 - MapTriangle_r( lm, info, dv, plane, stv, ttv );
2194 + MapTriangle_r( lm, info, dv, plane, stv, ttv, worldverts );
2199 dv2[ 2 ] = dv[ (i + 1) % 3 ];
2201 /* map the degenerate triangle */
2202 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
2203 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
2208 LerpDrawVert( dv[ max + 2 ], dv[ (max + 3) % 4 ], &mid[ 1 ] );
2210 /* map the vertexes */
2211 - MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv );
2212 - MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv );
2213 + MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv, NULL );
2214 + MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv, NULL );
2218 @@ -878,10 +975,10 @@
2221 /* map the vertexes */
2222 - MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
2223 - MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
2224 - MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
2225 - MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv );
2226 + MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, NULL );
2227 + MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, NULL );
2228 + MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, NULL );
2229 + MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv, NULL );
2231 /* subdivide the quad */
2232 MapQuad_r( lm, info, dv, plane, stv, ttv );
2233 @@ -1173,7 +1270,7 @@
2236 /* map the fake vert */
2237 - MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL );
2238 + MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL, NULL );
2242 @@ -1963,22 +2062,32 @@
2243 deluxel = SUPER_DELUXEL( x, y );
2244 origin = SUPER_ORIGIN( x, y );
2245 normal = SUPER_NORMAL( x, y );
2247 - /* set contribution count */
2248 - lightLuxel[ 3 ] = 1.0f;
2251 - trace.cluster = *cluster;
2252 - VectorCopy( origin, trace.origin );
2253 - VectorCopy( normal, trace.normal );
2255 - /* get light for this sample */
2256 - LightContributionToSample( &trace );
2257 - VectorCopy( trace.color, lightLuxel );
2259 - /* add to count */
2260 - if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
2262 + ////////// 27's temp hack for testing edge clipping ////
2263 + if( origin[0]==0 && origin[1]==0 && origin[2]==0 )
2265 + lightLuxel[ 1 ] = 255;
2266 + lightLuxel[ 3 ] = 1.0f;
2271 + /* set contribution count */
2272 + lightLuxel[ 3 ] = 1.0f;
2275 + trace.cluster = *cluster;
2276 + VectorCopy( origin, trace.origin );
2277 + VectorCopy( normal, trace.normal );
2279 + /* get light for this sample */
2280 + LightContributionToSample( &trace );
2281 + VectorCopy( trace.color, lightLuxel );
2283 + /* add to count */
2284 + if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
2288 /* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
2290 Index: tools/quake3/q3map2/q3map2.h
2291 ===================================================================
2292 --- tools/quake3/q3map2/q3map2.h (revision 303)
2293 +++ tools/quake3/q3map2/q3map2.h (working copy)
2298 -#define Q3MAP_VERSION "2.5.17"
2299 -#define Q3MAP_MOTD "Last one turns the lights off"
2300 +#define Q3MAP_VERSION "2.5.17-div0-obj-decomptexcoords-snapplane-UTavgcolorfix-UTfloodlight-UTlmexposure-UTtrianglecheck"
2301 +#define Q3MAP_MOTD "Light some candles, put them on a wooden table, take a photo, and paste it on the lightmaps!"
2305 Index: include/version.default
2306 ===================================================================
2307 --- include/version.default (revision 290)
2308 +++ include/version.default (working copy)
2311 +1.4.0-div0-obj-targetname
\r