1 Index: tools/quake3/q3map2/convert_map.c
2 ===================================================================
3 --- tools/quake3/q3map2/convert_map.c (revision 191)
4 +++ tools/quake3/q3map2/convert_map.c (working copy)
6 #define SNAP_FLOAT_TO_INT 4
7 #define SNAP_INT_TO_FLOAT (1.0 / SNAP_FLOAT_TO_INT)
9 +typedef vec_t vec2_t[2];
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)
16 + a00 * (a11 * a22 - a12 * a21)
17 + - a01 * (a10 * a22 - a12 * a20)
18 + + a02 * (a10 * a21 - a11 * a20);
21 +void GetBestSurfaceTriangleMatchForBrushside(side_t *buildSide, bspDrawVert_t *bestVert[3])
23 + bspDrawSurface_t *s;
29 + vec3_t v1v0, v2v0, norm;
30 + bspDrawVert_t *vert[3];
32 + plane_t *buildPlane = &mapplanes[buildSide->planenum];
35 + // first, start out with NULLs
36 + bestVert[0] = bestVert[1] = bestVert[2] = NULL;
38 + // brute force through all surfaces
39 + for(s = bspDrawSurfaces; s != bspDrawSurfaces + numBSPDrawSurfaces; ++s)
41 + if(s->surfaceType != MST_PLANAR && s->surfaceType != MST_TRIANGLE_SOUP)
43 + if(strcmp(buildSide->shaderInfo->shader, bspShaders[s->shaderNum].shader))
45 + for(t = 0; t + 3 <= s->numIndexes; t += 3)
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)
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;
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;
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)
76 + vec3_t *v1 = &vert[(i+1)%3]->xyz;
77 + vec3_t *v2 = &vert[(i+2)%3]->xyz;
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);
89 + thisarea = WindingArea(polygon);
95 + bestVert[0] = vert[0];
96 + bestVert[1] = vert[1];
97 + bestVert[2] = vert[2];
99 + FreeWinding(polygon);
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);
108 static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
115 + plane_t *buildPlane;
117 + bspDrawVert_t *vert[3];
122 fprintf( f, "\t// brush %d\n", num );
123 fprintf( f, "\t{\n" );
124 + fprintf( f, "\tbrushDef\n" );
125 + fprintf( f, "\t{\n" );
127 /* clear out build brush */
128 for( i = 0; i < buildBrush->numsides; i++ )
131 buildSide = &buildBrush->sides[ i ];
134 + buildPlane = &mapplanes[ buildSide->planenum ];
137 if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
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);
145 + // find surface for this side (by brute force)
147 + // - meshverts point in pairs of three into verts
149 + // - find the triangle that has most in common with our side
150 + GetBestSurfaceTriangleMatchForBrushside(buildSide, vert);
153 + if(vert[0] && vert[1] && vert[2])
157 + vec3_t xy1I, xy1J, xy1K;
158 + vec2_t stI, stJ, stK;
159 + vec_t D, D0, D1, D2;
161 + ComputeAxisBase(buildPlane->normal, texX, texY);
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];
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)
175 + xy1I[0], xy1I[1], 1,
176 + xy1J[0], xy1J[1], 1,
177 + xy1K[0], xy1K[1], 1
181 + for(i = 0; i < 2; ++i)
184 + stI[i], xy1I[1], 1,
185 + stJ[i], xy1J[1], 1,
189 + xy1I[0], stI[i], 1,
190 + xy1J[0], stJ[i], 1,
194 + xy1I[0], xy1I[1], stI[i],
195 + xy1J[0], xy1J[1], stJ[i],
196 + xy1K[0], xy1K[1], stK[i]
198 + VectorSet(buildSide->texMat[i], D0 / D, D1 / D, D2 / D);
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]
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);
216 /* get texture name */
217 if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
218 @@ -130,14 +313,21 @@
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 ],
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],
231 + // DEBUG: valid ? 0 : C_DETAIL
234 + // TODO write brush primitives format here
238 + fprintf( f, "\t}\n" );
239 fprintf( f, "\t}\n\n" );
242 Index: tools/quake3/q3map2/main.c
243 ===================================================================
244 --- tools/quake3/q3map2/main.c (revision 191)
245 +++ tools/quake3/q3map2/main.c (working copy)
247 Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
250 + else if( !strcmp( argv[ i ], "-ne" ) )
252 + normalEpsilon = atof( argv[ i + 1 ] );
254 + Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
256 + else if( !strcmp( argv[ i ], "-de" ) )
258 + distanceEpsilon = atof( argv[ i + 1 ] );
260 + Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
264 /* clean up map name */