]> icculus.org git repositories - divverent/nexuiz.git/blob - misc/gtkradiant/singlepatches/q3map2-decomptexcoords.diff
add the ACBC Assault Circuit Board Creator
[divverent/nexuiz.git] / misc / gtkradiant / singlepatches / q3map2-decomptexcoords.diff
1 Index: tools/quake3/q3map2/convert_map.c
2 ===================================================================
3 --- tools/quake3/q3map2/convert_map.c.orig      2008-09-06 15:32:05.000000000 +0200
4 +++ tools/quake3/q3map2/convert_map.c   2008-09-06 15:32:11.000000000 +0200
5 @@ -46,6 +46,105 @@
6  #define        SNAP_FLOAT_TO_INT       4
7  #define        SNAP_INT_TO_FLOAT       (1.0 / SNAP_FLOAT_TO_INT)
8  
9 +typedef vec_t vec2_t[2];
10 +
11 +static vec_t Det3x3(vec_t a00, vec_t a01, vec_t a02,
12 +                    vec_t a10, vec_t a11, vec_t a12,
13 +                    vec_t a20, vec_t a21, vec_t a22)
14 +{
15 +       return
16 +               a00 * (a11 * a22 - a12 * a21)
17 +       -       a01 * (a10 * a22 - a12 * a20)
18 +       +       a02 * (a10 * a21 - a11 * a20);
19 +}
20 +
21 +void GetBestSurfaceTriangleMatchForBrushside(side_t *buildSide, bspDrawVert_t *bestVert[3])
22 +{
23 +       bspDrawSurface_t *s;
24 +       int i;
25 +       int t;
26 +       vec_t best = 0;
27 +       vec_t thisarea;
28 +       vec3_t normdiff;
29 +       vec3_t v1v0, v2v0, norm;
30 +       bspDrawVert_t *vert[3];
31 +       winding_t *polygon;
32 +       plane_t *buildPlane = &mapplanes[buildSide->planenum];
33 +       int matches = 0;
34 +
35 +       // first, start out with NULLs
36 +       bestVert[0] = bestVert[1] = bestVert[2] = NULL;
37 +
38 +       // brute force through all surfaces
39 +       for(s = bspDrawSurfaces; s != bspDrawSurfaces + numBSPDrawSurfaces; ++s)
40 +       {
41 +               if(s->surfaceType != MST_PLANAR && s->surfaceType != MST_TRIANGLE_SOUP)
42 +                       continue;
43 +               if(strcmp(buildSide->shaderInfo->shader, bspShaders[s->shaderNum].shader))
44 +                       continue;
45 +               for(t = 0; t + 3 <= s->numIndexes; t += 3)
46 +               {
47 +                       vert[0] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 0]];
48 +                       vert[1] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 1]];
49 +                       vert[2] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 2]];
50 +                       if(s->surfaceType == MST_PLANAR)
51 +                       {
52 +                               VectorSubtract(vert[0]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
53 +                               VectorSubtract(vert[1]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
54 +                               VectorSubtract(vert[2]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
55 +                       }
56 +                       else
57 +                       {
58 +                               // this is more prone to roundoff errors, but with embedded
59 +                               // models, there is no better way
60 +                               VectorSubtract(vert[1]->xyz, vert[0]->xyz, v1v0);
61 +                               VectorSubtract(vert[2]->xyz, vert[0]->xyz, v2v0);
62 +                               CrossProduct(v2v0, v1v0, norm);
63 +                               VectorNormalize(norm, norm);
64 +                               VectorSubtract(norm, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
65 +                       }
66 +                       if(abs(DotProduct(vert[0]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
67 +                       if(abs(DotProduct(vert[1]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
68 +                       if(abs(DotProduct(vert[2]->xyz, buildPlane->normal) - buildPlane->dist) >= distanceEpsilon) continue;
69 +                       // Okay. Correct surface type, correct shader, correct plane. Let's start with the business...
70 +                       polygon = CopyWinding(buildSide->winding);
71 +                       for(i = 0; i < 3; ++i)
72 +                       {
73 +                               // 0: 1, 2
74 +                               // 1: 2, 0
75 +                               // 2; 0, 1
76 +                               vec3_t *v1 = &vert[(i+1)%3]->xyz;
77 +                               vec3_t *v2 = &vert[(i+2)%3]->xyz;
78 +                               vec3_t triNormal;
79 +                               vec_t triDist;
80 +                               vec3_t sideDirection;
81 +                               // we now need to generate triNormal and triDist so that they represent the plane spanned by normal and (v2 - v1).
82 +                               VectorSubtract(*v2, *v1, sideDirection);
83 +                               CrossProduct(sideDirection, buildPlane->normal, triNormal);
84 +                               triDist = DotProduct(*v1, triNormal);
85 +                               ChopWindingInPlace(&polygon, triNormal, triDist, distanceEpsilon);
86 +                               if(!polygon)
87 +                                       goto exwinding;
88 +                       }
89 +                       thisarea = WindingArea(polygon);
90 +                       if(thisarea > 0)
91 +                               ++matches;
92 +                       if(thisarea > best)
93 +                       {
94 +                               best = thisarea;
95 +                               bestVert[0] = vert[0];
96 +                               bestVert[1] = vert[1];
97 +                               bestVert[2] = vert[2];
98 +                       }
99 +                       FreeWinding(polygon);
100 +exwinding:
101 +                       ;
102 +               }
103 +       }
104 +       //if(strncmp(buildSide->shaderInfo->shader, "textures/common/", 16))
105 +       //      fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide->shaderInfo->shader, matches, best);
106 +}
107 +
108  static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
109  {
110         int                             i, j;
111 @@ -54,12 +153,17 @@
112         bspShader_t             *shader;
113         char                    *texture;
114         bspPlane_t              *plane;
115 +       plane_t         *buildPlane;
116         vec3_t                  pts[ 3 ];
117 +       bspDrawVert_t   *vert[3];
118 +       int valid;
119         
120         
121         /* start brush */
122         fprintf( f, "\t// brush %d\n", num );
123         fprintf( f, "\t{\n" );
124 +       fprintf( f, "\tbrushDef\n" );
125 +       fprintf( f, "\t{\n" );
126         
127         /* clear out build brush */
128         for( i = 0; i < buildBrush->numsides; i++ )
129 @@ -109,9 +213,88 @@
130                 /* get build side */
131                 buildSide = &buildBrush->sides[ i ];
132                 
133 +               /* get plane */
134 +               buildPlane = &mapplanes[ buildSide->planenum ];
135 +
136                 /* dummy check */
137                 if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
138                         continue;
139 +
140 +               // st-texcoords -> texMat block
141 +               // start out with dummy
142 +               VectorSet(buildSide->texMat[0], 1/32.0, 0, 0);
143 +               VectorSet(buildSide->texMat[1], 0, 1/32.0, 0);
144 +
145 +               // find surface for this side (by brute force)
146 +               // surface format:
147 +               //   - meshverts point in pairs of three into verts
148 +               //   - (triangles)
149 +               //   - find the triangle that has most in common with our side
150 +               GetBestSurfaceTriangleMatchForBrushside(buildSide, vert);
151 +               valid = 0;
152 +
153 +               if(vert[0] && vert[1] && vert[2])
154 +               {
155 +                       int i;
156 +                       vec3_t texX, texY;
157 +                       vec3_t xy1I, xy1J, xy1K;
158 +                       vec2_t stI, stJ, stK;
159 +                       vec_t D, D0, D1, D2;
160 +
161 +                       ComputeAxisBase(buildPlane->normal, texX, texY);
162 +
163 +                       VectorSet(xy1I, DotProduct(vert[0]->xyz, texX), DotProduct(vert[0]->xyz, texY), 1);
164 +                       VectorSet(xy1J, DotProduct(vert[1]->xyz, texX), DotProduct(vert[1]->xyz, texY), 1);
165 +                       VectorSet(xy1K, DotProduct(vert[2]->xyz, texX), DotProduct(vert[2]->xyz, texY), 1);
166 +                       stI[0] = vert[0]->st[0]; stI[1] = vert[0]->st[1];
167 +                       stJ[0] = vert[1]->st[0]; stJ[1] = vert[1]->st[1];
168 +                       stK[0] = vert[2]->st[0]; stK[1] = vert[2]->st[1];
169 +
170 +                       //   - solve linear equations:
171 +                       //     - (x, y) := xyz . (texX, texY)
172 +                       //     - st[i] = texMat[i][0]*x + texMat[i][1]*y + texMat[i][2]
173 +                       //       (for three vertices)
174 +                       D = Det3x3(
175 +                               xy1I[0], xy1I[1], 1,
176 +                               xy1J[0], xy1J[1], 1,
177 +                               xy1K[0], xy1K[1], 1
178 +                       );
179 +                       if(D != 0)
180 +                       {
181 +                               for(i = 0; i < 2; ++i)
182 +                               {
183 +                                       D0 = Det3x3(
184 +                                               stI[i], xy1I[1], 1,
185 +                                               stJ[i], xy1J[1], 1,
186 +                                               stK[i], xy1K[1], 1
187 +                                       );
188 +                                       D1 = Det3x3(
189 +                                               xy1I[0], stI[i], 1,
190 +                                               xy1J[0], stJ[i], 1,
191 +                                               xy1K[0], stK[i], 1
192 +                                       );
193 +                                       D2 = Det3x3(
194 +                                               xy1I[0], xy1I[1], stI[i],
195 +                                               xy1J[0], xy1J[1], stJ[i],
196 +                                               xy1K[0], xy1K[1], stK[i]
197 +                                       );
198 +                                       VectorSet(buildSide->texMat[i], D0 / D, D1 / D, D2 / D);
199 +                                       valid = 1;
200 +                               }
201 +                       }
202 +                       else
203 +                               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",
204 +                                       buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2],
205 +                                       vert[0]->normal[0], vert[0]->normal[1], vert[0]->normal[2],
206 +                                       texX[0], texX[1], texX[2], texY[0], texY[1], texY[2],
207 +                                       vert[0]->xyz[0], vert[0]->xyz[1], vert[0]->xyz[2], xy1I[0], xy1I[1],
208 +                                       vert[1]->xyz[0], vert[1]->xyz[1], vert[1]->xyz[2], xy1J[0], xy1J[1],
209 +                                       vert[2]->xyz[0], vert[2]->xyz[1], vert[2]->xyz[2], xy1K[0], xy1K[1]
210 +                                       );
211 +               }
212 +               else
213 +                       if(strncmp(buildSide->shaderInfo->shader, "textures/common/", 16))
214 +                               fprintf(stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide->shaderInfo->shader);
215                 
216                 /* get texture name */
217                 if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
218 @@ -130,14 +313,21 @@
219                 
220                 /* print brush side */
221                 /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
222 -               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",
223 +               fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( ( %.8f %.8f %.8f ) ( %.8f %.8f %.8f ) ) %s %d 0 0\n",
224                         pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
225                         pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
226                         pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
227 -                       texture );
228 +                       buildSide->texMat[0][0], buildSide->texMat[0][1], buildSide->texMat[0][2],
229 +                       buildSide->texMat[1][0], buildSide->texMat[1][1], buildSide->texMat[1][2],
230 +                       texture,
231 +                       // DEBUG: valid ? 0 : C_DETAIL
232 +                       0
233 +                       );
234 +               // TODO write brush primitives format here
235         }
236         
237         /* end brush */
238 +       fprintf( f, "\t}\n" );
239         fprintf( f, "\t}\n\n" );
240  }
241  
242 Index: tools/quake3/q3map2/main.c
243 ===================================================================
244 --- tools/quake3/q3map2/main.c.orig     2008-09-06 15:32:05.000000000 +0200
245 +++ tools/quake3/q3map2/main.c  2008-09-06 15:32:11.000000000 +0200
246 @@ -541,6 +541,18 @@
247                                         Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
248                         }
249                 }
250 +               else if( !strcmp( argv[ i ],  "-ne" ) )
251 +               {
252 +                       normalEpsilon = atof( argv[ i + 1 ] );
253 +                       i++;
254 +                       Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
255 +               }
256 +               else if( !strcmp( argv[ i ],  "-de" ) )
257 +               {
258 +                       distanceEpsilon = atof( argv[ i + 1 ] );
259 +                       i++;
260 +                       Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
261 +               }
262         }
263         
264         /* clean up map name */