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: tools/quake3/q3map2/convert_map.c
115 ===================================================================
116 --- tools/quake3/q3map2/convert_map.c (revision 290)
117 +++ tools/quake3/q3map2/convert_map.c (working copy)
119 #define SNAP_FLOAT_TO_INT 4
120 #define SNAP_INT_TO_FLOAT (1.0 / SNAP_FLOAT_TO_INT)
122 +typedef vec_t vec2_t[2];
124 +static vec_t Det3x3(vec_t a00, vec_t a01, vec_t a02,
125 + vec_t a10, vec_t a11, vec_t a12,
126 + vec_t a20, vec_t a21, vec_t a22)
129 + a00 * (a11 * a22 - a12 * a21)
130 + - a01 * (a10 * a22 - a12 * a20)
131 + + a02 * (a10 * a21 - a11 * a20);
134 +void GetBestSurfaceTriangleMatchForBrushside(side_t *buildSide, bspDrawVert_t *bestVert[3])
136 + bspDrawSurface_t *s;
142 + vec3_t v1v0, v2v0, norm;
143 + bspDrawVert_t *vert[3];
144 + winding_t *polygon;
145 + plane_t *buildPlane = &mapplanes[buildSide->planenum];
148 + // first, start out with NULLs
149 + bestVert[0] = bestVert[1] = bestVert[2] = NULL;
151 + // brute force through all surfaces
152 + for(s = bspDrawSurfaces; s != bspDrawSurfaces + numBSPDrawSurfaces; ++s)
154 + if(s->surfaceType != MST_PLANAR && s->surfaceType != MST_TRIANGLE_SOUP)
156 + if(strcmp(buildSide->shaderInfo->shader, bspShaders[s->shaderNum].shader))
158 + for(t = 0; t + 3 <= s->numIndexes; t += 3)
160 + vert[0] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 0]];
161 + vert[1] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 1]];
162 + vert[2] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 2]];
163 + if(s->surfaceType == MST_PLANAR)
165 + VectorSubtract(vert[0]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
166 + VectorSubtract(vert[1]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
167 + VectorSubtract(vert[2]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
171 + // this is more prone to roundoff errors, but with embedded
172 + // models, there is no better way
173 + VectorSubtract(vert[1]->xyz, vert[0]->xyz, v1v0);
174 + VectorSubtract(vert[2]->xyz, vert[0]->xyz, v2v0);
175 + CrossProduct(v2v0, v1v0, norm);
176 + VectorNormalize(norm, norm);
177 + VectorSubtract(norm, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
179 + if(abs(DotProduct(vert[0]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
180 + if(abs(DotProduct(vert[1]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
181 + if(abs(DotProduct(vert[2]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
182 + // Okay. Correct surface type, correct shader, correct plane. Let's start with the business...
183 + polygon = CopyWinding(buildSide->winding);
184 + for(i = 0; i < 3; ++i)
189 + vec3_t *v1 = &vert[(i+1)%3]->xyz;
190 + vec3_t *v2 = &vert[(i+2)%3]->xyz;
193 + vec3_t sideDirection;
194 + // we now need to generate triNormal and triDist so that they represent the plane spanned by normal and (v2 - v1).
195 + VectorSubtract(*v2, *v1, sideDirection);
196 + CrossProduct(sideDirection, buildPlane->normal, triNormal);
197 + triDist = DotProduct(*v1, triNormal);
198 + ChopWindingInPlace(&polygon, triNormal, triDist, distanceEpsilon);
202 + thisarea = WindingArea(polygon);
205 + if(thisarea > best)
208 + bestVert[0] = vert[0];
209 + bestVert[1] = vert[1];
210 + bestVert[2] = vert[2];
212 + FreeWinding(polygon);
217 + //if(strncmp(buildSide->shaderInfo->shader, "textures/common/", 16))
218 + // fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide->shaderInfo->shader, matches, best);
221 static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
228 + plane_t *buildPlane;
230 + bspDrawVert_t *vert[3];
235 fprintf( f, "\t// brush %d\n", num );
236 fprintf( f, "\t{\n" );
237 + fprintf( f, "\tbrushDef\n" );
238 + fprintf( f, "\t{\n" );
240 /* clear out build brush */
241 for( i = 0; i < buildBrush->numsides; i++ )
244 buildSide = &buildBrush->sides[ i ];
247 + buildPlane = &mapplanes[ buildSide->planenum ];
250 if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
253 + // st-texcoords -> texMat block
254 + // start out with dummy
255 + VectorSet(buildSide->texMat[0], 1/32.0, 0, 0);
256 + VectorSet(buildSide->texMat[1], 0, 1/32.0, 0);
258 + // find surface for this side (by brute force)
260 + // - meshverts point in pairs of three into verts
262 + // - find the triangle that has most in common with our side
263 + GetBestSurfaceTriangleMatchForBrushside(buildSide, vert);
266 + if(vert[0] && vert[1] && vert[2])
270 + vec3_t xy1I, xy1J, xy1K;
271 + vec2_t stI, stJ, stK;
272 + vec_t D, D0, D1, D2;
274 + ComputeAxisBase(buildPlane->normal, texX, texY);
276 + VectorSet(xy1I, DotProduct(vert[0]->xyz, texX), DotProduct(vert[0]->xyz, texY), 1);
277 + VectorSet(xy1J, DotProduct(vert[1]->xyz, texX), DotProduct(vert[1]->xyz, texY), 1);
278 + VectorSet(xy1K, DotProduct(vert[2]->xyz, texX), DotProduct(vert[2]->xyz, texY), 1);
279 + stI[0] = vert[0]->st[0]; stI[1] = vert[0]->st[1];
280 + stJ[0] = vert[1]->st[0]; stJ[1] = vert[1]->st[1];
281 + stK[0] = vert[2]->st[0]; stK[1] = vert[2]->st[1];
283 + // - solve linear equations:
284 + // - (x, y) := xyz . (texX, texY)
285 + // - st[i] = texMat[i][0]*x + texMat[i][1]*y + texMat[i][2]
286 + // (for three vertices)
288 + xy1I[0], xy1I[1], 1,
289 + xy1J[0], xy1J[1], 1,
290 + xy1K[0], xy1K[1], 1
294 + for(i = 0; i < 2; ++i)
297 + stI[i], xy1I[1], 1,
298 + stJ[i], xy1J[1], 1,
302 + xy1I[0], stI[i], 1,
303 + xy1J[0], stJ[i], 1,
307 + xy1I[0], xy1I[1], stI[i],
308 + xy1J[0], xy1J[1], stJ[i],
309 + xy1K[0], xy1K[1], stK[i]
311 + VectorSet(buildSide->texMat[i], D0 / D, D1 / D, D2 / D);
316 + 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",
317 + buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2],
318 + vert[0]->normal[0], vert[0]->normal[1], vert[0]->normal[2],
319 + texX[0], texX[1], texX[2], texY[0], texY[1], texY[2],
320 + vert[0]->xyz[0], vert[0]->xyz[1], vert[0]->xyz[2], xy1I[0], xy1I[1],
321 + vert[1]->xyz[0], vert[1]->xyz[1], vert[1]->xyz[2], xy1J[0], xy1J[1],
322 + vert[2]->xyz[0], vert[2]->xyz[1], vert[2]->xyz[2], xy1K[0], xy1K[1]
326 + if(strncmp(buildSide->shaderInfo->shader, "textures/common/", 16))
327 + fprintf(stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide->shaderInfo->shader);
329 /* get texture name */
330 if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
331 @@ -129,14 +312,21 @@
333 /* print brush side */
334 /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
335 - 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",
336 + fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( ( %.8f %.8f %.8f ) ( %.8f %.8f %.8f ) ) %s %d 0 0\n",
337 pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
338 pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
339 pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
341 + buildSide->texMat[0][0], buildSide->texMat[0][1], buildSide->texMat[0][2],
342 + buildSide->texMat[1][0], buildSide->texMat[1][1], buildSide->texMat[1][2],
344 + // DEBUG: valid ? 0 : C_DETAIL
347 + // TODO write brush primitives format here
351 + fprintf( f, "\t}\n" );
352 fprintf( f, "\t}\n\n" );
355 Index: tools/quake3/q3map2/main.c
356 ===================================================================
357 --- tools/quake3/q3map2/main.c (revision 290)
358 +++ tools/quake3/q3map2/main.c (working copy)
361 Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
363 + else if( !strcmp( argv[ i ], "-ne" ) )
365 + normalEpsilon = atof( argv[ i + 1 ] );
367 + Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
369 + else if( !strcmp( argv[ i ], "-de" ) )
371 + distanceEpsilon = atof( argv[ i + 1 ] );
373 + Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
377 /* clean up map name */
378 Index: tools/quake3/q3map2/model.c
379 ===================================================================
380 --- tools/quake3/q3map2/model.c (revision 290)
381 +++ tools/quake3/q3map2/model.c (working copy)
384 picoIndex_t *indexes;
386 + double normalEpsilon_save;
387 + double distanceEpsilon_save;
392 /* ydnar: giant hack land: generate clipping brushes for model triangles */
393 if( si->clipModel || (spawnFlags & 2) ) /* 2nd bit */
395 - vec3_t points[ 3 ], backs[ 3 ];
396 + vec3_t points[ 4 ], backs[ 3 ];
397 vec4_t plane, reverse, pa, pb, pc;
402 @@ -437,90 +438,141 @@
403 /* note: this doesn't work as well as simply using the plane of the triangle, below */
404 for( k = 0; k < 3; k++ )
406 - if( fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 1) % 3 ] ) &&
407 - fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 2) % 3 ] ) )
408 + if( fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 1) % 3 ] ) &&
409 + fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 2) % 3 ] ) )
411 backs[ j ][ k ] += dv->normal[ k ] < 0.0f ? 64.0f : -64.0f;
417 + VectorCopy( points[0], points[3] ); // for cyclic usage
419 /* make plane for triangle */
420 + // div0: add some extra spawnflags:
421 + // 0: snap normals to axial planes for extrusion
422 + // 8: extrude with the original normals
423 + // 16: extrude only with up/down normals (ideal for terrain)
424 + // 24: extrude by distance zero (may need engine changes)
425 if( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) )
428 + float backPlaneDistance = 2;
430 + if(spawnFlags & 8) // use a DOWN normal
432 + if(spawnFlags & 16)
434 + // 24: normal as is, and zero width (broken)
435 + VectorCopy(plane, bestNormal);
440 + VectorCopy(plane, bestNormal);
445 + if(spawnFlags & 16)
447 + // 16: UP/DOWN normal
448 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
453 + if(fabs(plane[0]) > fabs(plane[1])) // x>y
454 + if(fabs(plane[1]) > fabs(plane[2])) // x>y, y>z
455 + VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
457 + if(fabs(plane[0]) > fabs(plane[2])) // x>z, z>=y
458 + VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
460 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
462 + if(fabs(plane[1]) > fabs(plane[2])) // y>z, y>=x
463 + VectorSet(bestNormal, 0, (plane[1] >= 0 ? 1 : -1), 0);
465 + VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
469 + /* build a brush */
470 + buildBrush = AllocBrush( 48 );
471 + buildBrush->entityNum = mapEntityNum;
472 + buildBrush->original = buildBrush;
473 + buildBrush->contentShader = si;
474 + buildBrush->compileFlags = si->compileFlags;
475 + buildBrush->contentFlags = si->contentFlags;
476 + normalEpsilon_save = normalEpsilon;
477 + distanceEpsilon_save = distanceEpsilon;
478 + if(si->compileFlags & C_STRUCTURAL) // allow forced structural brushes here
480 + buildBrush->detail = qfalse;
482 + // only allow EXACT matches when snapping for these (this is mostly for caulk brushes inside a model)
483 + if(normalEpsilon > 0)
485 + if(distanceEpsilon > 0)
486 + distanceEpsilon = 0;
489 + buildBrush->detail = qtrue;
491 /* regenerate back points */
492 for( j = 0; j < 3; j++ )
495 dv = &ds->verts[ ds->indexes[ i + j ] ];
498 - VectorCopy( dv->xyz, backs[ j ] );
500 - /* find nearest axial to plane normal and push back points opposite */
501 - for( k = 0; k < 3; k++ )
503 - if( fabs( plane[ k ] ) > fabs( plane[ (k + 1) % 3 ] ) &&
504 - fabs( plane[ k ] ) > fabs( plane[ (k + 2) % 3 ] ) )
506 - backs[ j ][ k ] += plane[ k ] < 0.0f ? 64.0f : -64.0f;
511 + // shift by some units
512 + VectorMA(dv->xyz, -64.0f, bestNormal, backs[j]); // 64 prevents roundoff errors a bit
516 /* make back plane */
517 VectorScale( plane, -1.0f, reverse );
518 - reverse[ 3 ] = -(plane[ 3 ] - 1);
520 - /* make back pyramid point */
521 - VectorCopy( points[ 0 ], nadir );
522 - VectorAdd( nadir, points[ 1 ], nadir );
523 - VectorAdd( nadir, points[ 2 ], nadir );
524 - VectorScale( nadir, 0.3333333333333f, nadir );
525 - VectorMA( nadir, -2.0f, plane, nadir );
527 - /* make 3 more planes */
528 - //% if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], nadir ) &&
529 - //% PlaneFromPoints( pb, points[ 1 ], points[ 0 ], nadir ) &&
530 - //% PlaneFromPoints( pc, points[ 0 ], points[ 2 ], nadir ) )
531 + reverse[ 3 ] = -plane[ 3 ];
532 + if((spawnFlags & 24) != 24)
533 + reverse[3] += DotProduct(bestNormal, plane) * backPlaneDistance;
534 + // 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)
536 if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], backs[ 1 ] ) &&
537 - PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
538 - PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
539 + PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
540 + PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
542 - /* build a brush */
543 - buildBrush = AllocBrush( 48 );
545 - buildBrush->entityNum = mapEntityNum;
546 - buildBrush->original = buildBrush;
547 - buildBrush->contentShader = si;
548 - buildBrush->compileFlags = si->compileFlags;
549 - buildBrush->contentFlags = si->contentFlags;
550 - buildBrush->detail = qtrue;
552 /* set up brush sides */
553 buildBrush->numsides = 5;
554 for( j = 0; j < buildBrush->numsides; j++ )
555 buildBrush->sides[ j ].shaderInfo = si;
557 buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
558 - buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 1, &points[ 2 ] );
559 - buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 1, &points[ 1 ] );
560 - buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 1, &points[ 0 ] );
561 - buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, points );
563 - /* add to entity */
564 - if( CreateBrushWindings( buildBrush ) )
567 - //% EmitBrushes( buildBrush, NULL, NULL );
568 - buildBrush->next = entities[ mapEntityNum ].brushes;
569 - entities[ mapEntityNum ].brushes = buildBrush;
570 - entities[ mapEntityNum ].numBrushes++;
573 - free( buildBrush );
574 + buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 2, &points[ 1 ] ); // pa contains points[1] and points[2]
575 + buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 2, &points[ 0 ] ); // pb contains points[0] and points[1]
576 + buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 2, &points[ 2 ] ); // pc contains points[2] and points[0] (copied to points[3]
577 + buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, backs );
585 + normalEpsilon = normalEpsilon_save;
586 + distanceEpsilon = distanceEpsilon_save;
588 + /* add to entity */
589 + if( CreateBrushWindings( buildBrush ) )
592 + //% EmitBrushes( buildBrush, NULL, NULL );
593 + buildBrush->next = entities[ mapEntityNum ].brushes;
594 + entities[ mapEntityNum ].brushes = buildBrush;
595 + entities[ mapEntityNum ].numBrushes++;
598 + free( buildBrush );
602 Index: tools/quake3/q3map2/map.c
603 ===================================================================
604 --- tools/quake3/q3map2/map.c (revision 290)
605 +++ tools/quake3/q3map2/map.c (working copy)
607 snaps a plane to normal/distance epsilons
610 -void SnapPlane( vec3_t normal, vec_t *dist )
611 +void SnapPlane( vec3_t normal, vec_t *dist, vec3_t center )
613 - SnapNormal( normal );
614 + // div0: ensure the point "center" stays on the plane (actually, this
615 + // rotates the plane around the point center).
616 + // if center lies on the plane, it is guaranteed to stay on the plane by
618 + vec_t centerDist = DotProduct(normal, center);
619 + SnapNormal( normal );
620 + *dist += (DotProduct(normal, center) - centerDist);
622 if( fabs( *dist - Q_rint( *dist ) ) < distanceEpsilon )
623 *dist = Q_rint( *dist );
625 must be within an epsilon distance of the plane
628 -int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points )
629 +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?
633 @@ -207,10 +213,14 @@
637 + vec3_t centerofweight;
639 + VectorClear(centerofweight);
640 + for(i = 0; i < numPoints; ++i)
641 + VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
645 - SnapPlane( normal, &dist );
646 + SnapPlane( normal, &dist, centerofweight );
647 hash = (PLANE_HASHES - 1) & (int) fabs( dist );
649 /* search the border bins as well */
654 - SnapPlane( normal, &dist );
655 + vec3_t centerofweight;
657 + VectorClear(centerofweight);
658 + for(i = 0; i < numPoints; ++i)
659 + VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
661 + SnapPlane( normal, &dist, centerofweight );
662 for( i = 0, p = mapplanes; i < nummapplanes; i++, p++ )
664 if( PlaneEqual( p, normal, dist ) )
665 Index: tools/quake3/q3map2/shaders.c
666 ===================================================================
667 --- tools/quake3/q3map2/shaders.c (revision 290)
668 +++ tools/quake3/q3map2/shaders.c (working copy)
672 if( VectorLength( si->color ) <= 0.0f )
674 ColorNormalize( color, si->color );
675 - VectorScale( color, (1.0f / count), si->averageColor );
676 + VectorScale( color, (1.0f / count), si->averageColor );
680 + VectorCopy( si->color, si->averageColor );
685 Index: tools/quake3/q3map2/light_ydnar.c
686 ===================================================================
687 --- tools/quake3/q3map2/light_ydnar.c (revision 290)
688 +++ tools/quake3/q3map2/light_ydnar.c (working copy)
689 @@ -1449,6 +1449,8 @@
690 vec3_t color, averageColor, averageDir, total, temp, temp2;
691 float tests[ 4 ][ 2 ] = { { 0.0f, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
697 /* bail if this number exceeds the number of raw lightmaps */
698 @@ -1871,6 +1873,78 @@
699 /* free light list */
700 FreeTraceLights( &trace );
702 + /* -----------------------------------------------------------------
704 + ----------------------------------------------------------------- */
708 + /* walk lightmaps */
709 + for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
712 + if( lm->superLuxels[ lightmapNum ] == NULL )
715 + /* apply floodlight to each luxel */
716 + for( y = 0; y < lm->sh; y++ )
718 + for( x = 0; x < lm->sw; x++ )
721 + cluster = SUPER_CLUSTER( x, y );
722 + //% if( *cluster < 0 )
725 + /* get particulars */
726 + luxel = SUPER_LUXEL( lightmapNum, x, y );
727 + floodlight = SUPER_FLOODLIGHT( x, y );
729 + flood[0]=floodlightRGB[0]*floodlightIntensity;
730 + flood[1]=floodlightRGB[1]*floodlightIntensity;
731 + flood[2]=floodlightRGB[2]*floodlightIntensity;
733 + /* scale light value */
734 + VectorScale( flood, *floodlight, flood );
735 + luxel[0]+=flood[0];
736 + luxel[1]+=flood[1];
737 + luxel[2]+=flood[2];
739 + if (luxel[3]==0) luxel[3]=1;
747 + for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
750 + if( lm->superLuxels[ lightmapNum ] == NULL )
753 + for( y = 0; y < lm->sh; y++ )
755 + for( x = 0; x < lm->sw; x++ )
758 + cluster = SUPER_CLUSTER( x, y );
759 + //% if( *cluster < 0 )
762 + /* get particulars */
763 + luxel = SUPER_LUXEL( lightmapNum, x, y );
764 + normal = SUPER_NORMAL ( x, y );
766 + luxel[0]=(normal[0]*127)+127;
767 + luxel[1]=(normal[1]*127)+127;
768 + luxel[2]=(normal[2]*127)+127;
774 /* -----------------------------------------------------------------
776 ----------------------------------------------------------------- */
777 @@ -3123,7 +3197,320 @@
778 CreateTraceLightsForBounds( mins, maxs, normal, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ], LIGHT_SURFACES, trace );
781 +/////////////////////////////////////////////////////////////
783 +#define FLOODLIGHT_CONE_ANGLE 88 /* degrees */
784 +#define FLOODLIGHT_NUM_ANGLE_STEPS 16
785 +#define FLOODLIGHT_NUM_ELEVATION_STEPS 4
786 +#define FLOODLIGHT_NUM_VECTORS (FLOODLIGHT_NUM_ANGLE_STEPS * FLOODLIGHT_NUM_ELEVATION_STEPS)
788 +static vec3_t floodVectors[ FLOODLIGHT_NUM_VECTORS ];
789 +static int numFloodVectors = 0;
791 +void SetupFloodLight( void )
794 + float angle, elevation, angleStep, elevationStep;
796 + double v1,v2,v3,v4,v5;
799 + Sys_FPrintf( SYS_VRB, "--- SetupFloodLight ---\n" );
801 + /* calculate angular steps */
802 + angleStep = DEG2RAD( 360.0f / FLOODLIGHT_NUM_ANGLE_STEPS );
803 + elevationStep = DEG2RAD( FLOODLIGHT_CONE_ANGLE / FLOODLIGHT_NUM_ELEVATION_STEPS );
805 + /* iterate angle */
807 + for( i = 0, angle = 0.0f; i < FLOODLIGHT_NUM_ANGLE_STEPS; i++, angle += angleStep )
809 + /* iterate elevation */
810 + for( j = 0, elevation = elevationStep * 0.5f; j < FLOODLIGHT_NUM_ELEVATION_STEPS; j++, elevation += elevationStep )
812 + floodVectors[ numFloodVectors ][ 0 ] = sin( elevation ) * cos( angle );
813 + floodVectors[ numFloodVectors ][ 1 ] = sin( elevation ) * sin( angle );
814 + floodVectors[ numFloodVectors ][ 2 ] = cos( elevation );
819 + /* emit some statistics */
820 + Sys_FPrintf( SYS_VRB, "%9d numFloodVectors\n", numFloodVectors );
823 + value = ValueForKey( &entities[ 0 ], "_floodlight" );
825 + if( value[ 0 ] != '\0' )
828 + v4=floodlightDistance;
829 + v5=floodlightIntensity;
831 + sscanf( value, "%lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5);
833 + floodlightRGB[0]=v1;
834 + floodlightRGB[1]=v2;
835 + floodlightRGB[2]=v3;
837 + if (VectorLength(floodlightRGB)==0)
839 + VectorSet(floodlightRGB,240,240,255);
845 + floodlightDistance=v4;
846 + floodlightIntensity=v5;
848 + floodlighty = qtrue;
849 + Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
853 + VectorSet(floodlightRGB,240,240,255);
854 + //floodlighty = qtrue;
855 + //Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
857 + VectorNormalize(floodlightRGB,floodlightRGB);
860 +//27 - lighttracer style ambient occlusion light hack.
861 +//Kudos to the dirtmapping author for most of this source.
862 +void FloodLightRawLightmap( int rawLightmapNum )
864 + int i, x, y, sx, sy, *cluster;
865 + float *origin, *normal, *floodlight, *floodlight2, average, samples;
867 + surfaceInfo_t *info;
870 + /* bail if this number exceeds the number of raw lightmaps */
871 + if( rawLightmapNum >= numRawLightmaps )
875 + lm = &rawLightmaps[ rawLightmapNum ];
877 + memset(&trace,0,sizeof(trace_t));
879 + trace.testOcclusion = qtrue;
880 + trace.forceSunlight = qfalse;
881 + trace.twoSided = qtrue;
882 + trace.recvShadows = lm->recvShadows;
883 + trace.numSurfaces = lm->numLightSurfaces;
884 + trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
885 + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
886 + trace.testAll = qfalse;
887 + trace.distance = 1024;
889 + /* twosided lighting (may or may not be a good idea for lightmapped stuff) */
890 + //trace.twoSided = qfalse;
891 + for( i = 0; i < trace.numSurfaces; i++ )
894 + info = &surfaceInfos[ trace.surfaces[ i ] ];
896 + /* check twosidedness */
897 + if( info->si->twoSided )
899 + trace.twoSided = qtrue;
905 + for( y = 0; y < lm->sh; y++ )
907 + for( x = 0; x < lm->sw; x++ )
910 + cluster = SUPER_CLUSTER( x, y );
911 + origin = SUPER_ORIGIN( x, y );
912 + normal = SUPER_NORMAL( x, y );
913 + floodlight = SUPER_FLOODLIGHT( x, y );
915 + /* set default dirt */
916 + *floodlight = 0.0f;
918 + /* only look at mapped luxels */
922 + /* copy to trace */
923 + trace.cluster = *cluster;
924 + VectorCopy( origin, trace.origin );
925 + VectorCopy( normal, trace.normal );
930 + *floodlight = FloodLightForSample( &trace );
934 + /* testing no filtering */
937 + /* filter "dirt" */
938 + for( y = 0; y < lm->sh; y++ )
940 + for( x = 0; x < lm->sw; x++ )
943 + cluster = SUPER_CLUSTER( x, y );
944 + floodlight = SUPER_FLOODLIGHT( x, y );
946 + /* filter dirt by adjacency to unmapped luxels */
947 + average = *floodlight;
949 + for( sy = (y - 1); sy <= (y + 1); sy++ )
951 + if( sy < 0 || sy >= lm->sh )
954 + for( sx = (x - 1); sx <= (x + 1); sx++ )
956 + if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
959 + /* get neighboring luxel */
960 + cluster = SUPER_CLUSTER( sx, sy );
961 + floodlight2 = SUPER_FLOODLIGHT( sx, sy );
962 + if( *cluster < 0 || *floodlight2 <= 0.0f )
966 + average += *floodlight2;
971 + if( samples <= 0.0f )
976 + if( samples <= 0.0f )
980 + *floodlight = average / samples;
986 +FloodLightForSample()
987 +calculates floodlight value for a given sample
988 +once again, kudos to the dirtmapping coder
990 +float FloodLightForSample( trace_t *trace )
994 + float contribution;
996 + float gatherLight, outLight;
997 + vec3_t normal, worldUp, myUp, myRt, direction, displacement;
1005 + if( trace == NULL || trace->cluster < 0 )
1010 + dd = floodlightDistance;
1011 + VectorCopy( trace->normal, normal );
1013 + /* check if the normal is aligned to the world-up */
1014 + if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f )
1016 + if( normal[ 2 ] == 1.0f )
1018 + VectorSet( myRt, 1.0f, 0.0f, 0.0f );
1019 + VectorSet( myUp, 0.0f, 1.0f, 0.0f );
1021 + else if( normal[ 2 ] == -1.0f )
1023 + VectorSet( myRt, -1.0f, 0.0f, 0.0f );
1024 + VectorSet( myUp, 0.0f, 1.0f, 0.0f );
1029 + VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
1030 + CrossProduct( normal, worldUp, myRt );
1031 + VectorNormalize( myRt, myRt );
1032 + CrossProduct( myRt, normal, myUp );
1033 + VectorNormalize( myUp, myUp );
1036 + /* iterate through ordered vectors */
1037 + for( i = 0; i < numFloodVectors; i++ )
1039 + if (floodlight_lowquality==qtrue)
1041 + if (rand()%10 != 0 ) continue;
1046 + /* transform vector into tangent space */
1047 + direction[ 0 ] = myRt[ 0 ] * floodVectors[ i ][ 0 ] + myUp[ 0 ] * floodVectors[ i ][ 1 ] + normal[ 0 ] * floodVectors[ i ][ 2 ];
1048 + direction[ 1 ] = myRt[ 1 ] * floodVectors[ i ][ 0 ] + myUp[ 1 ] * floodVectors[ i ][ 1 ] + normal[ 1 ] * floodVectors[ i ][ 2 ];
1049 + direction[ 2 ] = myRt[ 2 ] * floodVectors[ i ][ 0 ] + myUp[ 2 ] * floodVectors[ i ][ 1 ] + normal[ 2 ] * floodVectors[ i ][ 2 ];
1051 + /* set endpoint */
1052 + VectorMA( trace->origin, dd, direction, trace->end );
1054 + //VectorMA( trace->origin, 1, direction, trace->origin );
1056 + SetupTrace( trace );
1058 + TraceLine( trace );
1061 + if (trace->compileFlags & C_SKY )
1063 + contribution=1.0f;
1065 + else if ( trace->opaque )
1067 + VectorSubtract( trace->hit, trace->origin, displacement );
1068 + d=VectorLength( displacement );
1070 + // d=trace->distance;
1071 + //if (d>256) gatherDirt+=1;
1072 + contribution=d/dd;
1073 + if (contribution>1) contribution=1.0f;
1075 + //gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
1078 + gatherLight+=contribution;
1082 + if( gatherLight <= 0.0f )
1088 + gatherLight/=(sub);
1090 + outLight=gatherLight;
1091 + if( outLight > 1.0f )
1094 + /* return to sender */
1098 Index: tools/quake3/q3map2/light.c
1099 ===================================================================
1100 --- tools/quake3/q3map2/light.c (revision 290)
1101 +++ tools/quake3/q3map2/light.c (working copy)
1102 @@ -1363,6 +1363,56 @@
1106 + /////// Floodlighting for point //////////////////
1107 + //do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir
1113 + col[0]=col[1]=col[2]=floodlightIntensity;
1117 + trace.testOcclusion = qtrue;
1118 + trace.forceSunlight = qfalse;
1119 + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
1120 + trace.testAll = qtrue;
1124 + if (q==0) //upper hemisphere
1126 + trace.normal[0]=0;
1127 + trace.normal[1]=0;
1128 + trace.normal[2]=1;
1130 + else //lower hemisphere
1132 + trace.normal[0]=0;
1133 + trace.normal[1]=0;
1134 + trace.normal[2]=-1;
1137 + f = FloodLightForSample(&trace);
1139 + contributions[ numCon ].color[0]=col[0]*f;
1140 + contributions[ numCon ].color[1]=col[1]*f;
1141 + contributions[ numCon ].color[2]=col[2]*f;
1143 + contributions[ numCon ].dir[0]=dir[0];
1144 + contributions[ numCon ].dir[1]=dir[1];
1145 + contributions[ numCon ].dir[2]=dir[2];
1147 + contributions[ numCon ].style = 0;
1149 + /* push average direction around */
1150 + addSize = VectorLength( col );
1151 + VectorMA( gp->dir, addSize, dir, gp->dir );
1154 + /////////////////////
1156 /* normalize to get primary light direction */
1157 VectorNormalize( gp->dir, gp->dir );
1159 @@ -1544,6 +1594,12 @@
1160 qboolean minVertex, minGrid;
1163 + /* floodlight them up */
1166 + Sys_Printf( "--- FloodlightRawLightmap ---\n" );
1167 + RunThreadsOnIndividual( numRawLightmaps, qtrue, FloodLightRawLightmap );
1170 /* ydnar: smooth normals */
1172 @@ -1675,6 +1731,7 @@
1175 VectorClear( ambientColor );
1176 + floodlighty = qfalse;
1178 /* generate diffuse lights */
1180 @@ -2114,6 +2171,21 @@
1182 Sys_Printf( "Enabling low-memory (potentially slower) lighting mode\n" );
1184 + else if( !strcmp( argv[ i ], "-floodlight" ) )
1186 + floodlighty = qtrue;
1187 + Sys_Printf( "FloodLighting enabled\n" );
1189 + else if( !strcmp( argv[ i ], "-debugnormals" ) )
1191 + debugnormals = qtrue;
1192 + Sys_Printf( "DebugNormals enabled\n" );
1194 + else if( !strcmp( argv[ i ], "-lowquality" ) )
1196 + floodlight_lowquality = qtrue;
1197 + Sys_Printf( "Low Quality FloodLighting enabled\n" );
1201 Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
1202 @@ -2156,6 +2228,7 @@
1204 /* ydnar: set up optimization */
1206 + SetupFloodLight();
1207 SetupSurfaceLightmaps();
1209 /* initialize the surface facet tracing */
1210 Index: tools/quake3/q3map2/lightmaps_ydnar.c
1211 ===================================================================
1212 --- tools/quake3/q3map2/lightmaps_ydnar.c (revision 290)
1213 +++ tools/quake3/q3map2/lightmaps_ydnar.c (working copy)
1214 @@ -413,6 +413,12 @@
1215 lm->superNormals = safe_malloc( size );
1216 memset( lm->superNormals, 0, size );
1218 + /* allocate floodlight map storage */
1219 + size = lm->sw * lm->sh * SUPER_FLOODLIGHT_SIZE * sizeof( float );
1220 + if( lm->superFloodLight == NULL )
1221 + lm->superFloodLight = safe_malloc( size );
1222 + memset( lm->superFloodLight, 0, size );
1224 /* allocate cluster map storage */
1225 size = lm->sw * lm->sh * sizeof( int );
1226 if( lm->superClusters == NULL )
1227 Index: tools/quake3/q3map2/q3map2.h
1228 ===================================================================
1229 --- tools/quake3/q3map2/q3map2.h (revision 290)
1230 +++ tools/quake3/q3map2/q3map2.h (working copy)
1232 #define SUPER_NORMAL_SIZE 3
1233 #define SUPER_DELUXEL_SIZE 3
1234 #define BSP_DELUXEL_SIZE 3
1235 +#define SUPER_FLOODLIGHT_SIZE 1
1237 #define VERTEX_LUXEL( s, v ) (vertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
1238 #define RAD_VERTEX_LUXEL( s, v )(radVertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
1240 #define SUPER_LUXEL( s, x, y ) (lm->superLuxels[ s ] + ((((y) * lm->sw) + (x)) * SUPER_LUXEL_SIZE))
1241 #define SUPER_ORIGIN( x, y ) (lm->superOrigins + ((((y) * lm->sw) + (x)) * SUPER_ORIGIN_SIZE))
1242 #define SUPER_NORMAL( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE))
1243 +#define SUPER_FLOODLIGHT( x, y ) (lm->superFloodLight + ((((y) * lm->sw) + (x)) * SUPER_FLOODLIGHT_SIZE) )
1244 #define SUPER_CLUSTER( x, y ) (lm->superClusters + (((y) * lm->sw) + (x)))
1245 #define SUPER_DELUXEL( x, y ) (lm->superDeluxels + ((((y) * lm->sw) + (x)) * SUPER_DELUXEL_SIZE))
1246 #define BSP_DELUXEL( x, y ) (lm->bspDeluxels + ((((y) * lm->w) + (x)) * BSP_DELUXEL_SIZE))
1247 @@ -1364,6 +1366,7 @@
1249 float *superDeluxels; /* average light direction */
1251 + float *superFloodLight;
1255 @@ -1670,6 +1673,9 @@
1256 void SmoothNormals( void );
1258 void MapRawLightmap( int num );
1259 +void SetupFloodLight();
1260 +float FloodLightForSample( trace_t *trace );
1261 +void FloodLightRawLightmap( int num );
1262 void IlluminateRawLightmap( int num );
1263 void IlluminateVertexes( int num );
1265 @@ -2037,6 +2043,12 @@
1266 Q_EXTERN qboolean sunOnly;
1267 Q_EXTERN int approximateTolerance Q_ASSIGN( 0 );
1268 Q_EXTERN qboolean noCollapse;
1269 +Q_EXTERN qboolean debugnormals Q_ASSIGN( qfalse );
1270 +Q_EXTERN qboolean floodlighty Q_ASSIGN( qfalse );
1271 +Q_EXTERN qboolean floodlight_lowquality Q_ASSIGN( qfalse );
1272 +Q_EXTERN vec3_t floodlightRGB;
1273 +Q_EXTERN float floodlightIntensity Q_ASSIGN( 512 );
1274 +Q_EXTERN float floodlightDistance Q_ASSIGN( 1024 );
1275 Q_EXTERN qboolean debug;
1276 Q_EXTERN qboolean debugSurfaces;
1277 Q_EXTERN qboolean debugUnused;
1278 Index: tools/quake3/q3map2/q3map2.h
1279 ===================================================================
1280 --- tools/quake3/q3map2/q3map2.h (revision 290)
1281 +++ tools/quake3/q3map2/q3map2.h (working copy)
1282 @@ -1274,6 +1274,7 @@
1283 vec3_t color; /* starts out at full color, may be reduced if transparent surfaces are crossed */
1287 int compileFlags; /* for determining surface compile flags traced through */
1290 Index: tools/quake3/q3map2/light_trace.c
1291 ===================================================================
1292 --- tools/quake3/q3map2/light_trace.c (revision 290)
1293 +++ tools/quake3/q3map2/light_trace.c (working copy)
1294 @@ -1596,6 +1596,7 @@
1295 /* bogus node number means solid, end tracing unless testing all */
1298 + VectorCopy( origin, trace->hit );
1299 trace->passSolid = qtrue;
1302 @@ -1606,6 +1607,7 @@
1304 if( node->type == TRACE_LEAF_SOLID )
1306 + VectorCopy( origin, trace->hit );
1307 trace->passSolid = qtrue;
1310 Index: tools/quake3/q3map2/light_ydnar.c
1311 ===================================================================
1312 --- tools/quake3/q3map2/light_ydnar.c (revision 290)
1313 +++ tools/quake3/q3map2/light_ydnar.c (working copy)
1316 #define BOGUS_NUDGE -99999.0f
1318 -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 ] )
1319 +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 ] )
1321 int i, x, y, numClusters, *clusters, pointCluster, *cluster;
1322 float *luxel, *origin, *normal, d, lightmapSampleOffset;
1323 @@ -380,6 +380,12 @@
1327 + vec3_t cverts[ 3 ];
1329 + vec4_t sideplane, hostplane;
1334 static float nudges[][ 2 ] =
1336 @@ -473,6 +479,51 @@
1337 /* non axial lightmap projection (explicit xyz) */
1339 VectorCopy( dv->xyz, origin );
1341 + //////////////////////
1342 + //27's test to make sure samples stay within the triangle boundaries
1343 + //1) Test the sample origin to see if it lays on the wrong side of any edge (x/y)
1344 + //2) if it does, nudge it onto the correct side.
1346 + if (worldverts!=NULL)
1350 + VectorCopy(worldverts[j],cverts[j]);
1352 + PlaneFromPoints(hostplane,cverts[0],cverts[1],cverts[2]);
1358 + //build plane using 2 edges and a normal
1361 + VectorCopy(cverts[next],temp);
1362 + VectorAdd(temp,hostplane,temp);
1363 + PlaneFromPoints(sideplane,cverts[i],cverts[ next ], temp);
1365 + //planetest sample point
1366 + e=DotProduct(origin,sideplane);
1371 + //VectorClear(origin);
1372 + //Move the sample point back inside triangle bounds
1373 + origin[0]-=sideplane[0]*(e+1);
1374 + origin[1]-=sideplane[1]*(e+1);
1375 + origin[2]-=sideplane[2]*(e+1);
1377 + VectorClear(origin);
1384 + ////////////////////////
1386 /* planar surfaces have precalculated lightmap vectors for nudging */
1387 if( lm->plane != NULL )
1388 @@ -504,8 +555,13 @@
1390 origin[ lm->axisNum ] += lightmapSampleOffset;
1392 + VectorCopy(origin,origintwo);
1393 + origintwo[0]+=vecs[2][0];
1394 + origintwo[1]+=vecs[2][1];
1395 + origintwo[2]+=vecs[2][2];
1398 - pointCluster = ClusterForPointExtFilter( origin, LUXEL_EPSILON, numClusters, clusters );
1399 + pointCluster = ClusterForPointExtFilter( origintwo, LUXEL_EPSILON, numClusters, clusters );
1401 /* another retarded hack, storing nudge count in luxel[ 1 ] */
1403 @@ -521,14 +577,14 @@
1404 for( i = 0; i < 3; i++ )
1406 /* set nudged point*/
1407 - nudged[ i ] = origin[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
1408 + nudged[ i ] = origintwo[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
1412 /* get pvs cluster */
1413 pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters ); //% + 0.625 );
1414 - if( pointCluster >= 0 )
1415 - VectorCopy( nudged, origin );
1416 + //if( pointCluster >= 0 )
1417 + // VectorCopy( nudged, origin );
1423 VectorMA( dv->xyz, lightmapSampleOffset, dv->normal, nudged );
1424 pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters );
1425 - if( pointCluster >= 0 )
1426 - VectorCopy( nudged, origin );
1427 + //if( pointCluster >= 0 )
1428 + // VectorCopy( nudged, origin );
1433 than the distance between two luxels (thanks jc :)
1436 -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 ] )
1437 +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 ] )
1439 bspDrawVert_t mid, *dv2[ 3 ];
1443 /* split the longest edge and map it */
1444 LerpDrawVert( dv[ max ], dv[ (max + 1) % 3 ], &mid );
1445 - MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv );
1446 + MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv, worldverts );
1448 /* push the point up a little bit to account for fp creep (fixme: revisit this) */
1449 //% VectorMA( mid.xyz, 2.0f, mid.normal, mid.xyz );
1450 @@ -641,12 +697,12 @@
1451 /* recurse to first triangle */
1452 VectorCopy( dv, dv2 );
1454 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
1455 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
1457 /* recurse to second triangle */
1458 VectorCopy( dv, dv2 );
1459 dv2[ (max + 1) % 3 ] = ∣
1460 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
1461 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
1468 vec3_t *stv, *ttv, stvStatic[ 3 ], ttvStatic[ 3 ];
1469 + vec3_t worldverts[ 3 ];
1472 /* get plane if possible */
1473 @@ -687,16 +744,20 @@
1477 + VectorCopy( dv[ 0 ]->xyz, worldverts[ 0 ] );
1478 + VectorCopy( dv[ 1 ]->xyz, worldverts[ 1 ] );
1479 + VectorCopy( dv[ 2 ]->xyz, worldverts[ 2 ] );
1481 /* map the vertexes */
1482 - MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
1483 - MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
1484 - MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
1485 + MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, worldverts );
1486 + MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, worldverts );
1487 + MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, worldverts );
1489 /* 2002-11-20: prefer axial triangle edges */
1492 /* subdivide the triangle */
1493 - MapTriangle_r( lm, info, dv, plane, stv, ttv );
1494 + MapTriangle_r( lm, info, dv, plane, stv, ttv, worldverts );
1499 dv2[ 2 ] = dv[ (i + 1) % 3 ];
1501 /* map the degenerate triangle */
1502 - MapTriangle_r( lm, info, dv2, plane, stv, ttv );
1503 + MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
1508 LerpDrawVert( dv[ max + 2 ], dv[ (max + 3) % 4 ], &mid[ 1 ] );
1510 /* map the vertexes */
1511 - MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv );
1512 - MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv );
1513 + MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv, NULL );
1514 + MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv, NULL );
1518 @@ -866,10 +927,10 @@
1521 /* map the vertexes */
1522 - MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
1523 - MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
1524 - MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
1525 - MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv );
1526 + MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, NULL );
1527 + MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, NULL );
1528 + MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, NULL );
1529 + MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv, NULL );
1531 /* subdivide the quad */
1532 MapQuad_r( lm, info, dv, plane, stv, ttv );
1533 @@ -1161,7 +1222,7 @@
1536 /* map the fake vert */
1537 - MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL );
1538 + MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL, NULL );
1542 @@ -1636,22 +1697,32 @@
1543 deluxel = SUPER_DELUXEL( x, y );
1544 origin = SUPER_ORIGIN( x, y );
1545 normal = SUPER_NORMAL( x, y );
1547 - /* set contribution count */
1548 - lightLuxel[ 3 ] = 1.0f;
1551 - trace.cluster = *cluster;
1552 - VectorCopy( origin, trace.origin );
1553 - VectorCopy( normal, trace.normal );
1555 - /* get light for this sample */
1556 - LightContributionToSample( &trace );
1557 - VectorCopy( trace.color, lightLuxel );
1559 - /* add to count */
1560 - if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
1562 + ////////// 27's temp hack for testing edge clipping ////
1563 + if( origin[0]==0 && origin[1]==0 && origin[2]==0 )
1565 + lightLuxel[ 1 ] = 255;
1566 + lightLuxel[ 3 ] = 1.0f;
1571 + /* set contribution count */
1572 + lightLuxel[ 3 ] = 1.0f;
1575 + trace.cluster = *cluster;
1576 + VectorCopy( origin, trace.origin );
1577 + VectorCopy( normal, trace.normal );
1579 + /* get light for this sample */
1580 + LightContributionToSample( &trace );
1581 + VectorCopy( trace.color, lightLuxel );
1583 + /* add to count */
1584 + if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
1588 /* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
1590 Index: tools/quake3/q3map2/q3map2.h
1591 ===================================================================
1592 --- tools/quake3/q3map2/q3map2.h (revision 290)
1593 +++ tools/quake3/q3map2/q3map2.h (working copy)
1598 -#define Q3MAP_VERSION "2.5.11"
1599 -#define Q3MAP_MOTD "A well-oiled toaster oven"
1600 +#define Q3MAP_VERSION "2.5.11-div0-obj-decomptexcoords-snapplane-UTavgcolorfix-UTfloodlight-UTtrianglecheck"
1601 +#define Q3MAP_MOTD "Blackhole Box gives the light back"
1605 Index: include/version.default
1606 ===================================================================
1607 --- include/version.default (revision 290)
1608 +++ include/version.default (working copy)