00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include "qe3.h"
00024
00025
00026
00027
00028 vec_t SarrusDet(vec3_t a, vec3_t b, vec3_t c)
00029 {
00030 return a[0]*b[1]*c[2]+b[0]*c[1]*a[2]+c[0]*a[1]*b[2]
00031 -c[0]*b[1]*a[2]-a[1]*b[0]*c[2]-a[0]*b[2]*c[1];
00032 }
00033
00034
00035
00036
00037
00038 void ComputeAxisBase(vec3_t normal,vec3_t texS,vec3_t texT )
00039 {
00040 vec_t RotY,RotZ;
00041
00042 if (fabs(normal[0])<1e-6)
00043 normal[0]=0.0f;
00044 if (fabs(normal[1])<1e-6)
00045 normal[1]=0.0f;
00046 if (fabs(normal[2])<1e-6)
00047 normal[2]=0.0f;
00048 RotY=-atan2(normal[2],sqrt(normal[1]*normal[1]+normal[0]*normal[0]));
00049 RotZ=atan2(normal[1],normal[0]);
00050
00051 texS[0]=-sin(RotZ);
00052 texS[1]=cos(RotZ);
00053 texS[2]=0;
00054
00055 texT[0]=-sin(RotY)*cos(RotZ);
00056 texT[1]=-sin(RotY)*sin(RotZ);
00057 texT[2]=-cos(RotY);
00058 }
00059
00060 void FaceToBrushPrimitFace(face_t *f)
00061 {
00062 vec3_t texX,texY;
00063 vec3_t proj;
00064
00065 vec_t ST[3][5];
00066
00067
00068
00069
00070
00071 #ifdef _DEBUG
00072 if ( f->plane.normal[0]==0.0f && f->plane.normal[1]==0.0f && f->plane.normal[2]==0.0f )
00073 {
00074 Sys_Printf("Warning : f->plane.normal is (0,0,0) in FaceToBrushPrimitFace\n");
00075 }
00076
00077 if (!f->d_texture)
00078 {
00079 Sys_Printf("Warning : f.d_texture is NULL in FaceToBrushPrimitFace\n");
00080 return;
00081 }
00082 #endif
00083
00084 ComputeAxisBase(f->plane.normal,texX,texY);
00085
00086 VectorCopy(f->plane.normal,proj);
00087 VectorScale(proj,f->plane.dist,proj);
00088
00089
00090
00091
00092 VectorCopy(proj,ST[0]);
00093 EmitTextureCoordinates(ST[0], f->d_texture, f);
00094 VectorCopy(texX,ST[1]);
00095 VectorAdd(ST[1],proj,ST[1]);
00096 EmitTextureCoordinates(ST[1], f->d_texture, f);
00097 VectorCopy(texY,ST[2]);
00098 VectorAdd(ST[2],proj,ST[2]);
00099 EmitTextureCoordinates(ST[2], f->d_texture, f);
00100
00101 f->brushprimit_texdef.coords[0][2]=ST[0][3];
00102 f->brushprimit_texdef.coords[1][2]=ST[0][4];
00103 f->brushprimit_texdef.coords[0][0]=ST[1][3]-f->brushprimit_texdef.coords[0][2];
00104 f->brushprimit_texdef.coords[1][0]=ST[1][4]-f->brushprimit_texdef.coords[1][2];
00105 f->brushprimit_texdef.coords[0][1]=ST[2][3]-f->brushprimit_texdef.coords[0][2];
00106 f->brushprimit_texdef.coords[1][1]=ST[2][4]-f->brushprimit_texdef.coords[1][2];
00107 }
00108
00109
00110 void EmitBrushPrimitTextureCoordinates(face_t * f, winding_t * w)
00111 {
00112 vec3_t texX,texY;
00113 vec_t x,y;
00114
00115 ComputeAxisBase(f->plane.normal,texX,texY);
00116
00117
00118 if (f->brushprimit_texdef.coords[0][0]==0 && f->brushprimit_texdef.coords[1][0]==0 && f->brushprimit_texdef.coords[0][1]==0 && f->brushprimit_texdef.coords[1][1]==0)
00119 {
00120 f->brushprimit_texdef.coords[0][0] = 1.0f;
00121 f->brushprimit_texdef.coords[1][1] = 1.0f;
00122 ConvertTexMatWithQTexture( &f->brushprimit_texdef, NULL, &f->brushprimit_texdef, f->d_texture );
00123 }
00124 int i;
00125 for (i=0 ; i<w->numpoints ; i++)
00126 {
00127 x=DotProduct(w->points[i],texX);
00128 y=DotProduct(w->points[i],texY);
00129 #ifdef _DEBUG
00130 if (g_qeglobals.bNeedConvert)
00131 {
00132
00133 vec_t S=f->brushprimit_texdef.coords[0][0]*x+f->brushprimit_texdef.coords[0][1]*y+f->brushprimit_texdef.coords[0][2];
00134 vec_t T=f->brushprimit_texdef.coords[1][0]*x+f->brushprimit_texdef.coords[1][1]*y+f->brushprimit_texdef.coords[1][2];
00135 if ( fabs(S-w->points[i][3])>1e-2 || fabs(T-w->points[i][4])>1e-2 )
00136 {
00137 if ( fabs(S-w->points[i][3])>1e-4 || fabs(T-w->points[i][4])>1e-4 )
00138 Sys_Printf("Warning : precision loss in brush -> brush primitive texture computation\n");
00139 else
00140 Sys_Printf("Warning : brush -> brush primitive texture computation bug detected\n");
00141 }
00142 }
00143 #endif
00144 w->points[i][3]=f->brushprimit_texdef.coords[0][0]*x+f->brushprimit_texdef.coords[0][1]*y+f->brushprimit_texdef.coords[0][2];
00145 w->points[i][4]=f->brushprimit_texdef.coords[1][0]*x+f->brushprimit_texdef.coords[1][1]*y+f->brushprimit_texdef.coords[1][2];
00146 }
00147 }
00148
00149
00150 void BrushPrimit_Parse(brush_t *b)
00151 {
00152 epair_t *ep;
00153 face_t *f;
00154 int i,j;
00155 GetToken (true);
00156 if (strcmp (token, "{"))
00157 {
00158 Warning ("parsing brush primitive");
00159 return;
00160 }
00161 do
00162 {
00163 if (!GetToken (true))
00164 break;
00165 if (!strcmp (token, "}") )
00166 break;
00167
00168 if (strcmp (token, "(") )
00169 {
00170 ep = ParseEpair();
00171 ep->next = b->epairs;
00172 b->epairs = ep;
00173 }
00174 else
00175
00176 {
00177 f = Face_Alloc();
00178 f->next = NULL;
00179 if (!b->brush_faces)
00180 b->brush_faces = f;
00181 else
00182 {
00183 face_t *scan;
00184 for (scan=b->brush_faces ; scan->next ; scan=scan->next)
00185 ;
00186 scan->next = f;
00187 }
00188
00189
00190 for (i=0 ; i<3 ; i++)
00191 {
00192 if (i != 0)
00193 GetToken (true);
00194 if (strcmp (token, "(") )
00195 {
00196 Warning ("parsing brush");
00197 return;
00198 }
00199 for (j=0 ; j<3 ; j++)
00200 {
00201 GetToken (false);
00202 f->planepts[i][j] = atof(token);
00203 }
00204 GetToken (false);
00205 if (strcmp (token, ")") )
00206 {
00207 Warning ("parsing brush");
00208 return;
00209 }
00210 }
00211
00212 GetToken (false);
00213 if (strcmp(token, "("))
00214 {
00215 Warning ("parsing brush primitive");
00216 return;
00217 }
00218 GetToken (false);
00219 if (strcmp(token, "("))
00220 {
00221 Warning ("parsing brush primitive");
00222 return;
00223 }
00224 for (j=0;j<3;j++)
00225 {
00226 GetToken(false);
00227 f->brushprimit_texdef.coords[0][j]=atof(token);
00228 }
00229 GetToken (false);
00230 if (strcmp(token, ")"))
00231 {
00232 Warning ("parsing brush primitive");
00233 return;
00234 }
00235 GetToken (false);
00236 if (strcmp(token, "("))
00237 {
00238 Warning ("parsing brush primitive");
00239 return;
00240 }
00241 for (j=0;j<3;j++)
00242 {
00243 GetToken(false);
00244 f->brushprimit_texdef.coords[1][j]=atof(token);
00245 }
00246 GetToken (false);
00247 if (strcmp(token, ")"))
00248 {
00249 Warning ("parsing brush primitive");
00250 return;
00251 }
00252 GetToken (false);
00253 if (strcmp(token, ")"))
00254 {
00255 Warning ("parsing brush primitive");
00256 return;
00257 }
00258
00259 GetToken (false);
00260
00261 f->texdef.SetName(token);
00262 if (TokenAvailable ())
00263 {
00264 GetToken (false);
00265 f->texdef.contents = atoi(token);
00266 GetToken (false);
00267 f->texdef.flags = atoi(token);
00268 GetToken (false);
00269 f->texdef.value = atoi(token);
00270 }
00271 }
00272 } while (1);
00273 }
00274
00275
00276
00277 void TexMatToFakeTexCoords( vec_t texMat[2][3], float shift[2], float *rot, float scale[2] )
00278 {
00279 #ifdef _DEBUG
00280
00281 if (fabs(texMat[0][0]*texMat[0][1]+texMat[1][0]*texMat[1][1])>ZERO_EPSILON)
00282 Sys_Printf("Warning : non orthogonal texture matrix in TexMatToFakeTexCoords\n");
00283 #endif
00284 scale[0]=sqrt(texMat[0][0]*texMat[0][0]+texMat[1][0]*texMat[1][0]);
00285 scale[1]=sqrt(texMat[0][1]*texMat[0][1]+texMat[1][1]*texMat[1][1]);
00286 #ifdef _DEBUG
00287 if (scale[0]<ZERO_EPSILON || scale[1]<ZERO_EPSILON)
00288 Sys_Printf("Warning : unexpected scale==0 in TexMatToFakeTexCoords\n");
00289 #endif
00290
00291 if (fabs(texMat[0][0])<ZERO_EPSILON)
00292 {
00293 #ifdef _DEBUG
00294
00295 if (fabs(texMat[1][0])<ZERO_EPSILON)
00296 Sys_Printf("Warning : unexpected texdef[1][0]==0 in TexMatToFakeTexCoords\n");
00297 #endif
00298
00299 if (texMat[1][0]>0)
00300 *rot=90.0f;
00301 else
00302 *rot=-90.0f;
00303 }
00304 else
00305 *rot = RAD2DEG( atan2( texMat[1][0], texMat[0][0] ) );
00306 shift[0] = -texMat[0][2];
00307 shift[1] = texMat[1][2];
00308 }
00309
00310
00311
00312 void FakeTexCoordsToTexMat( float shift[2], float rot, float scale[2], vec_t texMat[2][3] )
00313 {
00314 texMat[0][0] = scale[0] * cos( DEG2RAD( rot ) );
00315 texMat[1][0] = scale[0] * sin( DEG2RAD( rot ) );
00316 texMat[0][1] = -1.0f * scale[1] * sin( DEG2RAD( rot ) );
00317 texMat[1][1] = scale[1] * cos( DEG2RAD( rot ) );
00318 texMat[0][2] = -shift[0];
00319 texMat[1][2] = shift[1];
00320 }
00321
00322
00323
00324 void ConvertTexMatWithQTexture( brushprimit_texdef_t *texMat1, qtexture_t *qtex1, brushprimit_texdef_t *texMat2, qtexture_t *qtex2 )
00325 {
00326 float s1,s2;
00327 s1 = ( qtex1 ? static_cast<float>( qtex1->width ) : 2.0f ) / ( qtex2 ? static_cast<float>( qtex2->width ) : 2.0f );
00328 s2 = ( qtex1 ? static_cast<float>( qtex1->height ) : 2.0f ) / ( qtex2 ? static_cast<float>( qtex2->height ) : 2.0f );
00329 texMat2->coords[0][0]=s1*texMat1->coords[0][0];
00330 texMat2->coords[0][1]=s1*texMat1->coords[0][1];
00331 texMat2->coords[0][2]=s1*texMat1->coords[0][2];
00332 texMat2->coords[1][0]=s2*texMat1->coords[1][0];
00333 texMat2->coords[1][1]=s2*texMat1->coords[1][1];
00334 texMat2->coords[1][2]=s2*texMat1->coords[1][2];
00335 }
00336
00337
00338 void Face_MoveTexture_BrushPrimit(face_t *f, vec3_t delta)
00339 {
00340 vec3_t texS,texT;
00341 vec_t tx,ty;
00342 vec3_t M[3];
00343 vec_t det;
00344 vec3_t D[2];
00345
00346 ComputeAxisBase( f->plane.normal, texS, texT );
00347
00348 tx = DotProduct( delta, texS );
00349 ty = DotProduct( delta, texT );
00350
00351 M[0][0]=tx; M[0][1]=1.0f+tx; M[0][2]=tx;
00352 M[1][0]=ty; M[1][1]=ty; M[1][2]=1.0f+ty;
00353 M[2][0]=1.0f; M[2][1]=1.0f; M[2][2]=1.0f;
00354 D[0][0]=f->brushprimit_texdef.coords[0][2];
00355 D[0][1]=f->brushprimit_texdef.coords[0][0]+f->brushprimit_texdef.coords[0][2];
00356 D[0][2]=f->brushprimit_texdef.coords[0][1]+f->brushprimit_texdef.coords[0][2];
00357 D[1][0]=f->brushprimit_texdef.coords[1][2];
00358 D[1][1]=f->brushprimit_texdef.coords[1][0]+f->brushprimit_texdef.coords[1][2];
00359 D[1][2]=f->brushprimit_texdef.coords[1][1]+f->brushprimit_texdef.coords[1][2];
00360
00361 det = SarrusDet( M[0], M[1], M[2] );
00362 f->brushprimit_texdef.coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det;
00363 f->brushprimit_texdef.coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det;
00364 f->brushprimit_texdef.coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det;
00365 f->brushprimit_texdef.coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det;
00366 f->brushprimit_texdef.coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det;
00367 f->brushprimit_texdef.coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det;
00368 }
00369
00370
00371 void Select_ShiftTexture_BrushPrimit( face_t *f, int x, int y )
00372 {
00373 vec3_t texS,texT;
00374 vec3_t delta;
00375 ComputeAxisBase( f->plane.normal, texS, texT );
00376 VectorScale( texS, static_cast<float>(x), texS );
00377 VectorScale( texT, static_cast<float>(y), texT );
00378 VectorCopy( texS, delta );
00379 VectorAdd( delta, texT, delta );
00380 Face_MoveTexture_BrushPrimit( f, delta );
00381 }
00382
00383
00384
00385 void RotateFaceTexture_BrushPrimit(face_t *f, int nAxis, float fDeg, vec3_t vOrigin )
00386 {
00387 vec3_t texS,texT;
00388 vec3_t vRotate;
00389 vec3_t Orig;
00390 vec3_t rOrig,rvecS,rvecT;
00391 vec3_t rNormal;
00392 vec3_t rtexS,rtexT;
00393 vec3_t lOrig,lvecS,lvecT;
00394 vec3_t M[3];
00395 vec_t det;
00396 vec3_t D[2];
00397
00398 ComputeAxisBase( f->plane.normal, texS, texT );
00399
00400
00401
00402 VectorSet( vRotate, 0.0f, 0.0f, 0.0f );
00403 vRotate[nAxis]=fDeg;
00404 VectorSet( Orig, 0.0f, 0.0f, 0.0f );
00405 VectorRotate( Orig, vRotate, vOrigin, rOrig );
00406 VectorRotate( texS, vRotate, vOrigin, rvecS );
00407 VectorRotate( texT, vRotate, vOrigin, rvecT );
00408
00409 VectorRotate( f->plane.normal, vRotate, rNormal );
00410
00411 ComputeAxisBase( rNormal, rtexS, rtexT );
00412
00413 lOrig[0] = DotProduct( rOrig, rtexS );
00414 lOrig[1] = DotProduct( rOrig, rtexT );
00415 lvecS[0] = DotProduct( rvecS, rtexS );
00416 lvecS[1] = DotProduct( rvecS, rtexT );
00417 lvecT[0] = DotProduct( rvecT, rtexS );
00418 lvecT[1] = DotProduct( rvecT, rtexT );
00419 M[0][0] = lOrig[0]; M[1][0] = lOrig[1]; M[2][0] = 1.0f;
00420 M[0][1] = lvecS[0]; M[1][1] = lvecS[1]; M[2][1] = 1.0f;
00421 M[0][2] = lvecT[0]; M[1][2] = lvecT[1]; M[2][2] = 1.0f;
00422
00423 D[0][0]=f->brushprimit_texdef.coords[0][2];
00424 D[0][1]=f->brushprimit_texdef.coords[0][0]+f->brushprimit_texdef.coords[0][2];
00425 D[0][2]=f->brushprimit_texdef.coords[0][1]+f->brushprimit_texdef.coords[0][2];
00426 D[1][0]=f->brushprimit_texdef.coords[1][2];
00427 D[1][1]=f->brushprimit_texdef.coords[1][0]+f->brushprimit_texdef.coords[1][2];
00428 D[1][2]=f->brushprimit_texdef.coords[1][1]+f->brushprimit_texdef.coords[1][2];
00429
00430 det = SarrusDet( M[0], M[1], M[2] );
00431 f->brushprimit_texdef.coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det;
00432 f->brushprimit_texdef.coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det;
00433 f->brushprimit_texdef.coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det;
00434 f->brushprimit_texdef.coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det;
00435 f->brushprimit_texdef.coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det;
00436 f->brushprimit_texdef.coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det;
00437 }
00438
00439
00440 void ComputeBest2DVector( vec3_t v, vec3_t X, vec3_t Y, int &x, int &y )
00441 {
00442 double sx,sy;
00443 sx = DotProduct( v, X );
00444 sy = DotProduct( v, Y );
00445 if ( fabs(sy) > fabs(sx) )
00446 {
00447 x = 0;
00448 if ( sy > 0.0 )
00449 y = 1;
00450 else
00451 y = -1;
00452 }
00453 else
00454 {
00455 y = 0;
00456 if ( sx > 0.0 )
00457 x = 1;
00458 else
00459 x = -1;
00460 }
00461 }