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.orig 2008-09-06 15:32:05.000000000 +0200
14 +++ libs/picomodel/pm_obj.c 2008-09-06 15:32:09.000000000 +0200
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.orig 2008-09-06 15:32:05.000000000 +0200
117 +++ radiant/map.cpp 2008-09-06 15:32:10.000000000 +0200
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;
231 - // check the current map entities for an actual collision
232 - for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
234 - if(!strcmp(target, ValueForKey(e_target, "target")))
237 - // make sure the collision is not between two imported entities
238 - for(j=0; j<(int)new_ents->len; j++)
240 - if(e_target == g_ptr_array_index(new_ents, j))
241 - bCollision = FALSE;
246 - // find the matching targeted entity(s)
249 - for(j=num_ents-1; j>0; j--)
251 - e_target = (entity_t*)ents->GetAt(j);
252 - if(e_target != NULL && e_target != e)
254 - const char *targetname = ValueForKey(e_target, "targetname");
255 - if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
256 - g_ptr_array_add(t_ents, (gpointer)e_target);
259 - if(t_ents->len > 0)
261 - // link the first to get a unique target/targetname
262 - Entity_Connect(e, (entity_t*)g_ptr_array_index(t_ents,0));
263 - // set the targetname of the rest of them manually
264 - for(j = 1; j < (int)t_ents->len; j++)
265 - SetKeyValue( (entity_t*)g_ptr_array_index(t_ents, j), "targetname", ValueForKey(e, "target") );
267 - g_ptr_array_free(t_ents, FALSE);
270 + // keep a list of ents added to avoid testing collisions against them
271 + g_ptr_array_add(new_ents, (gpointer)e);
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.orig 2008-09-06 15:32:05.000000000 +0200
299 +++ radiant/drag.cpp 2008-09-06 15:32:10.000000000 +0200
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.orig 2008-09-06 15:32:05.000000000 +0200
358 +++ radiant/xywindow.cpp 2008-09-06 15:32:10.000000000 +0200
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.orig 2008-09-06 15:32:05.000000000 +0200
444 +++ radiant/targetname.cpp 2008-09-06 15:32:10.000000000 +0200
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.orig 2008-09-06 15:32:05.000000000 +0200
539 +++ radiant/qe3.cpp 2008-09-06 15:32:10.000000000 +0200
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.orig 2008-09-06 15:32:05.000000000 +0200
576 +++ radiant/qe3.h 2008-09-06 15:32:10.000000000 +0200
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.orig 2008-09-06 15:32:05.000000000 +0200
598 +++ tools/quake3/q3map2/convert_map.c 2008-09-06 15:32:11.000000000 +0200
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.orig 2008-09-06 15:32:05.000000000 +0200
839 +++ tools/quake3/q3map2/main.c 2008-09-06 15:32:11.000000000 +0200
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/game_quake3.h
860 ===================================================================
861 --- tools/quake3/q3map2/game_quake3.h.orig 2008-09-11 10:59:01.000000000 +0200
862 +++ tools/quake3/q3map2/game_quake3.h 2008-09-11 10:59:07.000000000 +0200
864 1.0f, /* lightmap gamma */
865 1.0f, /* lightmap compensate */
866 "IBSP", /* bsp file prefix */
867 - 47, /* bsp file version */
868 + 46, /* bsp file version */
869 qfalse, /* cod-style lump len/ofs order */
870 LoadIBSPFile, /* bsp load function */
871 WriteIBSPFile, /* bsp write function */
872 Index: tools/quake3/q3map2/model.c
873 ===================================================================
874 --- tools/quake3/q3map2/model.c.orig 2008-09-06 15:32:05.000000000 +0200
875 +++ tools/quake3/q3map2/model.c 2008-09-06 15:32:12.000000000 +0200
878 picoIndex_t *indexes;
880 + double normalEpsilon_save;
881 + double distanceEpsilon_save;
886 /* ydnar: giant hack land: generate clipping brushes for model triangles */
887 if( si->clipModel || (spawnFlags & 2) ) /* 2nd bit */
889 - vec3_t points[ 3 ], backs[ 3 ];
890 + vec3_t points[ 4 ], backs[ 3 ];
891 vec4_t plane, reverse, pa, pb, pc;
896 @@ -437,90 +438,141 @@
897 /* note: this doesn't work as well as simply using the plane of the triangle, below */
898 for( k = 0; k < 3; k++ )
900 - if( fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 1) % 3 ] ) &&
901 - fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 2) % 3 ] ) )
902 + if( fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 1) % 3 ] ) &&
903 + fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 2) % 3 ] ) )
905 backs[ j ][ k ] += dv->normal[ k ] < 0.0f ? 64.0f : -64.0f;
911 + VectorCopy( points[0], points[3] ); // for cyclic usage
913 /* make plane for triangle */
914 + // div0: add some extra spawnflags:
915 + // 0: snap normals to axial planes for extrusion
916 + // 8: extrude with the original normals
917 + // 16: extrude only with up/down normals (ideal for terrain)
918 + // 24: extrude by distance zero (may need engine changes)
919 if( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) )
922 + float backPlaneDistance = 2;
924 + if(spawnFlags & 8) // use a DOWN normal
926 + if(spawnFlags & 16)
928 + // 24: normal as is, and zero width (broken)
929 + VectorCopy(plane, bestNormal);
934 + VectorCopy(plane, bestNormal);
939 + if(spawnFlags & 16)
941 + // 16: UP/DOWN normal
942 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
947 + if(fabs(plane[0]) > fabs(plane[1])) // x>y
948 + if(fabs(plane[1]) > fabs(plane[2])) // x>y, y>z
949 + VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
951 + if(fabs(plane[0]) > fabs(plane[2])) // x>z, z>=y
952 + VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
954 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
956 + if(fabs(plane[1]) > fabs(plane[2])) // y>z, y>=x
957 + VectorSet(bestNormal, 0, (plane[1] >= 0 ? 1 : -1), 0);
959 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
963 + /* build a brush */
964 + buildBrush = AllocBrush( 48 );
965 + buildBrush->entityNum = mapEntityNum;
966 + buildBrush->original = buildBrush;
967 + buildBrush->contentShader = si;
968 + buildBrush->compileFlags = si->compileFlags;
969 + buildBrush->contentFlags = si->contentFlags;
970 + normalEpsilon_save = normalEpsilon;
971 + distanceEpsilon_save = distanceEpsilon;
972 + if(si->compileFlags & C_STRUCTURAL) // allow forced structural brushes here
974 + buildBrush->detail = qfalse;
976 + // only allow EXACT matches when snapping for these (this is mostly for caulk brushes inside a model)
977 + if(normalEpsilon > 0)
979 + if(distanceEpsilon > 0)
980 + distanceEpsilon = 0;
983 + buildBrush->detail = qtrue;
985 /* regenerate back points */
986 for( j = 0; j < 3; j++ )
989 dv = &ds->verts[ ds->indexes[ i + j ] ];
992 - VectorCopy( dv->xyz, backs[ j ] );
994 - /* find nearest axial to plane normal and push back points opposite */
995 - for( k = 0; k < 3; k++ )
997 - if( fabs( plane[ k ] ) > fabs( plane[ (k + 1) % 3 ] ) &&
998 - fabs( plane[ k ] ) > fabs( plane[ (k + 2) % 3 ] ) )
1000 - backs[ j ][ k ] += plane[ k ] < 0.0f ? 64.0f : -64.0f;
1005 + // shift by some units
1006 + VectorMA(dv->xyz, -64.0f, bestNormal, backs[j]); // 64 prevents roundoff errors a bit
1010 /* make back plane */
1011 VectorScale( plane, -1.0f, reverse );
1012 - reverse[ 3 ] = -(plane[ 3 ] - 1);
1014 - /* make back pyramid point */
1015 - VectorCopy( points[ 0 ], nadir );
1016 - VectorAdd( nadir, points[ 1 ], nadir );
1017 - VectorAdd( nadir, points[ 2 ], nadir );
1018 - VectorScale( nadir, 0.3333333333333f, nadir );
1019 - VectorMA( nadir, -2.0f, plane, nadir );
1021 - /* make 3 more planes */
1022 - //% if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], nadir ) &&
1023 - //% PlaneFromPoints( pb, points[ 1 ], points[ 0 ], nadir ) &&
1024 - //% PlaneFromPoints( pc, points[ 0 ], points[ 2 ], nadir ) )
1025 + reverse[ 3 ] = -plane[ 3 ];
1026 + if((spawnFlags & 24) != 24)
1027 + reverse[3] += DotProduct(bestNormal, plane) * backPlaneDistance;
1028 + // 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)
1030 if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], backs[ 1 ] ) &&
1031 - PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
1032 - PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
1033 + PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
1034 + PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
1036 - /* build a brush */
1037 - buildBrush = AllocBrush( 48 );
1039 - buildBrush->entityNum = mapEntityNum;
1040 - buildBrush->original = buildBrush;
1041 - buildBrush->contentShader = si;
1042 - buildBrush->compileFlags = si->compileFlags;
1043 - buildBrush->contentFlags = si->contentFlags;
1044 - buildBrush->detail = qtrue;
1046 /* set up brush sides */
1047 buildBrush->numsides = 5;
1048 for( j = 0; j < buildBrush->numsides; j++ )
1049 buildBrush->sides[ j ].shaderInfo = si;
1051 buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
1052 - buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 1, &points[ 2 ] );
1053 - buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 1, &points[ 1 ] );
1054 - buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 1, &points[ 0 ] );
1055 - buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, points );
1057 - /* add to entity */
1058 - if( CreateBrushWindings( buildBrush ) )
1061 - //% EmitBrushes( buildBrush, NULL, NULL );
1062 - buildBrush->next = entities[ mapEntityNum ].brushes;
1063 - entities[ mapEntityNum ].brushes = buildBrush;
1064 - entities[ mapEntityNum ].numBrushes++;
1067 - free( buildBrush );
1068 + buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 2, &points[ 1 ] ); // pa contains points[1] and points[2]
1069 + buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 2, &points[ 0 ] ); // pb contains points[0] and points[1]
1070 + buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 2, &points[ 2 ] ); // pc contains points[2] and points[0] (copied to points[3]
1071 + buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, backs );
1079 + normalEpsilon = normalEpsilon_save;
1080 + distanceEpsilon = distanceEpsilon_save;
1082 + /* add to entity */
1083 + if( CreateBrushWindings( buildBrush ) )
1086 + //% EmitBrushes( buildBrush, NULL, NULL );
1087 + buildBrush->next = entities[ mapEntityNum ].brushes;
1088 + entities[ mapEntityNum ].brushes = buildBrush;
1089 + entities[ mapEntityNum ].numBrushes++;
1092 + free( buildBrush );
1096 Index: tools/quake3/q3map2/map.c
1097 ===================================================================
1098 --- tools/quake3/q3map2/map.c.orig 2008-09-06 15:32:04.000000000 +0200
1099 +++ tools/quake3/q3map2/map.c 2008-09-06 15:32:12.000000000 +0200
1101 snaps a plane to normal/distance epsilons
1104 -void SnapPlane( vec3_t normal, vec_t *dist )
1105 +void SnapPlane( vec3_t normal, vec_t *dist, vec3_t center )
1107 // SnapPlane disabled by LordHavoc because it often messes up collision
1108 // brushes made from triangles of embedded models, and it has little effect
1109 @@ -193,7 +193,13 @@
1110 SnapPlane reenabled by namespace because of multiple reports of
1111 q3map2-crashes which were triggered by this patch.
1113 + // div0: ensure the point "center" stays on the plane (actually, this
1114 + // rotates the plane around the point center).
1115 + // if center lies on the plane, it is guaranteed to stay on the plane by
1117 + vec_t centerDist = DotProduct(normal, center);
1118 SnapNormal( normal );
1119 + *dist += (DotProduct(normal, center) - centerDist);
1121 if( fabs( *dist - Q_rint( *dist ) ) < distanceEpsilon )
1122 *dist = Q_rint( *dist );
1124 must be within an epsilon distance of the plane
1127 -int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points )
1128 +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?
1132 @@ -215,10 +221,14 @@
1137 + vec3_t centerofweight;
1139 + VectorClear(centerofweight);
1140 + for(i = 0; i < numPoints; ++i)
1141 + VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
1143 /* hash the plane */
1144 - SnapPlane( normal, &dist );
1145 + SnapPlane( normal, &dist, centerofweight );
1146 hash = (PLANE_HASHES - 1) & (int) fabs( dist );
1148 /* search the border bins as well */
1149 @@ -259,7 +269,13 @@
1153 - SnapPlane( normal, &dist );
1154 + vec3_t centerofweight;
1156 + VectorClear(centerofweight);
1157 + for(i = 0; i < numPoints; ++i)
1158 + VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
1160 + SnapPlane( normal, &dist, centerofweight );
1161 for( i = 0, p = mapplanes; i < nummapplanes; i++, p++ )
1163 if( PlaneEqual( p, normal, dist ) )
1164 Index: tools/quake3/q3map2/shaders.c
1165 ===================================================================
1166 --- tools/quake3/q3map2/shaders.c.orig 2008-09-06 15:32:04.000000000 +0200
1167 +++ tools/quake3/q3map2/shaders.c 2008-09-06 15:32:13.000000000 +0200
1168 @@ -794,8 +794,14 @@
1171 if( VectorLength( si->color ) <= 0.0f )
1173 ColorNormalize( color, si->color );
1174 - VectorScale( color, (1.0f / count), si->averageColor );
1175 + VectorScale( color, (1.0f / count), si->averageColor );
1179 + VectorCopy( si->color, si->averageColor );
1184 Index: tools/quake3/q3map2/light_ydnar.c
1185 ===================================================================
1186 --- tools/quake3/q3map2/light_ydnar.c.orig 2008-09-06 15:32:04.000000000 +0200
1187 +++ tools/quake3/q3map2/light_ydnar.c 2008-09-06 15:32:14.000000000 +0200
1188 @@ -1767,6 +1767,8 @@
1189 float tests[ 4 ][ 2 ] = { { 0.0f, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
1191 float stackLightLuxels[ STACK_LL_SIZE ];
1193 + float *floodlight;
1196 /* bail if this number exceeds the number of raw lightmaps */
1197 @@ -2223,6 +2225,78 @@
1198 FreeTraceLights( &trace );
1200 /* -----------------------------------------------------------------
1202 + ----------------------------------------------------------------- */
1206 + /* walk lightmaps */
1207 + for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
1210 + if( lm->superLuxels[ lightmapNum ] == NULL )
1213 + /* apply floodlight to each luxel */
1214 + for( y = 0; y < lm->sh; y++ )
1216 + for( x = 0; x < lm->sw; x++ )
1219 + cluster = SUPER_CLUSTER( x, y );
1220 + //% if( *cluster < 0 )
1223 + /* get particulars */
1224 + luxel = SUPER_LUXEL( lightmapNum, x, y );
1225 + floodlight = SUPER_FLOODLIGHT( x, y );
1227 + flood[0]=floodlightRGB[0]*floodlightIntensity;
1228 + flood[1]=floodlightRGB[1]*floodlightIntensity;
1229 + flood[2]=floodlightRGB[2]*floodlightIntensity;
1231 + /* scale light value */
1232 + VectorScale( flood, *floodlight, flood );
1233 + luxel[0]+=flood[0];
1234 + luxel[1]+=flood[1];
1235 + luxel[2]+=flood[2];
1237 + if (luxel[3]==0) luxel[3]=1;
1245 + for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
1248 + if( lm->superLuxels[ lightmapNum ] == NULL )
1251 + for( y = 0; y < lm->sh; y++ )
1253 + for( x = 0; x < lm->sw; x++ )
1256 + cluster = SUPER_CLUSTER( x, y );
1257 + //% if( *cluster < 0 )
1260 + /* get particulars */
1261 + luxel = SUPER_LUXEL( lightmapNum, x, y );
1262 + normal = SUPER_NORMAL ( x, y );
1264 + luxel[0]=(normal[0]*127)+127;
1265 + luxel[1]=(normal[1]*127)+127;
1266 + luxel[2]=(normal[2]*127)+127;
1272 + /* -----------------------------------------------------------------
1274 ----------------------------------------------------------------- */
1276 @@ -3587,7 +3661,320 @@
1277 CreateTraceLightsForBounds( mins, maxs, normal, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ], LIGHT_SURFACES, trace );
1280 +/////////////////////////////////////////////////////////////
1282 +#define FLOODLIGHT_CONE_ANGLE 88 /* degrees */
1283 +#define FLOODLIGHT_NUM_ANGLE_STEPS 16
1284 +#define FLOODLIGHT_NUM_ELEVATION_STEPS 4
1285 +#define FLOODLIGHT_NUM_VECTORS (FLOODLIGHT_NUM_ANGLE_STEPS * FLOODLIGHT_NUM_ELEVATION_STEPS)
1287 +static vec3_t floodVectors[ FLOODLIGHT_NUM_VECTORS ];
1288 +static int numFloodVectors = 0;
1290 +void SetupFloodLight( void )
1293 + float angle, elevation, angleStep, elevationStep;
1294 + const char *value;
1295 + double v1,v2,v3,v4,v5;
1298 + Sys_FPrintf( SYS_VRB, "--- SetupFloodLight ---\n" );
1300 + /* calculate angular steps */
1301 + angleStep = DEG2RAD( 360.0f / FLOODLIGHT_NUM_ANGLE_STEPS );
1302 + elevationStep = DEG2RAD( FLOODLIGHT_CONE_ANGLE / FLOODLIGHT_NUM_ELEVATION_STEPS );
1304 + /* iterate angle */
1306 + for( i = 0, angle = 0.0f; i < FLOODLIGHT_NUM_ANGLE_STEPS; i++, angle += angleStep )
1308 + /* iterate elevation */
1309 + for( j = 0, elevation = elevationStep * 0.5f; j < FLOODLIGHT_NUM_ELEVATION_STEPS; j++, elevation += elevationStep )
1311 + floodVectors[ numFloodVectors ][ 0 ] = sin( elevation ) * cos( angle );
1312 + floodVectors[ numFloodVectors ][ 1 ] = sin( elevation ) * sin( angle );
1313 + floodVectors[ numFloodVectors ][ 2 ] = cos( elevation );
1314 + numFloodVectors++;
1318 + /* emit some statistics */
1319 + Sys_FPrintf( SYS_VRB, "%9d numFloodVectors\n", numFloodVectors );
1322 + value = ValueForKey( &entities[ 0 ], "_floodlight" );
1324 + if( value[ 0 ] != '\0' )
1327 + v4=floodlightDistance;
1328 + v5=floodlightIntensity;
1330 + sscanf( value, "%lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5);
1332 + floodlightRGB[0]=v1;
1333 + floodlightRGB[1]=v2;
1334 + floodlightRGB[2]=v3;
1336 + if (VectorLength(floodlightRGB)==0)
1338 + VectorSet(floodlightRGB,240,240,255);
1341 + if (v4<1) v4=1024;
1344 + floodlightDistance=v4;
1345 + floodlightIntensity=v5;
1347 + floodlighty = qtrue;
1348 + Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
1352 + VectorSet(floodlightRGB,240,240,255);
1353 + //floodlighty = qtrue;
1354 + //Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
1356 + VectorNormalize(floodlightRGB,floodlightRGB);
1359 +//27 - lighttracer style ambient occlusion light hack.
1360 +//Kudos to the dirtmapping author for most of this source.
1361 +void FloodLightRawLightmap( int rawLightmapNum )
1363 + int i, x, y, sx, sy, *cluster;
1364 + float *origin, *normal, *floodlight, *floodlight2, average, samples;
1365 + rawLightmap_t *lm;
1366 + surfaceInfo_t *info;
1369 + /* bail if this number exceeds the number of raw lightmaps */
1370 + if( rawLightmapNum >= numRawLightmaps )
1373 + /* get lightmap */
1374 + lm = &rawLightmaps[ rawLightmapNum ];
1376 + memset(&trace,0,sizeof(trace_t));
1378 + trace.testOcclusion = qtrue;
1379 + trace.forceSunlight = qfalse;
1380 + trace.twoSided = qtrue;
1381 + trace.recvShadows = lm->recvShadows;
1382 + trace.numSurfaces = lm->numLightSurfaces;
1383 + trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
1384 + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
1385 + trace.testAll = qfalse;
1386 + trace.distance = 1024;
1388 + /* twosided lighting (may or may not be a good idea for lightmapped stuff) */
1389 + //trace.twoSided = qfalse;
1390 + for( i = 0; i < trace.numSurfaces; i++ )
1393 + info = &surfaceInfos[ trace.surfaces[ i ] ];
1395 + /* check twosidedness */
1396 + if( info->si->twoSided )
1398 + trace.twoSided = qtrue;
1404 + for( y = 0; y < lm->sh; y++ )
1406 + for( x = 0; x < lm->sw; x++ )
1409 + cluster = SUPER_CLUSTER( x, y );
1410 + origin = SUPER_ORIGIN( x, y );
1411 + normal = SUPER_NORMAL( x, y );
1412 + floodlight = SUPER_FLOODLIGHT( x, y );
1414 + /* set default dirt */
1415 + *floodlight = 0.0f;
1417 + /* only look at mapped luxels */
1418 + if( *cluster < 0 )
1421 + /* copy to trace */
1422 + trace.cluster = *cluster;
1423 + VectorCopy( origin, trace.origin );
1424 + VectorCopy( normal, trace.normal );
1429 + *floodlight = FloodLightForSample( &trace );
1433 + /* testing no filtering */
1436 + /* filter "dirt" */
1437 + for( y = 0; y < lm->sh; y++ )
1439 + for( x = 0; x < lm->sw; x++ )
1442 + cluster = SUPER_CLUSTER( x, y );
1443 + floodlight = SUPER_FLOODLIGHT( x, y );
1445 + /* filter dirt by adjacency to unmapped luxels */
1446 + average = *floodlight;
1448 + for( sy = (y - 1); sy <= (y + 1); sy++ )
1450 + if( sy < 0 || sy >= lm->sh )
1453 + for( sx = (x - 1); sx <= (x + 1); sx++ )
1455 + if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
1458 + /* get neighboring luxel */
1459 + cluster = SUPER_CLUSTER( sx, sy );
1460 + floodlight2 = SUPER_FLOODLIGHT( sx, sy );
1461 + if( *cluster < 0 || *floodlight2 <= 0.0f )
1465 + average += *floodlight2;
1470 + if( samples <= 0.0f )
1475 + if( samples <= 0.0f )
1479 + *floodlight = average / samples;
1485 +FloodLightForSample()
1486 +calculates floodlight value for a given sample
1487 +once again, kudos to the dirtmapping coder
1489 +float FloodLightForSample( trace_t *trace )
1493 + float contribution;
1495 + float gatherLight, outLight;
1496 + vec3_t normal, worldUp, myUp, myRt, direction, displacement;
1504 + if( trace == NULL || trace->cluster < 0 )
1509 + dd = floodlightDistance;
1510 + VectorCopy( trace->normal, normal );
1512 + /* check if the normal is aligned to the world-up */
1513 + if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f )
1515 + if( normal[ 2 ] == 1.0f )
1517 + VectorSet( myRt, 1.0f, 0.0f, 0.0f );
1518 + VectorSet( myUp, 0.0f, 1.0f, 0.0f );
1520 + else if( normal[ 2 ] == -1.0f )
1522 + VectorSet( myRt, -1.0f, 0.0f, 0.0f );
1523 + VectorSet( myUp, 0.0f, 1.0f, 0.0f );
1528 + VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
1529 + CrossProduct( normal, worldUp, myRt );
1530 + VectorNormalize( myRt, myRt );
1531 + CrossProduct( myRt, normal, myUp );
1532 + VectorNormalize( myUp, myUp );
1535 + /* iterate through ordered vectors */
1536 + for( i = 0; i < numFloodVectors; i++ )
1538 + if (floodlight_lowquality==qtrue)
1540 + if (rand()%10 != 0 ) continue;
1545 + /* transform vector into tangent space */
1546 + direction[ 0 ] = myRt[ 0 ] * floodVectors[ i ][ 0 ] + myUp[ 0 ] * floodVectors[ i ][ 1 ] + normal[ 0 ] * floodVectors[ i ][ 2 ];
1547 + direction[ 1 ] = myRt[ 1 ] * floodVectors[ i ][ 0 ] + myUp[ 1 ] * floodVectors[ i ][ 1 ] + normal[ 1 ] * floodVectors[ i ][ 2 ];
1548 + direction[ 2 ] = myRt[ 2 ] * floodVectors[ i ][ 0 ] + myUp[ 2 ] * floodVectors[ i ][ 1 ] + normal[ 2 ] * floodVectors[ i ][ 2 ];
1550 + /* set endpoint */
1551 + VectorMA( trace->origin, dd, direction, trace->end );
1553 + //VectorMA( trace->origin, 1, direction, trace->origin );
1555 + SetupTrace( trace );
1557 + TraceLine( trace );
1560 + if (trace->compileFlags & C_SKY )
1562 + contribution=1.0f;
1564 + else if ( trace->opaque )
1566 + VectorSubtract( trace->hit, trace->origin, displacement );
1567 + d=VectorLength( displacement );
1569 + // d=trace->distance;
1570 + //if (d>256) gatherDirt+=1;
1571 + contribution=d/dd;
1572 + if (contribution>1) contribution=1.0f;
1574 + //gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
1577 + gatherLight+=contribution;
1581 + if( gatherLight <= 0.0f )
1587 + gatherLight/=(sub);
1589 + outLight=gatherLight;
1590 + if( outLight > 1.0f )
1593 + /* return to sender */
1597 Index: tools/quake3/q3map2/light.c
1598 ===================================================================
1599 --- tools/quake3/q3map2/light.c.orig 2008-09-06 15:32:04.000000000 +0200
1600 +++ tools/quake3/q3map2/light.c 2008-09-06 15:32:14.000000000 +0200
1601 @@ -1378,6 +1378,56 @@
1605 + /////// Floodlighting for point //////////////////
1606 + //do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir
1612 + col[0]=col[1]=col[2]=floodlightIntensity;
1616 + trace.testOcclusion = qtrue;
1617 + trace.forceSunlight = qfalse;
1618 + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
1619 + trace.testAll = qtrue;
1623 + if (q==0) //upper hemisphere
1625 + trace.normal[0]=0;
1626 + trace.normal[1]=0;
1627 + trace.normal[2]=1;
1629 + else //lower hemisphere
1631 + trace.normal[0]=0;
1632 + trace.normal[1]=0;
1633 + trace.normal[2]=-1;
1636 + f = FloodLightForSample(&trace);
1638 + contributions[ numCon ].color[0]=col[0]*f;
1639 + contributions[ numCon ].color[1]=col[1]*f;
1640 + contributions[ numCon ].color[2]=col[2]*f;
1642 + contributions[ numCon ].dir[0]=dir[0];
1643 + contributions[ numCon ].dir[1]=dir[1];
1644 + contributions[ numCon ].dir[2]=dir[2];
1646 + contributions[ numCon ].style = 0;
1648 + /* push average direction around */
1649 + addSize = VectorLength( col );
1650 + VectorMA( gp->dir, addSize, dir, gp->dir );
1653 + /////////////////////
1655 /* normalize to get primary light direction */
1656 VectorNormalize( gp->dir, gp->dir );
1658 @@ -1661,6 +1711,12 @@
1659 RunThreadsOnIndividual( numRawLightmaps, qtrue, DirtyRawLightmap );
1662 + /* floodlight them up */
1665 + Sys_Printf( "--- FloodlightRawLightmap ---\n" );
1666 + RunThreadsOnIndividual( numRawLightmaps, qtrue, FloodLightRawLightmap );
1669 /* ydnar: set up light envelopes */
1670 SetupEnvelopes( qfalse, fast );
1671 @@ -1703,6 +1759,7 @@
1674 VectorClear( ambientColor );
1675 + floodlighty = false;
1677 /* generate diffuse lights */
1679 @@ -2191,6 +2248,21 @@
1681 Sys_Printf( "Enabling Challenge Pro Mode Asstacular Vertex Lighting Mode (tm)\n" );
1683 + else if( !strcmp( argv[ i ], "-floodlight" ) )
1685 + floodlighty = qtrue;
1686 + Sys_Printf( "FloodLighting enabled\n" );
1688 + else if( !strcmp( argv[ i ], "-debugnormals" ) )
1690 + debugnormals = qtrue;
1691 + Sys_Printf( "DebugNormals enabled\n" );
1693 + else if( !strcmp( argv[ i ], "-lowquality" ) )
1695 + floodlight_lowquality = qtrue;
1696 + Sys_Printf( "Low Quality FloodLighting enabled\n" );
1699 /* r7: dirtmapping */
1700 else if( !strcmp( argv[ i ], "-dirty" ) )
1701 @@ -2279,6 +2351,7 @@
1702 /* ydnar: set up optimization */
1705 + SetupFloodLight();
1706 SetupSurfaceLightmaps();
1708 /* initialize the surface facet tracing */
1709 Index: tools/quake3/q3map2/lightmaps_ydnar.c
1710 ===================================================================
1711 --- tools/quake3/q3map2/lightmaps_ydnar.c.orig 2008-09-06 15:32:04.000000000 +0200
1712 +++ tools/quake3/q3map2/lightmaps_ydnar.c 2008-09-06 15:32:14.000000000 +0200
1713 @@ -414,6 +414,12 @@
1714 lm->superNormals = safe_malloc( size );
1715 memset( lm->superNormals, 0, size );
1717 + /* allocate floodlight map storage */
1718 + size = lm->sw * lm->sh * SUPER_FLOODLIGHT_SIZE * sizeof( float );
1719 + if( lm->superFloodLight == NULL )
1720 + lm->superFloodLight = safe_malloc( size );
1721 + memset( lm->superFloodLight, 0, size );
1723 /* allocate cluster map storage */
1724 size = lm->sw * lm->sh * sizeof( int );
1725 if( lm->superClusters == NULL )
1726 Index: tools/quake3/q3map2/q3map2.h
1727 ===================================================================
1728 --- tools/quake3/q3map2/q3map2.h.orig 2008-09-06 15:32:04.000000000 +0200
1729 +++ tools/quake3/q3map2/q3map2.h 2008-09-06 15:32:14.000000000 +0200
1731 #define SUPER_NORMAL_SIZE 4
1732 #define SUPER_DELUXEL_SIZE 3
1733 #define BSP_DELUXEL_SIZE 3
1734 +#define SUPER_FLOODLIGHT_SIZE 1
1736 #define VERTEX_LUXEL( s, v ) (vertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
1737 #define RAD_VERTEX_LUXEL( s, v )(radVertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
1739 #define SUPER_ORIGIN( x, y ) (lm->superOrigins + ((((y) * lm->sw) + (x)) * SUPER_ORIGIN_SIZE))
1740 #define SUPER_NORMAL( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE))
1741 #define SUPER_DIRT( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE) + 3) /* stash dirtyness in normal[ 3 ] */
1742 +#define SUPER_FLOODLIGHT( x, y ) (lm->superFloodLight + ((((y) * lm->sw) + (x)) * SUPER_FLOODLIGHT_SIZE) )
1746 @@ -1400,6 +1402,7 @@
1748 float *superDeluxels; /* average light direction */
1750 + float *superFloodLight;
1754 @@ -1712,6 +1715,10 @@
1755 float DirtForSample( trace_t *trace );
1756 void DirtyRawLightmap( int num );
1758 +void SetupFloodLight();
1759 +float FloodLightForSample( trace_t *trace );
1760 +void FloodLightRawLightmap( int num );
1762 void IlluminateRawLightmap( int num );
1763 void IlluminateVertexes( int num );
1765 @@ -2106,6 +2113,13 @@
1766 Q_EXTERN float dirtScale Q_ASSIGN( 1.0f );
1767 Q_EXTERN float dirtGain Q_ASSIGN( 1.0f );
1769 +Q_EXTERN qboolean debugnormals Q_ASSIGN( qfalse );
1770 +Q_EXTERN qboolean floodlighty Q_ASSIGN( qfalse );
1771 +Q_EXTERN qboolean floodlight_lowquality Q_ASSIGN( qfalse );
1772 +Q_EXTERN vec3_t floodlightRGB;
1773 +Q_EXTERN float floodlightIntensity Q_ASSIGN( 512 );
1774 +Q_EXTERN float floodlightDistance Q_ASSIGN( 1024 );
1776 Q_EXTERN qboolean dump Q_ASSIGN( qfalse );
1777 Q_EXTERN qboolean debug Q_ASSIGN( qfalse );
1778 Q_EXTERN qboolean debugUnused Q_ASSIGN( qfalse );
1779 Index: tools/quake3/q3map2/game_ja.h
1780 ===================================================================
1781 --- tools/quake3/q3map2/game_ja.h.orig 2008-09-06 15:32:04.000000000 +0200
1782 +++ tools/quake3/q3map2/game_ja.h 2008-09-06 15:32:16.000000000 +0200
1784 qfalse, /* wolf lighting model? */
1785 128, /* lightmap width/height */
1786 1.0f, /* lightmap gamma */
1787 + 1.0f, /* lightmap exposure */
1788 1.0f, /* lightmap compensate */
1789 "RBSP", /* bsp file prefix */
1790 1, /* bsp file version */
1791 Index: tools/quake3/q3map2/game_tremulous.h
1792 ===================================================================
1793 --- tools/quake3/q3map2/game_tremulous.h.orig 2008-09-06 15:32:04.000000000 +0200
1794 +++ tools/quake3/q3map2/game_tremulous.h 2008-09-06 15:32:16.000000000 +0200
1796 qfalse, /* wolf lighting model? */
1797 128, /* lightmap width/height */
1798 1.0f, /* lightmap gamma */
1799 + 1.0f, /* lightmap exposure */
1800 1.0f, /* lightmap compensate */
1801 "IBSP", /* bsp file prefix */
1802 46, /* bsp file version */
1803 Index: tools/quake3/q3map2/game_wolfet.h
1804 ===================================================================
1805 --- tools/quake3/q3map2/game_wolfet.h.orig 2008-09-06 15:32:04.000000000 +0200
1806 +++ tools/quake3/q3map2/game_wolfet.h 2008-09-06 15:32:16.000000000 +0200
1808 qtrue, /* wolf lighting model? */
1809 128, /* lightmap width/height */
1810 1.0f, /* lightmap gamma */
1811 + 1.0f, /* lightmap exposure */
1812 1.0f, /* lightmap compensate */
1813 "IBSP", /* bsp file prefix */
1814 47, /* bsp file version */
1815 Index: tools/quake3/q3map2/game_wolf.h
1816 ===================================================================
1817 --- tools/quake3/q3map2/game_wolf.h.orig 2008-09-06 15:32:04.000000000 +0200
1818 +++ tools/quake3/q3map2/game_wolf.h 2008-09-06 15:32:16.000000000 +0200
1820 qtrue, /* wolf lighting model? */
1821 128, /* lightmap width/height */
1822 1.0f, /* lightmap gamma */
1823 + 1.0f, /* lightmap exposure */
1824 1.0f, /* lightmap compensate */
1825 "IBSP", /* bsp file prefix */
1826 47, /* bsp file version */
1827 Index: tools/quake3/q3map2/game_sof2.h
1828 ===================================================================
1829 --- tools/quake3/q3map2/game_sof2.h.orig 2008-09-06 15:32:04.000000000 +0200
1830 +++ tools/quake3/q3map2/game_sof2.h 2008-09-06 15:32:16.000000000 +0200
1832 qfalse, /* wolf lighting model? */
1833 128, /* lightmap width/height */
1834 1.0f, /* lightmap gamma */
1835 + 1.0f, /* lightmap exposure */
1836 1.0f, /* lightmap compensate */
1837 "RBSP", /* bsp file prefix */
1838 1, /* bsp file version */
1839 Index: tools/quake3/q3map2/game_etut.h
1840 ===================================================================
1841 --- tools/quake3/q3map2/game_etut.h.orig 2008-09-06 15:32:04.000000000 +0200
1842 +++ tools/quake3/q3map2/game_etut.h 2008-09-06 15:32:16.000000000 +0200
1844 qfalse, /* wolf lighting model? */
1845 128, /* lightmap width/height */
1846 2.2f, /* lightmap gamma */
1847 + 1.0f, /* lightmap exposure */
1848 1.0f, /* lightmap compensate */
1849 "IBSP", /* bsp file prefix */
1850 47, /* bsp file version */
1851 Index: tools/quake3/q3map2/game_jk2.h
1852 ===================================================================
1853 --- tools/quake3/q3map2/game_jk2.h.orig 2008-09-06 15:32:04.000000000 +0200
1854 +++ tools/quake3/q3map2/game_jk2.h 2008-09-06 15:32:16.000000000 +0200
1856 qfalse, /* wolf lighting model? */
1857 128, /* lightmap width/height */
1858 1.0f, /* lightmap gamma */
1859 + 1.0f, /* lightmap exposure */
1860 1.0f, /* lightmap compensate */
1861 "RBSP", /* bsp file prefix */
1862 1, /* bsp file version */
1863 Index: tools/quake3/q3map2/game_qfusion.h
1864 ===================================================================
1865 --- tools/quake3/q3map2/game_qfusion.h.orig 2008-09-06 15:32:04.000000000 +0200
1866 +++ tools/quake3/q3map2/game_qfusion.h 2008-09-06 15:32:16.000000000 +0200
1868 qfalse, /* wolf lighting model? */
1869 512, /* lightmap width/height */
1870 1.0f, /* lightmap gamma */
1871 + 1.0f, /* lightmap exposure */
1872 1.0f, /* lightmap compensate */
1873 "FBSP", /* bsp file prefix */
1874 1, /* bsp file version */
1875 Index: tools/quake3/q3map2/game_tenebrae.h
1876 ===================================================================
1877 --- tools/quake3/q3map2/game_tenebrae.h.orig 2008-09-06 15:32:04.000000000 +0200
1878 +++ tools/quake3/q3map2/game_tenebrae.h 2008-09-06 15:32:16.000000000 +0200
1880 qfalse, /* wolf lighting model? */
1881 512, /* lightmap width/height */
1882 2.0f, /* lightmap gamma */
1883 + 1.0f, /* lightmap exposure */
1884 1.0f, /* lightmap compensate */
1885 "IBSP", /* bsp file prefix */
1886 46, /* bsp file version */
1887 Index: tools/quake3/q3map2/game_quake3.h
1888 ===================================================================
1889 --- tools/quake3/q3map2/game_quake3.h.orig 2008-09-06 15:32:04.000000000 +0200
1890 +++ tools/quake3/q3map2/game_quake3.h 2008-09-06 15:32:16.000000000 +0200
1892 qfalse, /* wolf lighting model? */
1893 128, /* lightmap width/height */
1894 1.0f, /* lightmap gamma */
1895 + 1.0f, /* lightmap exposure */
1896 1.0f, /* lightmap compensate */
1897 "IBSP", /* bsp file prefix */
1898 47, /* bsp file version */
1899 Index: tools/quake3/q3map2/game_ef.h
1900 ===================================================================
1901 --- tools/quake3/q3map2/game_ef.h.orig 2008-09-06 15:32:04.000000000 +0200
1902 +++ tools/quake3/q3map2/game_ef.h 2008-09-06 15:32:16.000000000 +0200
1904 qfalse, /* wolf lighting model? */
1905 128, /* lightmap width/height */
1906 1.0f, /* lightmap gamma */
1907 + 1.0f, /* lightmap exposure */
1908 1.0f, /* lightmap compensate */
1909 "IBSP", /* bsp file prefix */
1910 46, /* bsp file version */
1911 Index: tools/quake3/q3map2/light_ydnar.c
1912 ===================================================================
1913 --- tools/quake3/q3map2/light_ydnar.c.orig 2008-09-06 15:32:14.000000000 +0200
1914 +++ tools/quake3/q3map2/light_ydnar.c 2008-09-06 15:32:16.000000000 +0200
1922 /* ydnar: scaling necessary for simulating r_overbrightBits on external lightmaps */
1925 sample[ i ] = pow( sample[ i ] / 255.0f, gamma ) * 255.0f;
1928 - /* clamp with color normalization */
1929 - max = sample[ 0 ];
1930 - if( sample[ 1 ] > max )
1931 - max = sample[ 1 ];
1932 - if( sample[ 2 ] > max )
1933 - max = sample[ 2 ];
1934 - if( max > 255.0f )
1935 - VectorScale( sample, (255.0f / max), sample );
1937 + if (lightmapExposure == 1)
1939 + /* clamp with color normalization */
1940 + max = sample[ 0 ];
1941 + if( sample[ 1 ] > max )
1942 + max = sample[ 1 ];
1943 + if( sample[ 2 ] > max )
1944 + max = sample[ 2 ];
1945 + if( max > 255.0f )
1946 + VectorScale( sample, (255.0f / max), sample );
1950 + if (lightmapExposure==0)
1952 + lightmapExposure=1.0f;
1954 + inv=1.f/lightmapExposure;
1957 + max = sample[ 0 ];
1958 + if( sample[ 1 ] > max )
1959 + max = sample[ 1 ];
1960 + if( sample[ 2 ] > max )
1961 + max = sample[ 2 ];
1963 + dif = (1- exp(-max * inv) ) * 255;
1981 /* compensate for ingame overbrighting/bitshifting */
1982 VectorScale( sample, (1.0f / lightmapCompensate), sample );
1983 Index: tools/quake3/q3map2/q3map2.h
1984 ===================================================================
1985 --- tools/quake3/q3map2/q3map2.h.orig 2008-09-06 15:32:14.000000000 +0200
1986 +++ tools/quake3/q3map2/q3map2.h 2008-09-06 15:32:16.000000000 +0200
1988 qboolean wolfLight; /* when true, lights work like wolf q3map */
1989 int lightmapSize; /* bsp lightmap width/height */
1990 float lightmapGamma; /* default lightmap gamma */
1991 + float lightmapExposure; /* default lightmap exposure */
1992 float lightmapCompensate; /* default lightmap compensate value */
1993 char *bspIdent; /* 4-letter bsp file prefix */
1994 int bspVersion; /* bsp version to use */
1995 @@ -2139,6 +2140,7 @@
1997 /* ydnar: lightmap gamma/compensation */
1998 Q_EXTERN float lightmapGamma Q_ASSIGN( 1.0f );
1999 +Q_EXTERN float lightmapExposure Q_ASSIGN( 1.0f );
2000 Q_EXTERN float lightmapCompensate Q_ASSIGN( 1.0f );
2002 /* ydnar: for runtime tweaking of falloff tolerance */
2003 Index: tools/quake3/q3map2/light.c
2004 ===================================================================
2005 --- tools/quake3/q3map2/light.c.orig 2008-09-06 15:32:14.000000000 +0200
2006 +++ tools/quake3/q3map2/light.c 2008-09-06 15:32:16.000000000 +0200
2007 @@ -1893,6 +1893,14 @@
2011 + else if( !strcmp( argv[ i ], "-exposure" ) )
2013 + f = atof( argv[ i + 1 ] );
2014 + lightmapExposure = f;
2015 + Sys_Printf( "Lighting exposure set to %f\n", lightmapExposure );
2019 else if( !strcmp( argv[ i ], "-compensate" ) )
2021 f = atof( argv[ i + 1 ] );
2022 Index: tools/quake3/q3map2/light_ydnar.c
2023 ===================================================================
2024 --- tools/quake3/q3map2/light_ydnar.c.orig 2008-09-06 15:32:16.000000000 +0200
2025 +++ tools/quake3/q3map2/light_ydnar.c 2008-09-06 15:32:18.000000000 +0200
2028 #define BOGUS_NUDGE -99999.0f
2030 -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 ] )
2031 +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 ] )
2033 int i, x, y, numClusters, *clusters, pointCluster, *cluster;
2034 float *luxel, *origin, *normal, d, lightmapSampleOffset;
2035 @@ -428,6 +428,12 @@
2039 + vec3_t cverts[ 3 ];
2041 + vec4_t sideplane, hostplane;
2046 static float nudges[][ 2 ] =
2048 @@ -521,6 +527,51 @@
2049 /* non axial lightmap projection (explicit xyz) */
2051 VectorCopy( dv->xyz, origin );
2053 + //////////////////////
2054 + //27's test to make sure samples stay within the triangle boundaries
2055 + //1) Test the sample origin to see if it lays on the wrong side of any edge (x/y)
2056 + //2) if it does, nudge it onto the correct side.
2058 + if (worldverts!=NULL)
2062 + VectorCopy(worldverts[j],cverts[j]);
2064 + PlaneFromPoints(hostplane,cverts[0],cverts[1],cverts[2]);
2070 + //build plane using 2 edges and a normal
2073 + VectorCopy(cverts[next],temp);
2074 + VectorAdd(temp,hostplane,temp);
2075 + PlaneFromPoints(sideplane,cverts[i],cverts[ next ], temp);
2077 + //planetest sample point
2078 + e=DotProduct(origin,sideplane);
2083 + //VectorClear(origin);
2084 + //Move the sample point back inside triangle bounds
2085 + origin[0]-=sideplane[0]*(e+1);
2086 + origin[1]-=sideplane[1]*(e+1);
2087 + origin[2]-=sideplane[2]*(e+1);
2089 + VectorClear(origin);
2096 + ////////////////////////
2098 /* planar surfaces have precalculated lightmap vectors for nudging */
2099 if( lm->plane != NULL )
2100 @@ -552,8 +603,13 @@
2102 origin[ lm->axisNum ] += lightmapSampleOffset;
2104 + VectorCopy(origin,origintwo);
2105 + origintwo[0]+=vecs[2][0];
2106 + origintwo[1]+=vecs[2][1];
2107 + origintwo[2]+=vecs[2][2];
2110 - pointCluster = ClusterForPointExtFilter( origin, LUXEL_EPSILON, numClusters, clusters );
2111 + pointCluster = ClusterForPointExtFilter( origintwo, LUXEL_EPSILON, numClusters, clusters );
2113 /* another retarded hack, storing nudge count in luxel[ 1 ] */
2115 @@ -569,14 +625,14 @@
2116 for( i = 0; i < 3; i++ )
2118 /* set nudged point*/
2119 - nudged[ i ] = origin[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
2120 + nudged[ i ] = origintwo[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
2124 /* get pvs cluster */
2125 pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters ); //% + 0.625 );
2126 - if( pointCluster >= 0 )
2127 - VectorCopy( nudged, origin );
2128 + //if( pointCluster >= 0 )
2129 + // VectorCopy( nudged, origin );
2135 VectorMA( dv->xyz, lightmapSampleOffset, dv->normal, nudged );
2136 pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters );
2137 - if( pointCluster >= 0 )
2138 - VectorCopy( nudged, origin );
2139 + //if( pointCluster >= 0 )
2140 + // VectorCopy( nudged, origin );
2145 than the distance between two luxels (thanks jc :)
2148 -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 ] )
2149 +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 ] )
2151 bspDrawVert_t mid, *dv2[ 3 ];
2155 /* split the longest edge and map it */
2156 LerpDrawVert( dv[ max ], dv[ (max + 1) % 3 ], &mid );
2157 - MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv );
2158 + MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv, worldverts );
2160 /* push the point up a little bit to account for fp creep (fixme: revisit this) */
2161 //% VectorMA( mid.xyz, 2.0f, mid.normal, mid.xyz );
2162 @@ -689,12 +745,12 @@
2163 /* recurse to first triangle */
2164 VectorCopy( dv, dv2 );
2166 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
2167 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
2169 /* recurse to second triangle */
2170 VectorCopy( dv, dv2 );
2171 dv2[ (max + 1) % 3 ] = ∣
2172 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
2173 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
2180 vec3_t *stv, *ttv, stvStatic[ 3 ], ttvStatic[ 3 ];
2181 + vec3_t worldverts[ 3 ];
2184 /* get plane if possible */
2185 @@ -735,16 +792,20 @@
2189 + VectorCopy( dv[ 0 ]->xyz, worldverts[ 0 ] );
2190 + VectorCopy( dv[ 1 ]->xyz, worldverts[ 1 ] );
2191 + VectorCopy( dv[ 2 ]->xyz, worldverts[ 2 ] );
2193 /* map the vertexes */
2194 - MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
2195 - MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
2196 - MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
2197 + MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, worldverts );
2198 + MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, worldverts );
2199 + MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, worldverts );
2201 /* 2002-11-20: prefer axial triangle edges */
2204 /* subdivide the triangle */
2205 - MapTriangle_r( lm, info, dv, plane, stv, ttv );
2206 + MapTriangle_r( lm, info, dv, plane, stv, ttv, worldverts );
2211 dv2[ 2 ] = dv[ (i + 1) % 3 ];
2213 /* map the degenerate triangle */
2214 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
2215 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
2220 LerpDrawVert( dv[ max + 2 ], dv[ (max + 3) % 4 ], &mid[ 1 ] );
2222 /* map the vertexes */
2223 - MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv );
2224 - MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv );
2225 + MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv, NULL );
2226 + MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv, NULL );
2230 @@ -914,10 +975,10 @@
2233 /* map the vertexes */
2234 - MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
2235 - MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
2236 - MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
2237 - MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv );
2238 + MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, NULL );
2239 + MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, NULL );
2240 + MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, NULL );
2241 + MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv, NULL );
2243 /* subdivide the quad */
2244 MapQuad_r( lm, info, dv, plane, stv, ttv );
2245 @@ -1209,7 +1270,7 @@
2248 /* map the fake vert */
2249 - MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL );
2250 + MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL, NULL );
2254 @@ -2001,22 +2062,32 @@
2255 deluxel = SUPER_DELUXEL( x, y );
2256 origin = SUPER_ORIGIN( x, y );
2257 normal = SUPER_NORMAL( x, y );
2259 - /* set contribution count */
2260 - lightLuxel[ 3 ] = 1.0f;
2263 - trace.cluster = *cluster;
2264 - VectorCopy( origin, trace.origin );
2265 - VectorCopy( normal, trace.normal );
2267 - /* get light for this sample */
2268 - LightContributionToSample( &trace );
2269 - VectorCopy( trace.color, lightLuxel );
2271 - /* add to count */
2272 - if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
2274 + ////////// 27's temp hack for testing edge clipping ////
2275 + if( origin[0]==0 && origin[1]==0 && origin[2]==0 )
2277 + lightLuxel[ 1 ] = 255;
2278 + lightLuxel[ 3 ] = 1.0f;
2283 + /* set contribution count */
2284 + lightLuxel[ 3 ] = 1.0f;
2287 + trace.cluster = *cluster;
2288 + VectorCopy( origin, trace.origin );
2289 + VectorCopy( normal, trace.normal );
2291 + /* get light for this sample */
2292 + LightContributionToSample( &trace );
2293 + VectorCopy( trace.color, lightLuxel );
2295 + /* add to count */
2296 + if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
2300 /* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
2302 Index: tools/quake3/q3map2/q3map2.h
2303 ===================================================================
2304 --- tools/quake3/q3map2/q3map2.h (revision 303)
2305 +++ tools/quake3/q3map2/q3map2.h (working copy)
2310 -#define Q3MAP_VERSION "2.5.17"
2311 -#define Q3MAP_MOTD "Last one turns the lights off"
2312 +#define Q3MAP_VERSION "2.5.17-div0-obj-decomptexcoords-format46-snapplane-UTavgcolorfix-UTfloodlight-UTlmexposure-UTtrianglecheck"
2313 +#define Q3MAP_MOTD "Light some candles, put them on a wooden table, take a photo, and paste it on the lightmaps!"
2317 Index: include/version.default
2318 ===================================================================
2319 --- include/version.default (revision 290)
2320 +++ include/version.default (working copy)
2323 +1.4.0-div0-obj-targetname
\r