]> icculus.org git repositories - divverent/nexuiz.git/blob - misc/gtkradiant/singlepatches/q3map2-snapplane.diff
add GtkRadiant patch set
[divverent/nexuiz.git] / misc / gtkradiant / singlepatches / q3map2-snapplane.diff
1 Index: tools/quake3/q3map2/model.c
2 ===================================================================
3 --- tools/quake3/q3map2/model.c (revision 193)
4 +++ tools/quake3/q3map2/model.c (working copy)
5 @@ -222,6 +222,8 @@
6         byte                            *color;
7         picoIndex_t                     *indexes;
8         remap_t                         *rm, *glob;
9 +       double                          normalEpsilon_save;
10 +       double                          distanceEpsilon_save;
11         
12         
13         /* get model */
14 @@ -398,9 +400,8 @@
15                 /* ydnar: giant hack land: generate clipping brushes for model triangles */
16                 if( si->clipModel || (spawnFlags & 2) ) /* 2nd bit */
17                 {
18 -                       vec3_t          points[ 3 ], backs[ 3 ];
19 +                       vec3_t          points[ 4 ], backs[ 3 ];
20                         vec4_t          plane, reverse, pa, pb, pc;
21 -                       vec3_t          nadir;
22                         
23                         
24                         /* temp hack */
25 @@ -437,90 +438,141 @@
26                                         /* note: this doesn't work as well as simply using the plane of the triangle, below */
27                                         for( k = 0; k < 3; k++ )
28                                         {
29 -                                               if( fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 1) % 3 ] ) &&
30 -                                                       fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 2) % 3 ] ) )
31 +                                               if( fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 1) % 3 ] ) &&
32 +                                                       fabs( dv->normal[ k ] ) >= fabs( dv->normal[ (k + 2) % 3 ] ) )
33                                                 {
34                                                         backs[ j ][ k ] += dv->normal[ k ] < 0.0f ? 64.0f : -64.0f;
35                                                         break;
36                                                 }
37                                         }
38                                 }
39 +
40 +                               VectorCopy( points[0], points[3] ); // for cyclic usage
41                                 
42                                 /* make plane for triangle */
43 +                               // div0: add some extra spawnflags:
44 +                               //   0: snap normals to axial planes for extrusion
45 +                               //   8: extrude with the original normals
46 +                               //  16: extrude only with up/down normals (ideal for terrain)
47 +                               //  24: extrude by distance zero (may need engine changes)
48                                 if( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) )
49                                 {
50 +                                       vec3_t bestNormal;
51 +                                       float backPlaneDistance = 2;
52 +
53 +                                       if(spawnFlags & 8) // use a DOWN normal
54 +                                       {
55 +                                               if(spawnFlags & 16)
56 +                                               {
57 +                                                       // 24: normal as is, and zero width (broken)
58 +                                                       VectorCopy(plane, bestNormal);
59 +                                               }
60 +                                               else
61 +                                               {
62 +                                                       // 8: normal as is
63 +                                                       VectorCopy(plane, bestNormal);
64 +                                               }
65 +                                       }
66 +                                       else
67 +                                       {
68 +                                               if(spawnFlags & 16)
69 +                                               {
70 +                                                       // 16: UP/DOWN normal
71 +                                                       VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
72 +                                               }
73 +                                               else
74 +                                               {
75 +                                                       // 0: axial normal
76 +                                                       if(fabs(plane[0]) > fabs(plane[1])) // x>y
77 +                                                               if(fabs(plane[1]) > fabs(plane[2])) // x>y, y>z
78 +                                                                       VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
79 +                                                               else // x>y, z>=y
80 +                                                                       if(fabs(plane[0]) > fabs(plane[2])) // x>z, z>=y
81 +                                                                               VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
82 +                                                                       else // z>=x, x>y
83 +                                                                               VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
84 +                                                       else // y>=x
85 +                                                               if(fabs(plane[1]) > fabs(plane[2])) // y>z, y>=x
86 +                                                                       VectorSet(bestNormal, 0, (plane[1] >= 0 ? 1 : -1), 0);
87 +                                                               else // z>=y, y>=x
88 +                                                                       VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
89 +                                               }
90 +                                       }
91 +
92 +                                       /* build a brush */
93 +                                       buildBrush = AllocBrush( 48 );
94 +                                       buildBrush->entityNum = mapEntityNum;
95 +                                       buildBrush->original = buildBrush;
96 +                                       buildBrush->contentShader = si;
97 +                                       buildBrush->compileFlags = si->compileFlags;
98 +                                       buildBrush->contentFlags = si->contentFlags;
99 +                                       normalEpsilon_save = normalEpsilon;
100 +                                       distanceEpsilon_save = distanceEpsilon;
101 +                                       if(si->compileFlags & C_STRUCTURAL) // allow forced structural brushes here
102 +                                       {
103 +                                               buildBrush->detail = qfalse;
104 +
105 +                                               // only allow EXACT matches when snapping for these (this is mostly for caulk brushes inside a model)
106 +                                               if(normalEpsilon > 0)
107 +                                                       normalEpsilon = 0;
108 +                                               if(distanceEpsilon > 0)
109 +                                                       distanceEpsilon = 0;
110 +                                       }
111 +                                       else
112 +                                               buildBrush->detail = qtrue;
113 +
114                                         /* regenerate back points */
115                                         for( j = 0; j < 3; j++ )
116                                         {
117                                                 /* get vertex */
118                                                 dv = &ds->verts[ ds->indexes[ i + j ] ];
119 -                                               
120 -                                               /* copy xyz */
121 -                                               VectorCopy( dv->xyz, backs[ j ] );
122 -                                               
123 -                                               /* find nearest axial to plane normal and push back points opposite */
124 -                                               for( k = 0; k < 3; k++ )
125 -                                               {
126 -                                                       if( fabs( plane[ k ] ) > fabs( plane[ (k + 1) % 3 ] ) &&
127 -                                                               fabs( plane[ k ] ) > fabs( plane[ (k + 2) % 3 ] ) )
128 -                                                       {
129 -                                                               backs[ j ][ k ] += plane[ k ] < 0.0f ? 64.0f : -64.0f;
130 -                                                               break;
131 -                                                       }
132 -                                               }
133 +
134 +                                               // shift by some units
135 +                                               VectorMA(dv->xyz, -64.0f, bestNormal, backs[j]); // 64 prevents roundoff errors a bit
136                                         }
137 -                                       
138 +
139                                         /* make back plane */
140                                         VectorScale( plane, -1.0f, reverse );
141 -                                       reverse[ 3 ] = -(plane[ 3 ] - 1);
142 -                                       
143 -                                       /* make back pyramid point */
144 -                                       VectorCopy( points[ 0 ], nadir );
145 -                                       VectorAdd( nadir, points[ 1 ], nadir );
146 -                                       VectorAdd( nadir, points[ 2 ], nadir );
147 -                                       VectorScale( nadir, 0.3333333333333f, nadir );
148 -                                       VectorMA( nadir, -2.0f, plane, nadir );
149 -                                       
150 -                                       /* make 3 more planes */
151 -                                       //%     if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], nadir ) &&
152 -                                       //%             PlaneFromPoints( pb, points[ 1 ], points[ 0 ], nadir ) &&
153 -                                       //%             PlaneFromPoints( pc, points[ 0 ], points[ 2 ], nadir ) )
154 +                                       reverse[ 3 ] = -plane[ 3 ];
155 +                                       if((spawnFlags & 24) != 24)
156 +                                               reverse[3] += DotProduct(bestNormal, plane) * backPlaneDistance;
157 +                                       // 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)
158 +
159                                         if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], backs[ 1 ] ) &&
160 -                                               PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
161 -                                               PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
162 +                                                       PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
163 +                                                       PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
164                                         {
165 -                                               /* build a brush */
166 -                                               buildBrush = AllocBrush( 48 );
167 -                                               
168 -                                               buildBrush->entityNum = mapEntityNum;
169 -                                               buildBrush->original = buildBrush;
170 -                                               buildBrush->contentShader = si;
171 -                                               buildBrush->compileFlags = si->compileFlags;
172 -                                               buildBrush->contentFlags = si->contentFlags;
173 -                                               buildBrush->detail = qtrue;
174 -                                               
175                                                 /* set up brush sides */
176                                                 buildBrush->numsides = 5;
177                                                 for( j = 0; j < buildBrush->numsides; j++ )
178                                                         buildBrush->sides[ j ].shaderInfo = si;
179 +
180                                                 buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
181 -                                               buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 1, &points[ 2 ] );
182 -                                               buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 1, &points[ 1 ] );
183 -                                               buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 1, &points[ 0 ] );
184 -                                               buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, points );
185 -                                               
186 -                                               /* add to entity */
187 -                                               if( CreateBrushWindings( buildBrush ) )
188 -                                               {
189 -                                                       AddBrushBevels();
190 -                                                       //%     EmitBrushes( buildBrush, NULL, NULL );
191 -                                                       buildBrush->next = entities[ mapEntityNum ].brushes;
192 -                                                       entities[ mapEntityNum ].brushes = buildBrush;
193 -                                                       entities[ mapEntityNum ].numBrushes++;
194 -                                               }
195 -                                               else
196 -                                                       free( buildBrush );
197 +                                               buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 2, &points[ 1 ] ); // pa contains points[1] and points[2]
198 +                                               buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 2, &points[ 0 ] ); // pb contains points[0] and points[1]
199 +                                               buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 2, &points[ 2 ] ); // pc contains points[2] and points[0] (copied to points[3]
200 +                                               buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, backs );
201                                         }
202 +                                       else
203 +                                       {
204 +                                               free(buildBrush);
205 +                                               continue;
206 +                                       }
207 +
208 +                                       normalEpsilon = normalEpsilon_save;
209 +                                       distanceEpsilon = distanceEpsilon_save;
210 +
211 +                                       /* add to entity */
212 +                                       if( CreateBrushWindings( buildBrush ) )
213 +                                       {
214 +                                               AddBrushBevels();
215 +                                               //%     EmitBrushes( buildBrush, NULL, NULL );
216 +                                               buildBrush->next = entities[ mapEntityNum ].brushes;
217 +                                               entities[ mapEntityNum ].brushes = buildBrush;
218 +                                               entities[ mapEntityNum ].numBrushes++;
219 +                                       }
220 +                                       else
221 +                                               free( buildBrush );
222                                 }
223                         }
224                 }
225 Index: tools/quake3/q3map2/map.c
226 ===================================================================
227 --- tools/quake3/q3map2/map.c   (revision 193)
228 +++ tools/quake3/q3map2/map.c   (working copy)
229 @@ -184,7 +184,7 @@
230  snaps a plane to normal/distance epsilons
231  */
232  
233 -void SnapPlane( vec3_t normal, vec_t *dist )
234 +void SnapPlane( vec3_t normal, vec_t *dist, vec3_t center )
235  {
236  // SnapPlane disabled by LordHavoc because it often messes up collision
237  // brushes made from triangles of embedded models, and it has little effect
238 @@ -193,7 +193,13 @@
239    SnapPlane reenabled by namespace because of multiple reports of
240    q3map2-crashes which were triggered by this patch.
241  */
242 +       // div0: ensure the point "center" stays on the plane (actually, this
243 +       // rotates the plane around the point center).
244 +       // if center lies on the plane, it is guaranteed to stay on the plane by
245 +       // this fix.
246 +       vec_t centerDist = DotProduct(normal, center);
247         SnapNormal( normal );
248 +       *dist += (DotProduct(normal, center) - centerDist);
249  
250         if( fabs( *dist - Q_rint( *dist ) ) < distanceEpsilon )
251                 *dist = Q_rint( *dist );
252 @@ -207,7 +213,7 @@
253  must be within an epsilon distance of the plane
254  */
255  
256 -int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points )
257 +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?
258  
259  #ifdef USE_HASHING
260  
261 @@ -215,10 +221,14 @@
262         int             i, j, hash, h;
263         plane_t *p;
264         vec_t   d;
265 +       vec3_t centerofweight;
266 +
267 +       VectorClear(centerofweight);
268 +       for(i = 0; i < numPoints; ++i)
269 +               VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
270         
271 -       
272         /* hash the plane */
273 -       SnapPlane( normal, &dist );
274 +       SnapPlane( normal, &dist, centerofweight );
275         hash = (PLANE_HASHES - 1) & (int) fabs( dist );
276         
277         /* search the border bins as well */
278 @@ -259,7 +269,13 @@
279         plane_t *p;
280         
281  
282 -       SnapPlane( normal, &dist );
283 +       vec3_t centerofweight;
284 +
285 +       VectorClear(centerofweight);
286 +       for(i = 0; i < numPoints; ++i)
287 +               VectorMA(centerofweight, 1.0 / numPoints, points[i], centerofweight);
288 +       
289 +       SnapPlane( normal, &dist, centerofweight );
290         for( i = 0, p = mapplanes; i < nummapplanes; i++, p++ )
291         {
292                 if( PlaneEqual( p, normal, dist ) )