]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/convert_map.c
properly ignore caulk
[xonotic/netradiant.git] / tools / quake3 / q3map2 / convert_map.c
index 38fc738fd52c831636c679241fedf32efe8c8ce3..418ee27a10750e5403d783ef33aa81ac9e6fabdc 100644 (file)
@@ -87,7 +87,7 @@ void GetBestSurfaceTriangleMatchForBrushside(side_t *buildSide, bspDrawVert_t *b
                        vert[0] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 0]];
                        vert[1] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 1]];
                        vert[2] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 2]];
-                       if(s->surfaceType == MST_PLANAR)
+                       if(s->surfaceType == MST_PLANAR && VectorCompare(vert[0]->normal, vert[1]->normal) && VectorCompare(vert[1]->normal, vert[2]->normal))
                        {
                                VectorSubtract(vert[0]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
                                VectorSubtract(vert[1]->normal, buildPlane->normal, normdiff); if(VectorLength(normdiff) >= normalEpsilon) continue;
@@ -145,25 +145,89 @@ exwinding:
        //      fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide->shaderInfo->shader, matches, best);
 }
 
-static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
+#define FRAC(x) ((x) - floor(x))
+static void ConvertOriginBrush( FILE *f, int num, vec3_t origin, qboolean brushPrimitives )
+{
+       int originSize = 256;
+
+       char pattern[6][7][3] = {
+               { "+++", "+-+", "-++", "-  ", " + ", " - ", "-  " },
+               { "+++", "-++", "++-", "-  ", "  +", "+  ", "  +" },
+               { "+++", "++-", "+-+", " - ", "  +", " - ", "  +" },
+               { "---", "+--", "-+-", "-  ", " + ", " - ", "+  " },
+               { "---", "--+", "+--", "-  ", "  +", "-  ", "  +" },
+               { "---", "-+-", "--+", " - ", "  +", " + ", "  +" }
+       };
+       int i;
+#define S(a,b,c) (pattern[a][b][c] == '+' ? +1 : pattern[a][b][c] == '-' ? -1 : 0)
+
+       /* start brush */
+       fprintf( f, "\t// brush %d\n", num );
+       fprintf( f, "\t{\n" );
+       if(brushPrimitives)
+       {
+               fprintf( f, "\tbrushDef\n" );
+               fprintf( f, "\t{\n" );
+       }
+       /* print brush side */
+       /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
+
+       for(i = 0; i < 6; ++i)
+       {
+               if(brushPrimitives)
+               {
+                       fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( ( %.8f %.8f %.8f ) ( %.8f %.8f %.8f ) ) %s %d 0 0\n",
+                                       origin[0] + 8 * S(i,0,0), origin[1] + 8 * S(i,0,1), origin[2] + 8 * S(i,0,2),
+                                       origin[0] + 8 * S(i,1,0), origin[1] + 8 * S(i,1,1), origin[2] + 8 * S(i,1,2),
+                                       origin[0] + 8 * S(i,2,0), origin[1] + 8 * S(i,2,1), origin[2] + 8 * S(i,2,2),
+                                       1.0f/16.0f, 0.0f, FRAC((S(i,5,0) * origin[0] + S(i,5,1) * origin[1] + S(i,5,2) * origin[2]) / 16.0 + 0.5),
+                                       0.0f, 1.0f/16.0f, FRAC((S(i,6,0) * origin[0] + S(i,6,1) * origin[1] + S(i,6,2) * origin[2]) / 16.0 + 0.5),
+                                       "common/origin",
+                                       0
+                                  );
+               }
+               else
+               {
+                       fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s %.8f %.8f %.8f %.8f %.8f %d 0 0\n",
+                                       origin[0] + 8 * S(i,0,0), origin[1] + 8 * S(i,0,1), origin[2] + 8 * S(i,0,2),
+                                       origin[0] + 8 * S(i,1,0), origin[1] + 8 * S(i,1,1), origin[2] + 8 * S(i,1,2),
+                                       origin[0] + 8 * S(i,2,0), origin[1] + 8 * S(i,2,1), origin[2] + 8 * S(i,2,2),
+                                       "common/origin",
+                                       FRAC((S(i,3,0) * origin[0] + S(i,3,1) * origin[1] + S(i,3,2) * origin[2]) / 16.0 + 0.5) * originSize,
+                                       FRAC((S(i,4,0) * origin[0] + S(i,4,1) * origin[1] + S(i,4,2) * origin[2]) / 16.0 + 0.5) * originSize,
+                                       0.0f, 16.0 / originSize, 16.0 / originSize,
+                                       0
+                                  );
+               }
+       }
+#undef S
+       
+       /* end brush */
+       if(brushPrimitives)
+               fprintf( f, "\t}\n" );
+       fprintf( f, "\t}\n\n" );
+}
+
+static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, qboolean brushPrimitives )
 {
        int                             i, j;
        bspBrushSide_t  *side;
        side_t                  *buildSide;
        bspShader_t             *shader;
        char                    *texture;
-       bspPlane_t              *plane;
        plane_t         *buildPlane;
        vec3_t                  pts[ 3 ];
        bspDrawVert_t   *vert[3];
-       int valid;
        
        
        /* start brush */
        fprintf( f, "\t// brush %d\n", num );
        fprintf( f, "\t{\n" );
-       fprintf( f, "\tbrushDef\n" );
-       fprintf( f, "\t{\n" );
+       if(brushPrimitives)
+       {
+               fprintf( f, "\tbrushDef\n" );
+               fprintf( f, "\t{\n" );
+       }
        
        /* clear out build brush */
        for( i = 0; i < buildBrush->numsides; i++ )
@@ -187,11 +251,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
                if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
                        continue;
                shader = &bspShaders[ side->shaderNum ];
-               if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
-                       continue;
-               
-               /* get plane */
-               plane = &bspPlanes[ side->planeNum ];
+               //if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
+               //      continue;
                
                /* add build side */
                buildSide = &buildBrush->sides[ buildBrush->numsides ];
@@ -205,7 +266,10 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
        
        /* make brush windings */
        if( !CreateBrushWindings( buildBrush ) )
+       {
+               Sys_Printf( "CreateBrushWindings failed\n" );
                return;
+       }
        
        /* iterate through build brush sides */
        for( i = 0; i < buildBrush->numsides; i++ )
@@ -231,71 +295,7 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
                //   - (triangles)
                //   - find the triangle that has most in common with our side
                GetBestSurfaceTriangleMatchForBrushside(buildSide, vert);
-               valid = 0;
 
-               if(vert[0] && vert[1] && vert[2])
-               {
-                       int i;
-                       vec3_t texX, texY;
-                       vec3_t xy1I, xy1J, xy1K;
-                       vec2_t stI, stJ, stK;
-                       vec_t D, D0, D1, D2;
-
-                       ComputeAxisBase(buildPlane->normal, texX, texY);
-
-                       VectorSet(xy1I, DotProduct(vert[0]->xyz, texX), DotProduct(vert[0]->xyz, texY), 1);
-                       VectorSet(xy1J, DotProduct(vert[1]->xyz, texX), DotProduct(vert[1]->xyz, texY), 1);
-                       VectorSet(xy1K, DotProduct(vert[2]->xyz, texX), DotProduct(vert[2]->xyz, texY), 1);
-                       stI[0] = vert[0]->st[0]; stI[1] = vert[0]->st[1];
-                       stJ[0] = vert[1]->st[0]; stJ[1] = vert[1]->st[1];
-                       stK[0] = vert[2]->st[0]; stK[1] = vert[2]->st[1];
-
-                       //   - solve linear equations:
-                       //     - (x, y) := xyz . (texX, texY)
-                       //     - st[i] = texMat[i][0]*x + texMat[i][1]*y + texMat[i][2]
-                       //       (for three vertices)
-                       D = Det3x3(
-                               xy1I[0], xy1I[1], 1,
-                               xy1J[0], xy1J[1], 1,
-                               xy1K[0], xy1K[1], 1
-                       );
-                       if(D != 0)
-                       {
-                               for(i = 0; i < 2; ++i)
-                               {
-                                       D0 = Det3x3(
-                                               stI[i], xy1I[1], 1,
-                                               stJ[i], xy1J[1], 1,
-                                               stK[i], xy1K[1], 1
-                                       );
-                                       D1 = Det3x3(
-                                               xy1I[0], stI[i], 1,
-                                               xy1J[0], stJ[i], 1,
-                                               xy1K[0], stK[i], 1
-                                       );
-                                       D2 = Det3x3(
-                                               xy1I[0], xy1I[1], stI[i],
-                                               xy1J[0], xy1J[1], stJ[i],
-                                               xy1K[0], xy1K[1], stK[i]
-                                       );
-                                       VectorSet(buildSide->texMat[i], D0 / D, D1 / D, D2 / D);
-                                       valid = 1;
-                               }
-                       }
-                       else
-                               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",
-                                       buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2],
-                                       vert[0]->normal[0], vert[0]->normal[1], vert[0]->normal[2],
-                                       texX[0], texX[1], texX[2], texY[0], texY[1], texY[2],
-                                       vert[0]->xyz[0], vert[0]->xyz[1], vert[0]->xyz[2], xy1I[0], xy1I[1],
-                                       vert[1]->xyz[0], vert[1]->xyz[1], vert[1]->xyz[2], xy1J[0], xy1J[1],
-                                       vert[2]->xyz[0], vert[2]->xyz[1], vert[2]->xyz[2], xy1K[0], xy1K[1]
-                                       );
-               }
-               else
-                       if(strncmp(buildSide->shaderInfo->shader, "textures/common/", 16))
-                               fprintf(stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide->shaderInfo->shader);
-               
                /* get texture name */
                if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
                        texture = buildSide->shaderInfo->shader + 9;
@@ -310,26 +310,222 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
                        //%     pts[ j ][ 1 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 1 ] * SNAP_FLOAT_TO_INT + 0.5f );
                        //%     pts[ j ][ 2 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 2 ] * SNAP_FLOAT_TO_INT + 0.5f );
                }
-               
-               /* print brush side */
-               /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
-               fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( ( %.8f %.8f %.8f ) ( %.8f %.8f %.8f ) ) %s %d 0 0\n",
-                       pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
-                       pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
-                       pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
-                       buildSide->texMat[0][0], buildSide->texMat[0][1], buildSide->texMat[0][2],
-                       buildSide->texMat[1][0], buildSide->texMat[1][1], buildSide->texMat[1][2],
-                       texture,
-                       // DEBUG: valid ? 0 : C_DETAIL
-                       0
-                       );
-               // TODO write brush primitives format here
+
+               if(vert[0] && vert[1] && vert[2])
+               {
+                       if(brushPrimitives)
+                       {
+                               int i;
+                               vec3_t texX, texY;
+                               vec2_t xyI, xyJ, xyK;
+                               vec2_t stI, stJ, stK;
+                               vec_t D, D0, D1, D2;
+
+                               ComputeAxisBase(buildPlane->normal, texX, texY);
+
+                               xyI[0] = DotProduct(vert[0]->xyz, texX);
+                               xyI[1] = DotProduct(vert[0]->xyz, texY);
+                               xyJ[0] = DotProduct(vert[1]->xyz, texX);
+                               xyJ[1] = DotProduct(vert[1]->xyz, texY);
+                               xyK[0] = DotProduct(vert[2]->xyz, texX);
+                               xyK[1] = DotProduct(vert[2]->xyz, texY);
+                               stI[0] = vert[0]->st[0]; stI[1] = vert[0]->st[1];
+                               stJ[0] = vert[1]->st[0]; stJ[1] = vert[1]->st[1];
+                               stK[0] = vert[2]->st[0]; stK[1] = vert[2]->st[1];
+
+                               //   - solve linear equations:
+                               //     - (x, y) := xyz . (texX, texY)
+                               //     - st[i] = texMat[i][0]*x + texMat[i][1]*y + texMat[i][2]
+                               //       (for three vertices)
+                               D = Det3x3(
+                                       xyI[0], xyI[1], 1,
+                                       xyJ[0], xyJ[1], 1,
+                                       xyK[0], xyK[1], 1
+                               );
+                               if(D != 0)
+                               {
+                                       for(i = 0; i < 2; ++i)
+                                       {
+                                               D0 = Det3x3(
+                                                       stI[i], xyI[1], 1,
+                                                       stJ[i], xyJ[1], 1,
+                                                       stK[i], xyK[1], 1
+                                               );
+                                               D1 = Det3x3(
+                                                       xyI[0], stI[i], 1,
+                                                       xyJ[0], stJ[i], 1,
+                                                       xyK[0], stK[i], 1
+                                               );
+                                               D2 = Det3x3(
+                                                       xyI[0], xyI[1], stI[i],
+                                                       xyJ[0], xyJ[1], stJ[i],
+                                                       xyK[0], xyK[1], stK[i]
+                                               );
+                                               VectorSet(buildSide->texMat[i], D0 / D, D1 / D, D2 / D);
+                                       }
+                               }
+                               else
+                                       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",
+                                               buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2],
+                                               vert[0]->normal[0], vert[0]->normal[1], vert[0]->normal[2],
+                                               texX[0], texX[1], texX[2], texY[0], texY[1], texY[2],
+                                               vert[0]->xyz[0], vert[0]->xyz[1], vert[0]->xyz[2], xyI[0], xyI[1],
+                                               vert[1]->xyz[0], vert[1]->xyz[1], vert[1]->xyz[2], xyJ[0], xyJ[1],
+                                               vert[2]->xyz[0], vert[2]->xyz[1], vert[2]->xyz[2], xyK[0], xyK[1]
+                                               );
+
+                               /* print brush side */
+                               /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
+                               fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( ( %.8f %.8f %.8f ) ( %.8f %.8f %.8f ) ) %s %d 0 0\n",
+                                               pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
+                                               pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
+                                               pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
+                                               buildSide->texMat[0][0], buildSide->texMat[0][1], FRAC(buildSide->texMat[0][2]),
+                                               buildSide->texMat[1][0], buildSide->texMat[1][1], FRAC(buildSide->texMat[1][2]),
+                                               texture,
+                                               0
+                                          );
+                       }
+                       else
+                       {
+                               // invert QuakeTextureVecs
+                               int i;
+                               vec3_t vecs[2];
+                               int sv, tv;
+                               vec2_t stI, stJ, stK;
+                               vec3_t sts[2];
+                               vec2_t shift, scale;
+                               vec_t rotate;
+                               vec_t D, D0, D1, D2;
+
+                               TextureAxisFromPlane(buildPlane, vecs[0], vecs[1]);
+                               if (vecs[0][0])
+                                       sv = 0;
+                               else if (vecs[0][1])
+                                       sv = 1;
+                               else
+                                       sv = 2;
+                               if (vecs[1][0])
+                                       tv = 0;
+                               else if (vecs[1][1])
+                                       tv = 1;
+                               else
+                                       tv = 2;
+
+                               stI[0] = vert[0]->st[0] * buildSide->shaderInfo->shaderWidth; stI[1] = vert[0]->st[1] * buildSide->shaderInfo->shaderHeight;
+                               stJ[0] = vert[1]->st[0] * buildSide->shaderInfo->shaderWidth; stJ[1] = vert[1]->st[1] * buildSide->shaderInfo->shaderHeight;
+                               stK[0] = vert[2]->st[0] * buildSide->shaderInfo->shaderWidth; stK[1] = vert[2]->st[1] * buildSide->shaderInfo->shaderHeight;
+
+                               D = Det3x3(
+                                       vert[0]->xyz[sv], vert[0]->xyz[tv], 1,
+                                       vert[1]->xyz[sv], vert[1]->xyz[tv], 1,
+                                       vert[2]->xyz[sv], vert[2]->xyz[tv], 1
+                               );
+                               if(D != 0)
+                               {
+                                       for(i = 0; i < 2; ++i)
+                                       {
+                                               D0 = Det3x3(
+                                                       stI[i], vert[0]->xyz[tv], 1,
+                                                       stJ[i], vert[1]->xyz[tv], 1,
+                                                       stK[i], vert[2]->xyz[tv], 1
+                                               );
+                                               D1 = Det3x3(
+                                                       vert[0]->xyz[sv], stI[i], 1,
+                                                       vert[1]->xyz[sv], stJ[i], 1,
+                                                       vert[2]->xyz[sv], stK[i], 1
+                                               );
+                                               D2 = Det3x3(
+                                                       vert[0]->xyz[sv], vert[0]->xyz[tv], stI[i],
+                                                       vert[1]->xyz[sv], vert[1]->xyz[tv], stJ[i],
+                                                       vert[2]->xyz[sv], vert[2]->xyz[tv], stK[i]
+                                               );
+                                               VectorSet(sts[i], D0 / D, D1 / D, D2 / D);
+                                       }
+                               }
+                               else
+                                       fprintf(stderr, "degenerate triangle found when solving texDef equations\n"); // FIXME add stuff here
+
+                               // now we must solve:
+                                       //      // now we must invert:
+                                       //      ang = rotate / 180 * Q_PI;
+                                       //      sinv = sin(ang);
+                                       //      cosv = cos(ang);
+                                       //      ns = cosv * vecs[0][sv];
+                                       //      nt = sinv * vecs[0][sv];
+                                       //      vecsrotscaled[0][sv] = ns / scale[0];
+                                       //      vecsrotscaled[0][tv] = nt / scale[0];
+                                       //      ns = -sinv * vecs[1][tv];
+                                       //      nt =  cosv * vecs[1][tv];
+                                       //      vecsrotscaled[1][sv] = ns / scale[1];
+                                       //      vecsrotscaled[1][tv] = nt / scale[1];
+                               scale[0] = 1.0/sqrt(sts[0][0] * sts[0][0] + sts[0][1] * sts[0][1]);
+                               scale[1] = 1.0/sqrt(sts[1][0] * sts[1][0] + sts[1][1] * sts[1][1]);
+                               rotate = atan2(sts[0][1] * vecs[0][sv] - sts[1][0] * vecs[1][tv], sts[0][0] * vecs[0][sv] + sts[1][1] * vecs[1][tv]) * (180.0f / Q_PI);
+                               shift[0] = buildSide->shaderInfo->shaderWidth * FRAC(sts[0][2] / buildSide->shaderInfo->shaderWidth);
+                               shift[1] = buildSide->shaderInfo->shaderHeight * FRAC(sts[1][2] / buildSide->shaderInfo->shaderHeight);
+
+                               /* print brush side */
+                               /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
+                               fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s %.8f %.8f %.8f %.8f %.8f %d 0 0\n",
+                                               pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
+                                               pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
+                                               pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
+                                               texture,
+                                               shift[0], shift[1], rotate, scale[0], scale[1],
+                                               0
+                                          );
+                       }
+               }
+               else
+               {
+                       vec3_t  vecs[ 2 ];
+                       if(strncmp(buildSide->shaderInfo->shader, "textures/common/", 16))
+                       if(strcmp(buildSide->shaderInfo->shader, "noshader"))
+                       if(strcmp(buildSide->shaderInfo->shader, "default"))
+                       {
+                               fprintf(stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide->shaderInfo->shader);
+                               texture = "common/WTF";
+                       }
+
+                       MakeNormalVectors( buildPlane->normal, vecs[ 0 ], vecs[ 1 ] );
+                       VectorMA( vec3_origin, buildPlane->dist, buildPlane->normal, pts[ 0 ] );
+                       VectorMA( pts[ 0 ], 256.0f, vecs[ 0 ], pts[ 1 ] );
+                       VectorMA( pts[ 0 ], 256.0f, vecs[ 1 ], pts[ 2 ] );
+                       if(brushPrimitives)
+                       {
+                               fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( ( %.8f %.8f %.8f ) ( %.8f %.8f %.8f ) ) %s %d 0 0\n",
+                                               pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
+                                               pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
+                                               pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
+                                               1.0f/16.0f, 0.0f, 0.0f,
+                                               0.0f, 1.0f/16.0f, 0.0f,
+                                               texture,
+                                               0
+                                          );
+                       }
+                       else
+                       {
+                               fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s %.8f %.8f %.8f %.8f %.8f %d 0 0\n",
+                                               pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
+                                               pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
+                                               pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
+                                               texture,
+                                               0.0f, 0.0f, 0.0f, 0.25f, 0.25f,
+                                               0
+                                          );
+                       }
+               }
        }
        
        /* end brush */
-       fprintf( f, "\t}\n" );
+       if(brushPrimitives)
+       {
+               fprintf( f, "\t}\n" );
+       }
        fprintf( f, "\t}\n\n" );
 }
+#undef FRAC
 
 #if 0
        /* iterate through the brush sides (ignore the first 6 bevel planes) */
@@ -468,7 +664,7 @@ ConvertModel()
 exports a bsp model to a map file
 */
 
-static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
+static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin, qboolean brushPrimitives )
 {
        int                                     i, num;
        bspBrush_t                      *brush;
@@ -477,25 +673,29 @@ static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origi
        
        /* convert bsp planes to map planes */
        nummapplanes = numBSPPlanes;
+       AUTOEXPAND_BY_REALLOC(mapplanes, nummapplanes, allocatedmapplanes, 1024);
        for( i = 0; i < numBSPPlanes; i++ )
        {
                VectorCopy( bspPlanes[ i ].normal, mapplanes[ i ].normal );
                mapplanes[ i ].dist = bspPlanes[ i ].dist;
                mapplanes[ i ].type = PlaneTypeForNormal( mapplanes[ i ].normal );
-               mapplanes[ i ].hash_chain = NULL;
+               mapplanes[ i ].hash_chain = 0;
        }
        
        /* allocate a build brush */
        buildBrush = AllocBrush( 512 );
        buildBrush->entityNum = 0;
        buildBrush->original = buildBrush;
+
+       if(origin[0] != 0 || origin[1] != 0 || origin[2] != 0)
+               ConvertOriginBrush(f, -1, origin, brushPrimitives);
        
        /* go through each brush in the model */
        for( i = 0; i < model->numBSPBrushes; i++ )
        {
                num = i + model->firstBSPBrush;
                brush = &bspBrushes[ num ];
-               ConvertBrush( f, num, brush, origin );
+               ConvertBrush( f, num, brush, origin, brushPrimitives );
        }
        
        /* free the build brush */
@@ -520,7 +720,7 @@ ConvertEPairs()
 exports entity key/value pairs to a map file
 */
 
-static void ConvertEPairs( FILE *f, entity_t *e )
+static void ConvertEPairs( FILE *f, entity_t *e, qboolean skip_origin )
 {
        epair_t *ep;
        
@@ -536,6 +736,10 @@ static void ConvertEPairs( FILE *f, entity_t *e )
                if( !Q_stricmp( ep->key, "model" ) && ep->value[ 0 ] == '*' )
                        continue;
                
+               /* ignore origin keys if skip_origin is set */
+               if( skip_origin && !Q_stricmp( ep->key, "origin" ) )
+                       continue;
+               
                /* emit the epair */
                fprintf( f, "\t\"%s\" \"%s\"\n", ep->key, ep->value );
        }
@@ -548,7 +752,7 @@ ConvertBSPToMap()
 exports an quake map file from the bsp
 */
 
-int ConvertBSPToMap( char *bspName )
+int ConvertBSPToMap_Ext( char *bspName, qboolean brushPrimitives )
 {
        int                             i, modelNum;
        FILE                    *f;
@@ -589,10 +793,6 @@ int ConvertBSPToMap( char *bspName )
                fprintf( f, "// entity %d\n", i );
                fprintf( f, "{\n" );
                
-               /* export keys */
-               ConvertEPairs( f, e );
-               fprintf( f, "\n" );
-               
                /* get model num */
                if( i == 0 )
                        modelNum = 0;
@@ -605,6 +805,10 @@ int ConvertBSPToMap( char *bspName )
                                modelNum = -1;
                }
                
+               /* export keys */
+               ConvertEPairs( f, e, modelNum >= 0 );
+               fprintf( f, "\n" );
+               
                /* only handle bsp models */
                if( modelNum >= 0 )
                {
@@ -619,7 +823,7 @@ int ConvertBSPToMap( char *bspName )
                                GetVectorForKey( e, "origin", origin );
                        
                        /* convert model */
-                       ConvertModel( f, model, modelNum, origin );
+                       ConvertModel( f, model, modelNum, origin, brushPrimitives );
                }
                
                /* end entity */
@@ -632,3 +836,13 @@ int ConvertBSPToMap( char *bspName )
        /* return to sender */
        return 0;
 }
+
+int ConvertBSPToMap( char *bspName )
+{
+       return ConvertBSPToMap_Ext(bspName, qfalse);
+}
+
+int ConvertBSPToMap_BP( char *bspName )
+{
+       return ConvertBSPToMap_Ext(bspName, qtrue);
+}