doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
EditorBrushPrimit.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "qe3.h"
33 
34 #define ZERO_EPSILON 1.0E-6
35 
36 class idVec3D {
37 public:
38  double x, y, z;
39  double & operator[]( const int index ) {
40  return (&x)[index];
41  }
42  void Zero() {
43  x = y = z = 0.0;
44  }
45 };
46 
47 //
48 // =======================================================================================================================
49 // compute a determinant using Sarrus rule ++timo "inline" this with a macro NOTE:: the three idVec3D are understood as
50 // columns of the matrix
51 // =======================================================================================================================
52 //
54  return (double)a[0] * (double)b[1] * (double)c[2] + (double)b[0] * (double)c[1] * (double)a[2] + (double)c[0] * (double)a[1] * (double)b[2] - (double)c[0] * (double)b[1] * (double)a[2] - (double)a[1] * (double)b[0] * (double)c[2] - (double)a[0] * (double)b[2] * (double)c[1];
55 }
56 
57 //
58 // =======================================================================================================================
59 // ++timo replace everywhere texX by texS etc. ( > and in q3map !) NOTE:: ComputeAxisBase here and in q3map code must
60 // always BE THE SAME ! WARNING:: special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere
61 // when x == 0 rotation by (0,RotY,RotZ) assigns X to normal
62 // =======================================================================================================================
63 //
64 void ComputeAxisBase(idVec3 &normal, idVec3D &texS, idVec3D &texT) {
65  double RotY, RotZ;
66 
67  // do some cleaning
68  if (idMath::Fabs(normal[0]) < 1e-6) {
69  normal[0] = 0.0f;
70  }
71 
72  if (idMath::Fabs(normal[1]) < 1e-6) {
73  normal[1] = 0.0f;
74  }
75 
76  if (idMath::Fabs(normal[2]) < 1e-6) {
77  normal[2] = 0.0f;
78  }
79 
80  RotY = -atan2(normal[2], idMath::Sqrt(normal[1] * normal[1] + normal[0] * normal[0]));
81  RotZ = atan2(normal[1], normal[0]);
82 
83  // rotate (0,1,0) and (0,0,1) to compute texS and texT
84  texS[0] = -sin(RotZ);
85  texS[1] = cos(RotZ);
86  texS[2] = 0;
87 
88  // the texT vector is along -Z ( T texture coorinates axis )
89  texT[0] = -sin(RotY) * cos(RotZ);
90  texT[1] = -sin(RotY) * sin(RotZ);
91  texT[2] = -cos(RotY);
92 }
93 
94 /*
95  =======================================================================================================================
96  =======================================================================================================================
97  */
98 void FaceToBrushPrimitFace(face_t *f) {
99  idVec3D texX, texY;
100  idVec3D proj;
101 
102  // ST of (0,0) (1,0) (0,1)
103  idVec5 ST[3]; // [ point index ] [ xyz ST ]
104 
105  //
106  // ++timo not used as long as brushprimit_texdef and texdef are static
107  // f->brushprimit_texdef.contents=f->texdef.contents;
108  // f->brushprimit_texdef.flags=f->texdef.flags;
109  // f->brushprimit_texdef.value=f->texdef.value;
110  // strcpy(f->brushprimit_texdef.name,f->texdef.name);
111  //
112 #ifdef _DEBUG
113  if (f->plane[0] == 0.0f && f->plane[1] == 0.0f && f->plane[2] == 0.0f) {
114  common->Printf("Warning : f->plane.normal is (0,0,0) in FaceToBrushPrimitFace\n");
115  }
116 
117  // check d_texture
118  if (!f->d_texture) {
119  common->Printf("Warning : f.d_texture is NULL in FaceToBrushPrimitFace\n");
120  return;
121  }
122 #endif
123  // compute axis base
124  ComputeAxisBase(f->plane.Normal(), texX, texY);
125 
126  // compute projection vector
127  VectorCopy( f->plane, proj );
128  VectorScale(proj, -f->plane[3], proj);
129 
130  //
131  // (0,0) in plane axis base is (0,0,0) in world coordinates + projection on the
132  // affine plane (1,0) in plane axis base is texX in world coordinates + projection
133  // on the affine plane (0,1) in plane axis base is texY in world coordinates +
134  // projection on the affine plane use old texture code to compute the ST coords of
135  // these points
136  //
137  VectorCopy(proj, ST[0]);
138  EmitTextureCoordinates(ST[0], f->d_texture, f);
139  VectorCopy(texX, ST[1]);
140  VectorAdd(ST[1], proj, ST[1]);
141  EmitTextureCoordinates(ST[1], f->d_texture, f);
142  VectorCopy(texY, ST[2]);
143  VectorAdd(ST[2], proj, ST[2]);
144  EmitTextureCoordinates(ST[2], f->d_texture, f);
145 
146  // compute texture matrix
147  f->brushprimit_texdef.coords[0][2] = ST[0][3];
148  f->brushprimit_texdef.coords[1][2] = ST[0][4];
149  f->brushprimit_texdef.coords[0][0] = ST[1][3] - f->brushprimit_texdef.coords[0][2];
150  f->brushprimit_texdef.coords[1][0] = ST[1][4] - f->brushprimit_texdef.coords[1][2];
151  f->brushprimit_texdef.coords[0][1] = ST[2][3] - f->brushprimit_texdef.coords[0][2];
152  f->brushprimit_texdef.coords[1][1] = ST[2][4] - f->brushprimit_texdef.coords[1][2];
153 }
154 
155 //
156 // =======================================================================================================================
157 // compute texture coordinates for the winding points
158 // =======================================================================================================================
159 //
160 void EmitBrushPrimitTextureCoordinates(face_t *f, idWinding *w, patchMesh_t *patch) {
161  idVec3D texX, texY;
162  double x, y;
163 
164  if (f== NULL || (w == NULL && patch == NULL)) {
165  return;
166  }
167 
168  // compute axis base
169  ComputeAxisBase(f->plane.Normal(), texX, texY);
170 
171  //
172  // in case the texcoords matrix is empty, build a default one same behaviour as if
173  // scale[0]==0 && scale[1]==0 in old code
174  //
175  if ( f->brushprimit_texdef.coords[0][0] == 0 &&
176  f->brushprimit_texdef.coords[1][0] == 0 &&
177  f->brushprimit_texdef.coords[0][1] == 0 &&
178  f->brushprimit_texdef.coords[1][1] == 0 ) {
179  f->brushprimit_texdef.coords[0][0] = 1.0f;
180  f->brushprimit_texdef.coords[1][1] = 1.0f;
181  ConvertTexMatWithQTexture(&f->brushprimit_texdef, NULL, &f->brushprimit_texdef, f->d_texture);
182  }
183 
184  int i;
185  if (w) {
186  for (i = 0; i < w->GetNumPoints(); i++) {
187  x = DotProduct((*w)[i], texX);
188  y = DotProduct((*w)[i], texY);
189  (*w)[i][3] = f->brushprimit_texdef.coords[0][0] * x + f->brushprimit_texdef.coords[0][1] * y + f->brushprimit_texdef.coords[0][2];
190  (*w)[i][4] = f->brushprimit_texdef.coords[1][0] * x + f->brushprimit_texdef.coords[1][1] * y + f->brushprimit_texdef.coords[1][2];
191  }
192  }
193 
194  if (patch) {
195  int j;
196  for ( i = 0; i < patch->width; i++ ) {
197  for ( j = 0; j < patch->height; j++ ) {
198  x = DotProduct(patch->ctrl(i, j).xyz, texX);
199  y = DotProduct(patch->ctrl(i, j).xyz, texY);
200  patch->ctrl(i, j).st.x = f->brushprimit_texdef.coords[0][0] * x + f->brushprimit_texdef.coords[0][1] * y + f->brushprimit_texdef.coords[0][2];
201  patch->ctrl(i, j).st.y = f->brushprimit_texdef.coords[1][0] * x + f->brushprimit_texdef.coords[1][1] * y + f->brushprimit_texdef.coords[1][2];
202  }
203  }
204  }
205 }
206 
207 //
208 // =======================================================================================================================
209 // parse a brush in brush primitive format
210 // =======================================================================================================================
211 //
212 void BrushPrimit_Parse(brush_t *b, bool newFormat, const idVec3 origin) {
213  face_t *f;
214  int i, j;
215  GetToken(true);
216  if (strcmp(token, "{")) {
217  Warning("parsing brush primitive");
218  return;
219  }
220 
221  do {
222  if (!GetToken(true)) {
223  break;
224  }
225 
226  if (!strcmp(token, "}")) {
227  break;
228  }
229 
230  // reading of b->epairs if any
231  if (strcmp(token, "(")) {
232  ParseEpair(&b->epairs);
233  }
234  else { // it's a face
235  f = Face_Alloc();
236  f->next = NULL;
237  if (!b->brush_faces) {
238  b->brush_faces = f;
239  }
240  else {
241  face_t *scan;
242  for (scan = b->brush_faces; scan->next; scan = scan->next)
243  ;
244  scan->next = f;
245  }
246 
247  if (newFormat) {
248  // read the three point plane definition
249  idPlane plane;
250  for (j = 0; j < 4; j++) {
251  GetToken(false);
252  plane[j] = atof(token);
253  }
254 
255  f->plane = plane;
256  f->originalPlane = plane;
257  f->dirty = false;
258 
259  //idWinding *w = Brush_MakeFaceWinding(b, f, true);
260  idWinding w;
261  w.BaseForPlane( plane );
262 
263  for (j = 0; j < 3; j++) {
264  f->planepts[j].x = w[j].x + origin.x;
265  f->planepts[j].y = w[j].y + origin.y;
266  f->planepts[j].z = w[j].z + origin.z;
267  }
268 
269  GetToken(false);
270  }
271  else {
272  for (i = 0; i < 3; i++) {
273  if (i != 0) {
274  GetToken(true);
275  }
276 
277  if (strcmp(token, "(")) {
278  Warning("parsing brush");
279  return;
280  }
281 
282  for (j = 0; j < 3; j++) {
283  GetToken(false);
284  f->planepts[i][j] = atof(token);
285  }
286 
287  GetToken(false);
288  if (strcmp(token, ")")) {
289  Warning("parsing brush");
290  return;
291  }
292  }
293  }
294 
295  // texture coordinates
296  GetToken(false);
297  if (strcmp(token, "(")) {
298  Warning("parsing brush primitive");
299  return;
300  }
301 
302  GetToken(false);
303  if (strcmp(token, "(")) {
304  Warning("parsing brush primitive");
305  return;
306  }
307 
308  for (j = 0; j < 3; j++) {
309  GetToken(false);
310  f->brushprimit_texdef.coords[0][j] = atof(token);
311  }
312 
313  GetToken(false);
314  if (strcmp(token, ")")) {
315  Warning("parsing brush primitive");
316  return;
317  }
318 
319  GetToken(false);
320  if (strcmp(token, "(")) {
321  Warning("parsing brush primitive");
322  return;
323  }
324 
325  for (j = 0; j < 3; j++) {
326  GetToken(false);
327  f->brushprimit_texdef.coords[1][j] = atof(token);
328  }
329 
330  GetToken(false);
331  if (strcmp(token, ")")) {
332  Warning("parsing brush primitive");
333  return;
334  }
335 
336  GetToken(false);
337  if (strcmp(token, ")")) {
338  Warning("parsing brush primitive");
339  return;
340  }
341 
342  // read the texturedef
343  GetToken(false);
344 
345  // strcpy(f->texdef.name, token);
346  if (g_qeglobals.mapVersion < 2.0) {
347  f->texdef.SetName(va("textures/%s", token));
348  }
349  else {
350  f->texdef.SetName(token);
351  }
352 
353  if (TokenAvailable()) {
354  GetToken(false);
355  GetToken(false);
356  GetToken(false);
357  f->texdef.value = atoi(token);
358  }
359  }
360  } while (1);
361 }
362 
363 //
364 // =======================================================================================================================
365 // compute a fake shift scale rot representation from the texture matrix these shift scale rot values are to be
366 // understood in the local axis base
367 // =======================================================================================================================
368 //
369 void TexMatToFakeTexCoords(float texMat[2][3], float shift[2], float *rot, float scale[2])
370 {
371 #ifdef _DEBUG
372 
373  // check this matrix is orthogonal
374  if (idMath::Fabs(texMat[0][0] * texMat[0][1] + texMat[1][0] * texMat[1][1]) > ZERO_EPSILON) {
375  common->Printf("Warning : non orthogonal texture matrix in TexMatToFakeTexCoords\n");
376  }
377 #endif
378  scale[0] = idMath::Sqrt(texMat[0][0] * texMat[0][0] + texMat[1][0] * texMat[1][0]);
379  scale[1] = idMath::Sqrt(texMat[0][1] * texMat[0][1] + texMat[1][1] * texMat[1][1]);
380 #ifdef _DEBUG
381  if (scale[0] < ZERO_EPSILON || scale[1] < ZERO_EPSILON) {
382  common->Printf("Warning : unexpected scale==0 in TexMatToFakeTexCoords\n");
383  }
384 #endif
385  // compute rotate value
386  if (idMath::Fabs(texMat[0][0]) < ZERO_EPSILON)
387  {
388 #ifdef _DEBUG
389  // check brushprimit_texdef[1][0] is not zero
390  if (idMath::Fabs(texMat[1][0]) < ZERO_EPSILON) {
391  common->Printf("Warning : unexpected texdef[1][0]==0 in TexMatToFakeTexCoords\n");
392  }
393 #endif
394  // rotate is +-90
395  if (texMat[1][0] > 0) {
396  *rot = 90.0f;
397  }
398  else {
399  *rot = -90.0f;
400  }
401  }
402  else {
403  *rot = RAD2DEG(atan2(texMat[1][0], texMat[0][0]));
404  }
405 
406  shift[0] = -texMat[0][2];
407  shift[1] = texMat[1][2];
408 }
409 
410 //
411 // =======================================================================================================================
412 // compute back the texture matrix from fake shift scale rot the matrix returned must be understood as a qtexture_t
413 // with width=2 height=2 ( the default one )
414 // =======================================================================================================================
415 //
416 void FakeTexCoordsToTexMat(float shift[2], float rot, float scale[2], float texMat[2][3]) {
417  texMat[0][0] = scale[0] * cos(DEG2RAD(rot));
418  texMat[1][0] = scale[0] * sin(DEG2RAD(rot));
419  texMat[0][1] = -1.0f * scale[1] * sin(DEG2RAD(rot));
420  texMat[1][1] = scale[1] * cos(DEG2RAD(rot));
421  texMat[0][2] = -shift[0];
422  texMat[1][2] = shift[1];
423 }
424 
425 //
426 // =======================================================================================================================
427 // convert a texture matrix between two qtexture_t if NULL for qtexture_t, basic 2x2 texture is assumed ( straight
428 // mapping between s/t coordinates and geometric coordinates )
429 // =======================================================================================================================
430 //
431 void ConvertTexMatWithQTexture(float texMat1[2][3], const idMaterial *qtex1, float texMat2[2][3], const idMaterial *qtex2, float sScale = 1.0, float tScale = 1.0) {
432  float s1, s2;
433  s1 = (qtex1 ? static_cast<float>(qtex1->GetEditorImage()->uploadWidth) : 2.0f) / (qtex2 ? static_cast<float>(qtex2->GetEditorImage()->uploadWidth) : 2.0f);
434  s2 = (qtex1 ? static_cast<float>(qtex1->GetEditorImage()->uploadHeight) : 2.0f) / (qtex2 ? static_cast<float>(qtex2->GetEditorImage()->uploadHeight) : 2.0f);
435  s1 *= sScale;
436  s2 *= tScale;
437  texMat2[0][0] = s1 * texMat1[0][0];
438  texMat2[0][1] = s1 * texMat1[0][1];
439  texMat2[0][2] = s1 * texMat1[0][2];
440  texMat2[1][0] = s2 * texMat1[1][0];
441  texMat2[1][1] = s2 * texMat1[1][1];
442  texMat2[1][2] = s2 * texMat1[1][2];
443 }
444 
445 /*
446  =======================================================================================================================
447  =======================================================================================================================
448  */
449 void ConvertTexMatWithQTexture(brushprimit_texdef_t *texMat1, const idMaterial *qtex1, brushprimit_texdef_t *texMat2, const idMaterial *qtex2, float sScale, float tScale) {
450  ConvertTexMatWithQTexture(texMat1->coords, qtex1, texMat2->coords, qtex2, sScale, tScale);
451 }
452 
453 
454 //
455 // =======================================================================================================================
456 // texture locking
457 // =======================================================================================================================
458 //
459 void Face_MoveTexture_BrushPrimit(face_t *f, idVec3 delta) {
460  idVec3D texS, texT;
461  double tx, ty;
462  idVec3D M[3]; // columns of the matrix .. easier that way
463  double det;
464  idVec3D D[2];
465 
466  // compute plane axis base ( doesn't change with translation )
467  ComputeAxisBase(f->plane.Normal(), texS, texT);
468 
469  // compute translation vector in plane axis base
470  tx = DotProduct(delta, texS);
471  ty = DotProduct(delta, texT);
472 
473  // fill the data vectors
474  M[0][0] = tx;
475  M[0][1] = 1.0f + tx;
476  M[0][2] = tx;
477  M[1][0] = ty;
478  M[1][1] = ty;
479  M[1][2] = 1.0f + ty;
480  M[2][0] = 1.0f;
481  M[2][1] = 1.0f;
482  M[2][2] = 1.0f;
483  D[0][0] = f->brushprimit_texdef.coords[0][2];
484  D[0][1] = f->brushprimit_texdef.coords[0][0] + f->brushprimit_texdef.coords[0][2];
485  D[0][2] = f->brushprimit_texdef.coords[0][1] + f->brushprimit_texdef.coords[0][2];
486  D[1][0] = f->brushprimit_texdef.coords[1][2];
487  D[1][1] = f->brushprimit_texdef.coords[1][0] + f->brushprimit_texdef.coords[1][2];
488  D[1][2] = f->brushprimit_texdef.coords[1][1] + f->brushprimit_texdef.coords[1][2];
489 
490  // solve
491  det = SarrusDet(M[0], M[1], M[2]);
492  f->brushprimit_texdef.coords[0][0] = SarrusDet(D[0], M[1], M[2]) / det;
493  f->brushprimit_texdef.coords[0][1] = SarrusDet(M[0], D[0], M[2]) / det;
494  f->brushprimit_texdef.coords[0][2] = SarrusDet(M[0], M[1], D[0]) / det;
495  f->brushprimit_texdef.coords[1][0] = SarrusDet(D[1], M[1], M[2]) / det;
496  f->brushprimit_texdef.coords[1][1] = SarrusDet(M[0], D[1], M[2]) / det;
497  f->brushprimit_texdef.coords[1][2] = SarrusDet(M[0], M[1], D[1]) / det;
498 }
499 
500 //
501 // =======================================================================================================================
502 // call Face_MoveTexture_BrushPrimit after idVec3D computation
503 // =======================================================================================================================
504 //
505 void Select_ShiftTexture_BrushPrimit(face_t *f, float x, float y, bool autoAdjust) {
506 #if 0
507  idVec3D texS, texT;
508  idVec3D delta;
509  ComputeAxisBase(f->plane.normal, texS, texT);
510  VectorScale(texS, x, texS);
511  VectorScale(texT, y, texT);
512  VectorCopy(texS, delta);
513  VectorAdd(delta, texT, delta);
515 #else
516  if (autoAdjust) {
517  x /= f->d_texture->GetEditorImage()->uploadWidth;
518  y /= f->d_texture->GetEditorImage()->uploadHeight;
519  }
520  f->brushprimit_texdef.coords[0][2] += x;
521  f->brushprimit_texdef.coords[1][2] += y;
522  EmitBrushPrimitTextureCoordinates(f, f->face_winding);
523 #endif
524 }
525 
526 //
527 // =======================================================================================================================
528 // best fitted 2D vector is x.X+y.Y
529 // =======================================================================================================================
530 //
531 void ComputeBest2DVector(idVec3 v, idVec3 X, idVec3 Y, int &x, int &y) {
532  double sx, sy;
533  sx = DotProduct(v, X);
534  sy = DotProduct(v, Y);
535  if (idMath::Fabs(sy) > idMath::Fabs(sx)) {
536  x = 0;
537  if (sy > 0.0) {
538  y = 1;
539  }
540  else {
541  y = -1;
542  }
543  }
544  else {
545  y = 0;
546  if (sx > 0.0) {
547  x = 1;
548  }
549  else {
550  x = -1;
551  }
552  }
553 }
554 
555 //
556 // =======================================================================================================================
557 // in many case we know three points A,B,C in two axis base B1 and B2 and we want the matrix M so that A(B1) = T *
558 // A(B2) NOTE: 2D homogeneous space stuff NOTE: we don't do any check to see if there's a solution or we have a
559 // particular case .. need to make sure before calling NOTE: the third coord of the A,B,C point is ignored NOTE: see
560 // the commented out section to fill M and D ++timo TODO: update the other members to use this when possible
561 // =======================================================================================================================
562 //
563 void MatrixForPoints(idVec3D M[3], idVec3D D[2], brushprimit_texdef_t *T) {
564  //
565  // idVec3D M[3]; // columns of the matrix .. easier that way (the indexing is not
566  // standard! it's column-line .. later computations are easier that way)
567  //
568  double det;
569 
570  // idVec3D D[2];
571  M[2][0] = 1.0f;
572  M[2][1] = 1.0f;
573  M[2][2] = 1.0f;
574 #if 0
575 
576  // fill the data vectors
577  M[0][0] = A2[0];
578  M[0][1] = B2[0];
579  M[0][2] = C2[0];
580  M[1][0] = A2[1];
581  M[1][1] = B2[1];
582  M[1][2] = C2[1];
583  M[2][0] = 1.0f;
584  M[2][1] = 1.0f;
585  M[2][2] = 1.0f;
586  D[0][0] = A1[0];
587  D[0][1] = B1[0];
588  D[0][2] = C1[0];
589  D[1][0] = A1[1];
590  D[1][1] = B1[1];
591  D[1][2] = C1[1];
592 #endif
593  // solve
594  det = SarrusDet(M[0], M[1], M[2]);
595  T->coords[0][0] = SarrusDet(D[0], M[1], M[2]) / det;
596  T->coords[0][1] = SarrusDet(M[0], D[0], M[2]) / det;
597  T->coords[0][2] = SarrusDet(M[0], M[1], D[0]) / det;
598  T->coords[1][0] = SarrusDet(D[1], M[1], M[2]) / det;
599  T->coords[1][1] = SarrusDet(M[0], D[1], M[2]) / det;
600  T->coords[1][2] = SarrusDet(M[0], M[1], D[1]) / det;
601 }
602 
603 //
604 // =======================================================================================================================
605 // ++timo FIXME quick'n dirty hack, doesn't care about current texture settings (angle) can be improved .. bug #107311
606 // mins and maxs are the face bounding box ++timo fixme: we use the face info, mins and maxs are irrelevant
607 // =======================================================================================================================
608 //
609 void Face_FitTexture_BrushPrimit(face_t *f, idVec3 mins, idVec3 maxs, float height, float width) {
610  idVec3D BBoxSTMin, BBoxSTMax;
611  idWinding *w;
612  int i, j;
613  double val;
614  idVec3D M[3], D[2];
615 
616  // idVec3D N[2],Mf[2];
617  brushprimit_texdef_t N;
618  idVec3D Mf[2];
619 
620 
621 
622  //memset(f->brushprimit_texdef.coords, 0, sizeof(f->brushprimit_texdef.coords));
623  //f->brushprimit_texdef.coords[0][0] = 1.0f;
624  //f->brushprimit_texdef.coords[1][1] = 1.0f;
625  //ConvertTexMatWithQTexture(&f->brushprimit_texdef, NULL, &f->brushprimit_texdef, f->d_texture);
626  //
627  // we'll be working on a standardized texture size ConvertTexMatWithQTexture(
628  // &f->brushprimit_texdef, f->d_texture, &f->brushprimit_texdef, NULL ); compute
629  // the BBox in ST coords
630  //
631  EmitBrushPrimitTextureCoordinates(f, f->face_winding);
632  BBoxSTMin[0] = BBoxSTMin[1] = BBoxSTMin[2] = 999999;
633  BBoxSTMax[0] = BBoxSTMax[1] = BBoxSTMax[2] = -999999;
634 
635  w = f->face_winding;
636  if (w) {
637  for (i = 0; i < w->GetNumPoints(); i++) {
638  // AddPointToBounds in 2D on (S,T) coordinates
639  for (j = 0; j < 2; j++) {
640  val = (*w)[i][j + 3];
641  if (val < BBoxSTMin[j]) {
642  BBoxSTMin[j] = val;
643  }
644 
645  if (val > BBoxSTMax[j]) {
646  BBoxSTMax[j] = val;
647  }
648  }
649  }
650  }
651 
652  //
653  // we have the three points of the BBox (BBoxSTMin[0].BBoxSTMin[1])
654  // (BBoxSTMax[0],BBoxSTMin[1]) (BBoxSTMin[0],BBoxSTMax[1]) in ST space the BP
655  // matrix we are looking for gives (0,0) (nwidth,0) (0,nHeight) coordinates in
656  // (Sfit,Tfit) space to these three points we have A(Sfit,Tfit) = (0,0) = Mf *
657  // A(TexS,TexT) = N * M * A(TexS,TexT) = N * A(S,T) so we solve the system for N
658  // and then Mf = N * M
659  //
660  M[0][0] = BBoxSTMin[0];
661  M[0][1] = BBoxSTMax[0];
662  M[0][2] = BBoxSTMin[0];
663  M[1][0] = BBoxSTMin[1];
664  M[1][1] = BBoxSTMin[1];
665  M[1][2] = BBoxSTMax[1];
666  D[0][0] = 0.0f;
667  D[0][1] = width;
668  D[0][2] = 0.0f;
669  D[1][0] = 0.0f;
670  D[1][1] = 0.0f;
671  D[1][2] = height;
672  MatrixForPoints(M, D, &N);
673 
674 #if 0
675 
676  //
677  // FIT operation gives coordinates of three points of the bounding box in (S',T'),
678  // our target axis base A(S',T')=(0,0) B(S',T')=(nWidth,0) C(S',T')=(0,nHeight)
679  // and we have them in (S,T) axis base: A(S,T)=(BBoxSTMin[0],BBoxSTMin[1])
680  // B(S,T)=(BBoxSTMax[0],BBoxSTMin[1]) C(S,T)=(BBoxSTMin[0],BBoxSTMax[1]) we
681  // compute the N transformation so that: A(S',T') = N * A(S,T)
682  //
683  N[0][0] = (BBoxSTMax[0] - BBoxSTMin[0]) / width;
684  N[0][1] = 0.0f;
685  N[0][2] = BBoxSTMin[0];
686  N[1][0] = 0.0f;
687  N[1][1] = (BBoxSTMax[1] - BBoxSTMin[1]) / height;
688  N[1][2] = BBoxSTMin[1];
689 #endif
690  // the final matrix is the product (Mf stands for Mfit)
691  Mf[0][0] = N.coords[0][0] *
692  f->brushprimit_texdef.coords[0][0] +
693  N.coords[0][1] *
694  f->brushprimit_texdef.coords[1][0];
695  Mf[0][1] = N.coords[0][0] *
696  f->brushprimit_texdef.coords[0][1] +
697  N.coords[0][1] *
698  f->brushprimit_texdef.coords[1][1];
699  Mf[0][2] = N.coords[0][0] *
700  f->brushprimit_texdef.coords[0][2] +
701  N.coords[0][1] *
702  f->brushprimit_texdef.coords[1][2] +
703  N.coords[0][2];
704  Mf[1][0] = N.coords[1][0] *
705  f->brushprimit_texdef.coords[0][0] +
706  N.coords[1][1] *
707  f->brushprimit_texdef.coords[1][0];
708  Mf[1][1] = N.coords[1][0] *
709  f->brushprimit_texdef.coords[0][1] +
710  N.coords[1][1] *
711  f->brushprimit_texdef.coords[1][1];
712  Mf[1][2] = N.coords[1][0] *
713  f->brushprimit_texdef.coords[0][2] +
714  N.coords[1][1] *
715  f->brushprimit_texdef.coords[1][2] +
716  N.coords[1][2];
717 
718  // copy back
719  VectorCopy(Mf[0], f->brushprimit_texdef.coords[0]);
720  VectorCopy(Mf[1], f->brushprimit_texdef.coords[1]);
721 
722  //
723  // handle the texture size ConvertTexMatWithQTexture( &f->brushprimit_texdef,
724  // NULL, &f->brushprimit_texdef, f->d_texture );
725  //
726 }
727 
728 /*
729  =======================================================================================================================
730  =======================================================================================================================
731  */
732 void Face_ScaleTexture_BrushPrimit(face_t *face, float sS, float sT) {
733  if (!g_qeglobals.m_bBrushPrimitMode) {
734  Sys_Status("BP mode required\n");
735  return;
736  }
737 
738  brushprimit_texdef_t *pBP = &face->brushprimit_texdef;
739  BPMatScale(pBP->coords, sS, sT);
740 
741  // now emit the coordinates on the winding
742  EmitBrushPrimitTextureCoordinates(face, face->face_winding);
743 }
744 
745 /*
746  =======================================================================================================================
747  =======================================================================================================================
748  */
749 void Face_RotateTexture_BrushPrimit(face_t *face, float amount, idVec3 origin) {
750  brushprimit_texdef_t *pBP = &face->brushprimit_texdef;
751  if (amount) {
752  float x = pBP->coords[0][0];
753  float y = pBP->coords[0][1];
754  float x1 = pBP->coords[1][0];
755  float y1 = pBP->coords[1][1];
756  float s = sin( DEG2RAD( amount ) );
757  float c = cos( DEG2RAD( amount ) );
758  pBP->coords[0][0] = (((x - origin[0]) * c) - ((y - origin[1]) * s)) + origin[0];
759  pBP->coords[0][1] = (((x - origin[0]) * s) + ((y - origin[1]) * c)) + origin[1];
760  pBP->coords[1][0] = (((x1 - origin[0]) * c) - ((y1 - origin[1]) * s)) + origin[0];
761  pBP->coords[1][1] = (((x1 - origin[0]) * s) + ((y1 - origin[1]) * c)) + origin[1];
762  EmitBrushPrimitTextureCoordinates(face, face->face_winding);
763  }
764 }
765 
766 //
767 // TEXTURE LOCKING (Relevant to the editor only?)
768 // internally used for texture locking on rotation and flipping the general
769 // algorithm is the same for both lockings, it's only the geometric transformation
770 // part that changes so I wanted to keep it in a single function if there are more
771 // linear transformations that need the locking, going to a C++ or code pointer
772 // solution would be best (but right now I want to keep brush_primit.cpp striclty
773 // C)
774 //
776 
777 // rotation locking params
779 double txl_fDeg;
781 
782 // flip locking params
785 
786 /*
787  =======================================================================================================================
788  =======================================================================================================================
789  */
791  idVec3D Orig, texS, texT; // axis base of initial plane
792 
793  // used by transformation algo
794  idVec3D temp;
795  int j;
796  //idVec3D vRotate; // rotation vector
797 
798  idVec3D rOrig, rvecS, rvecT; // geometric transformation of (0,0) (1,0) (0,1) { initial plane axis base }
799  idVec3 rNormal;
800  idVec3D rtexS, rtexT; // axis base for the transformed plane
801  idVec3D lOrig, lvecS, lvecT; // [2] are not used ( but usefull for debugging )
802  idVec3D M[3];
803  double det;
804  idVec3D D[2];
805 
806  // silence compiler warnings
807  rOrig.Zero();
808  rvecS = rOrig;
809  rvecT = rOrig;
810  rNormal.x = rOrig.x;
811  rNormal.y = rOrig.y;
812  rNormal.z = rOrig.z;
813 
814  // compute plane axis base
815  ComputeAxisBase(f->plane.Normal(), texS, texT);
816  Orig.x = vec3_origin.x;
817  Orig.y = vec3_origin.y;
818  Orig.z = vec3_origin.z;
819 
820  //
821  // compute coordinates of (0,0) (1,0) (0,1) ( expressed in initial plane axis base
822  // ) after transformation (0,0) (1,0) (0,1) ( expressed in initial plane axis base
823  // ) <-> (0,0,0) texS texT ( expressed world axis base ) input: Orig, texS, texT
824  // (and the global locking params) ouput: rOrig, rvecS, rvecT, rNormal
825  //
826  if (txlock_bRotation) {
827 /*
828  // rotation vector
829  vRotate.x = vec3_origin.x;
830  vRotate.y = vec3_origin.y;
831  vRotate.z = vec3_origin.z;
832  vRotate[txl_nAxis] = txl_fDeg;
833  VectorRotate3Origin(Orig, vRotate, txl_vOrigin, rOrig);
834  VectorRotate3Origin(texS, vRotate, txl_vOrigin, rvecS);
835  VectorRotate3Origin(texT, vRotate, txl_vOrigin, rvecT);
836 
837  // compute normal of plane after rotation
838  VectorRotate3(f->plane.Normal(), vRotate, rNormal);
839 */
840  }
841  else {
842  VectorSubtract(Orig, txl_origin, temp);
843  for (j = 0; j < 3; j++) {
844  rOrig[j] = DotProduct(temp, txl_matrix[j]) + txl_origin[j];
845  }
846 
847  VectorSubtract(texS, txl_origin, temp);
848  for (j = 0; j < 3; j++) {
849  rvecS[j] = DotProduct(temp, txl_matrix[j]) + txl_origin[j];
850  }
851 
852  VectorSubtract(texT, txl_origin, temp);
853  for (j = 0; j < 3; j++) {
854  rvecT[j] = DotProduct(temp, txl_matrix[j]) + txl_origin[j];
855  }
856 
857  //
858  // we also need the axis base of the target plane, apply the transformation matrix
859  // to the normal too..
860  //
861  for (j = 0; j < 3; j++) {
862  rNormal[j] = DotProduct(f->plane, txl_matrix[j]);
863  }
864  }
865 
866  // compute rotated plane axis base
867  ComputeAxisBase(rNormal, rtexS, rtexT);
868 
869  // compute S/T coordinates of the three points in rotated axis base ( in M matrix )
870  lOrig[0] = DotProduct(rOrig, rtexS);
871  lOrig[1] = DotProduct(rOrig, rtexT);
872  lvecS[0] = DotProduct(rvecS, rtexS);
873  lvecS[1] = DotProduct(rvecS, rtexT);
874  lvecT[0] = DotProduct(rvecT, rtexS);
875  lvecT[1] = DotProduct(rvecT, rtexT);
876  M[0][0] = lOrig[0];
877  M[1][0] = lOrig[1];
878  M[2][0] = 1.0f;
879  M[0][1] = lvecS[0];
880  M[1][1] = lvecS[1];
881  M[2][1] = 1.0f;
882  M[0][2] = lvecT[0];
883  M[1][2] = lvecT[1];
884  M[2][2] = 1.0f;
885 
886  // fill data vector
887  D[0][0] = f->brushprimit_texdef.coords[0][2];
888  D[0][1] = f->brushprimit_texdef.coords[0][0] + f->brushprimit_texdef.coords[0][2];
889  D[0][2] = f->brushprimit_texdef.coords[0][1] + f->brushprimit_texdef.coords[0][2];
890  D[1][0] = f->brushprimit_texdef.coords[1][2];
891  D[1][1] = f->brushprimit_texdef.coords[1][0] + f->brushprimit_texdef.coords[1][2];
892  D[1][2] = f->brushprimit_texdef.coords[1][1] + f->brushprimit_texdef.coords[1][2];
893 
894  // solve
895  det = SarrusDet(M[0], M[1], M[2]);
896  f->brushprimit_texdef.coords[0][0] = SarrusDet(D[0], M[1], M[2]) / det;
897  f->brushprimit_texdef.coords[0][1] = SarrusDet(M[0], D[0], M[2]) / det;
898  f->brushprimit_texdef.coords[0][2] = SarrusDet(M[0], M[1], D[0]) / det;
899  f->brushprimit_texdef.coords[1][0] = SarrusDet(D[1], M[1], M[2]) / det;
900  f->brushprimit_texdef.coords[1][1] = SarrusDet(M[0], D[1], M[2]) / det;
901  f->brushprimit_texdef.coords[1][2] = SarrusDet(M[0], M[1], D[1]) / det;
902 }
903 
904 //
905 // =======================================================================================================================
906 // texture locking called before the points on the face are actually rotated
907 // =======================================================================================================================
908 //
909 void RotateFaceTexture_BrushPrimit(face_t *f, int nAxis, float fDeg, idVec3 vOrigin) {
910  // this is a placeholder to call the general texture locking algorithm
911  txlock_bRotation = true;
912  txl_nAxis = nAxis;
913  txl_fDeg = fDeg;
914  VectorCopy(vOrigin, txl_vOrigin);
916 }
917 
918 //
919 // =======================================================================================================================
920 // compute the new brush primit texture matrix for a transformation matrix and a flip order flag (change plane o
921 // rientation) this matches the select_matrix algo used in select.cpp this needs to be called on the face BEFORE any
922 // geometric transformation it will compute the texture matrix that will represent the same texture on the face after
923 // the geometric transformation is done
924 // =======================================================================================================================
925 //
926 void ApplyMatrix_BrushPrimit(face_t *f, idMat3 matrix, idVec3 origin) {
927  // this is a placeholder to call the general texture locking algorithm
928  txlock_bRotation = false;
929  VectorCopy(matrix[0], txl_matrix[0]);
930  VectorCopy(matrix[1], txl_matrix[1]);
931  VectorCopy(matrix[2], txl_matrix[2]);
932  VectorCopy(origin, txl_origin);
934 }
935 
936 //
937 // =======================================================================================================================
938 // don't do C==A!
939 // =======================================================================================================================
940 //
941 void BPMatMul(float A[2][3], float B[2][3], float C[2][3]) {
942  C[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0];
943  C[1][0] = A[1][0] * B[0][0] + A[1][1] * B[1][0];
944  C[0][1] = A[0][0] * B[0][1] + A[0][1] * B[1][1];
945  C[1][1] = A[1][0] * B[0][1] + A[1][1] * B[1][1];
946  C[0][2] = A[0][0] * B[0][2] + A[0][1] * B[1][2] + A[0][2];
947  C[1][2] = A[1][0] * B[0][2] + A[1][1] * B[1][2] + A[1][2];
948 }
949 
950 /*
951  =======================================================================================================================
952  =======================================================================================================================
953  */
954 void BPMatDump(float A[2][3]) {
955  common->Printf("%g %g %g\n%g %g %g\n0 0 1\n", A[0][0], A[0][1], A[0][2], A[1][0], A[1][1], A[1][2]);
956 }
957 
958 /*
959  =======================================================================================================================
960  =======================================================================================================================
961  */
962 void BPMatRotate(float A[2][3], float theta) {
963  float m[2][3];
964  float aux[2][3];
965  memset(&m, 0, sizeof (float) *6);
966  m[0][0] = cos( DEG2RAD( theta ) );
967  m[0][1] = -sin( DEG2RAD( theta ) );
968  m[1][0] = -m[0][1];
969  m[1][1] = m[0][0];
970  BPMatMul(A, m, aux);
971  BPMatCopy(aux, A);
972 }
973 
974 void Face_GetScale_BrushPrimit(face_t *face, float *s, float *t, float *rot) {
975  idVec3D texS, texT;
976  ComputeAxisBase(face->plane.Normal(), texS, texT);
977 
978  if (face == NULL || face->face_winding == NULL) {
979  return;
980  }
981  // find ST coordinates for the center of the face
982  double Os = 0, Ot = 0;
983  for (int i = 0; i < face->face_winding->GetNumPoints(); i++) {
984  Os += DotProduct((*face->face_winding)[i], texS);
985  Ot += DotProduct((*face->face_winding)[i], texT);
986  }
987 
988  Os /= face->face_winding->GetNumPoints();
989  Ot /= face->face_winding->GetNumPoints();
990 
991  brushprimit_texdef_t *pBP = &face->brushprimit_texdef;
992 
993  // here we have a special case, M is a translation and it's inverse is easy
994  float BPO[2][3];
995  float aux[2][3];
996  float m[2][3];
997  memset(&m, 0, sizeof (float) *6);
998  m[0][0] = 1;
999  m[1][1] = 1;
1000  m[0][2] = -Os;
1001  m[1][2] = -Ot;
1002  BPMatMul(m, pBP->coords, aux);
1003  m[0][2] = Os;
1004  m[1][2] = Ot; // now M^-1
1005  BPMatMul(aux, m, BPO);
1006 
1007  // apply a given scale (on S and T)
1008  ConvertTexMatWithQTexture(BPO, face->d_texture, aux, NULL);
1009 
1010  *s = idMath::Sqrt(aux[0][0] * aux[0][0] + aux[1][0] * aux[1][0]);
1011  *t = idMath::Sqrt(aux[0][1] * aux[0][1] + aux[1][1] * aux[1][1]);
1012 
1013  // compute rotate value
1014  if (idMath::Fabs(face->brushprimit_texdef.coords[0][0]) < ZERO_EPSILON)
1015  {
1016  // rotate is +-90
1017  if (face->brushprimit_texdef.coords[1][0] > 0) {
1018  *rot = 90.0f;
1019  }
1020  else {
1021  *rot = -90.0f;
1022  }
1023  }
1024  else {
1025  *rot = RAD2DEG(atan2(face->brushprimit_texdef.coords[1][0] / (*s) ? (*s) : 1.0f, face->brushprimit_texdef.coords[0][0] / (*t) ? (*t) : 1.0f));
1026  }
1027 
1028 
1029 }
1030 
1031 /*
1032  =======================================================================================================================
1033  =======================================================================================================================
1034  */
1035 void Face_SetExplicitScale_BrushPrimit(face_t *face, float s, float t) {
1036  idVec3D texS, texT;
1037  ComputeAxisBase(face->plane.Normal(), texS, texT);
1038 
1039  // find ST coordinates for the center of the face
1040  double Os = 0, Ot = 0;
1041 
1042  for (int i = 0; i < face->face_winding->GetNumPoints(); i++) {
1043  Os += DotProduct((*face->face_winding)[i], texS);
1044  Ot += DotProduct((*face->face_winding)[i], texT);
1045  }
1046 
1047  Os /= face->face_winding->GetNumPoints();
1048  Ot /= face->face_winding->GetNumPoints();
1049 
1050  brushprimit_texdef_t *pBP = &face->brushprimit_texdef;
1051 
1052  // here we have a special case, M is a translation and it's inverse is easy
1053  float BPO[2][3];
1054  float aux[2][3];
1055  float m[2][3];
1056  memset(&m, 0, sizeof (float) *6);
1057  m[0][0] = 1;
1058  m[1][1] = 1;
1059  m[0][2] = -Os;
1060  m[1][2] = -Ot;
1061  BPMatMul(m, pBP->coords, aux);
1062  m[0][2] = Os;
1063  m[1][2] = Ot; // now M^-1
1064  BPMatMul(aux, m, BPO);
1065 
1066  // apply a given scale (on S and T)
1067  ConvertTexMatWithQTexture(BPO, face->d_texture, aux, NULL);
1068 
1069  // reset the scale (normalize the matrix)
1070  double v1, v2;
1071  v1 = idMath::Sqrt(aux[0][0] * aux[0][0] + aux[1][0] * aux[1][0]);
1072  v2 = idMath::Sqrt(aux[0][1] * aux[0][1] + aux[1][1] * aux[1][1]);
1073 
1074  if (s == 0.0) {
1075  s = v1;
1076  }
1077  if (t == 0.0) {
1078  t = v2;
1079  }
1080 
1081  double sS, sT;
1082 
1083  // put the values for scale on S and T here:
1084  sS = s / v1;
1085  sT = t / v2;
1086  aux[0][0] *= sS;
1087  aux[1][0] *= sS;
1088  aux[0][1] *= sT;
1089  aux[1][1] *= sT;
1090  ConvertTexMatWithQTexture(aux, NULL, BPO, face->d_texture);
1091  BPMatMul(m, BPO, aux); // m is M^-1
1092  m[0][2] = -Os;
1093  m[1][2] = -Ot;
1094  BPMatMul(aux, m, pBP->coords);
1095 
1096  // now emit the coordinates on the winding
1097  EmitBrushPrimitTextureCoordinates(face, face->face_winding);
1098 }
1099 
1100 
1101 void Face_FlipTexture_BrushPrimit(face_t *f, bool y) {
1102 
1103  float s, t, rot;
1104  Face_GetScale_BrushPrimit(f, &s, &t, &rot);
1105  if (y) {
1107  } else {
1109  }
1110 #if 0
1111 
1112  idVec3D texS, texT;
1113  ComputeAxisBase(f->plane.normal, texS, texT);
1114  double Os = 0, Ot = 0;
1115  for (int i = 0; i < f->face_winding->numpoints; i++) {
1116  Os += DotProduct(f->face_winding->p[i], texS);
1117  Ot += DotProduct(f->face_winding->p[i], texT);
1118  }
1119 
1120  Ot = abs(Ot);
1121  Ot *= t;
1122  Ot /= f->d_texture->GetEditorImage()->uploadHeight;
1123 
1124  Os = abs(Os);
1125  Os *= s;
1126  Os /= f->d_texture->GetEditorImage()->uploadWidth;
1127 
1128 
1129  if (y) {
1130  Face_FitTexture_BrushPrimit(f, texS, texT, -Ot, 1.0);
1131  } else {
1132  Face_FitTexture_BrushPrimit(f, texS, texT, 1.0, -Os);
1133  }
1134  EmitBrushPrimitTextureCoordinates(f, f->face_winding);
1135 #endif
1136 }
1137 
1138 void Brush_FlipTexture_BrushPrimit(brush_t *b, bool y) {
1139  for (face_t *f = b->brush_faces; f; f = f->next) {
1141  }
1142 }
1143 
1144 void Face_SetAxialScale_BrushPrimit(face_t *face, bool y) {
1145 
1146  if (!face) {
1147  return;
1148  }
1149 
1150  if (!face->face_winding) {
1151  return;
1152  }
1153 
1154  //float oldS, oldT, oldR;
1155  //Face_GetScale_BrushPrimit(face, &oldS, &oldT, &oldR);
1156 
1157  idVec3D min, max;
1158  min.x = min.y = min.z = 999999.0;
1159  max.x = max.y = max.z = -999999.0;
1160  for (int i = 0; i < face->face_winding->GetNumPoints(); i++) {
1161  for (int j = 0; j < 3; j++) {
1162  if ((*face->face_winding)[i][j] < min[j]) {
1163  min[j] = (*face->face_winding)[i][j];
1164  }
1165  if ((*face->face_winding)[i][j] > max[j]) {
1166  max[j] = (*face->face_winding)[i][j];
1167  }
1168  }
1169  }
1170 
1171  idVec3 len;
1172 
1173  if (g_bAxialMode) {
1174  if (g_axialAnchor >= 0 && g_axialAnchor < face->face_winding->GetNumPoints() &&
1175  g_axialDest >= 0 && g_axialDest < face->face_winding->GetNumPoints() &&
1177  len = (*face->face_winding)[g_axialDest].ToVec3() - (*face->face_winding)[g_axialAnchor].ToVec3();
1178  } else {
1179  return;
1180  }
1181  } else {
1182  if (y) {
1183  len = (*face->face_winding)[2].ToVec3() - (*face->face_winding)[1].ToVec3();
1184  } else {
1185  len = (*face->face_winding)[1].ToVec3() - (*face->face_winding)[0].ToVec3();
1186  }
1187  }
1188 
1189  double dist = len.Length();
1190  double width = idMath::Fabs(max.x - min.x);
1191  double height = idMath::Fabs(max.z - min.z);
1192 
1193  //len = maxs[2] - mins[2];
1194  //double yDist = len.Length();
1195 
1196 
1197  if (dist != 0.0) {
1198  if (dist > face->d_texture->GetEditorImage()->uploadHeight) {
1199  height = 1.0 / (dist / face->d_texture->GetEditorImage()->uploadHeight);
1200  } else {
1201  height /= dist;
1202  }
1203  if (dist > face->d_texture->GetEditorImage()->uploadWidth) {
1204  width = 1.0 / (dist / face->d_texture->GetEditorImage()->uploadWidth);
1205  } else {
1206  width /= dist;
1207  }
1208  }
1209 
1210  if (y) {
1211  Face_SetExplicitScale_BrushPrimit(face, 0.0, height);
1212  //oldT = oldT / height * 10;
1213  //Select_ShiftTexture_BrushPrimit(face, 0, -oldT, true);
1214  } else {
1215  Face_SetExplicitScale_BrushPrimit(face, width, 0.0);
1216  }
1217 /*
1218  common->Printf("Face x: %f y: %f xr: %f yr: %f\n", x, y, xRatio, yRatio);
1219  common->Printf("Texture x: %i y: %i \n",face->d_texture->GetEditorImage()->uploadWidth, face->d_texture->GetEditorImage()->uploadHeight);
1220 
1221  idVec3D texS, texT;
1222  ComputeAxisBase(face->plane.normal, texS, texT);
1223  float Os = 0, Ot = 0;
1224  for (int i = 0; i < face->face_winding->numpoints; i++) {
1225  Os += DotProduct(face->face_winding->p[i], texS);
1226  Ot += DotProduct(face->face_winding->p[i], texT);
1227  }
1228 
1229  common->Printf("Face2 x: %f y: %f \n", Os, Ot);
1230  Os /= face->face_winding->numpoints;
1231  Ot /= face->face_winding->numpoints;
1232 
1233 
1234  //Os /= face->face_winding->numpoints;
1235  //Ot /= face->face_winding->numpoints;
1236 
1237 */
1238 }
1239 
void TexMatToFakeTexCoords(float texMat[2][3], float shift[2], float *rot, float scale[2])
#define strcmp
Definition: Str.h:41
idImage * GetEditorImage(void) const
Definition: Material.cpp:190
#define min(a, b)
face_t * Face_Alloc(void)
void FakeTexCoordsToTexMat(float shift[2], float rot, float scale[2], float texMat[2][3])
void BPMatMul(float A[2][3], float B[2][3], float C[2][3])
int txl_nAxis
void ApplyMatrix_BrushPrimit(face_t *f, idMat3 matrix, idVec3 origin)
double txl_fDeg
const GLdouble * v
Definition: glext.h:2936
GLuint GLenum matrix
Definition: glext.h:5179
void Face_SetExplicitScale_BrushPrimit(face_t *face, float s, float t)
#define VectorSubtract(a, b, c)
Definition: Vector.h:1995
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:4804
void ComputeAxisBase(idVec3 &normal, idVec3D &texS, idVec3D &texT)
GLenum GLint GLint y
Definition: glext.h:2849
float z
Definition: Vector.h:320
void Face_ScaleTexture_BrushPrimit(face_t *face, float sS, float sT)
#define VectorCopy(a, b)
Definition: Vector.h:1999
void Sys_Status(const char *psz, int part)
Definition: Radiant.cpp:465
Definition: Vector.h:316
static float Sqrt(float x)
Definition: Math.h:302
Definition: eax4.h:1412
#define VectorAdd(a, b, c)
Definition: Vector.h:1996
GLdouble s
Definition: glext.h:2935
GLenum GLsizei len
Definition: glext.h:3472
Definition: eax4.h:1413
Definition: eax4.h:1412
float x
Definition: Vector.h:318
GLenum GLint x
Definition: glext.h:2849
int i
Definition: process.py:33
#define ZERO_EPSILON
#define C2
void EmitTextureCoordinates(idVec5 &xyzst, const idMaterial *q, face_t *f, bool force)
void ParseEpair(idDict *dict)
void Face_GetScale_BrushPrimit(face_t *face, float *s, float *t, float *rot)
bool txlock_bRotation
int g_axialDest
Definition: CamWnd.cpp:50
GLfloat GLfloat GLfloat v2
Definition: glext.h:3608
void ComputeBest2DVector(idVec3 v, idVec3 X, idVec3 Y, int &x, int &y)
void Select_ShiftTexture_BrushPrimit(face_t *f, float x, float y, bool autoAdjust)
int GetNumPoints(void) const
Definition: Winding.h:238
GLuint index
Definition: glext.h:3476
const GLubyte * c
Definition: glext.h:4677
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
float Length(void) const
Definition: Vector.h:631
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
GLbyte ty
Definition: glext.h:4528
idVec3D txl_matrix[3]
static float Fabs(float f)
Definition: Math.h:779
idCommon * common
Definition: Common.cpp:206
void BPMatDump(float A[2][3])
#define NULL
Definition: Lib.h:88
float y
Definition: Vector.h:319
void BPMatRotate(float A[2][3], float theta)
void Face_FlipTexture_BrushPrimit(face_t *f, bool y)
Definition: Plane.h:71
void Face_MoveTexture_BrushPrimit(face_t *f, idVec3 delta)
void BrushPrimit_Parse(brush_t *b, bool newFormat, const idVec3 origin)
GLenum GLsizei width
Definition: glext.h:2846
GLubyte GLubyte GLubyte a
Definition: glext.h:4662
virtual void Printf(const char *fmt,...) id_attribute((format(printf
#define DEG2RAD(a)
Definition: Math.h:56
Definition: eax4.h:1412
void Face_FitTexture_BrushPrimit(face_t *f, idVec3 mins, idVec3 maxs, float height, float width)
GLfloat GLfloat v1
Definition: glext.h:3607
GLenum GLsizei GLsizei height
Definition: glext.h:2856
int uploadHeight
Definition: Image.h:249
GLubyte GLubyte b
Definition: glext.h:4662
double & operator[](const int index)
int uploadWidth
Definition: Image.h:249
void RotateFaceTexture_BrushPrimit(face_t *f, int nAxis, float fDeg, idVec3 vOrigin)
Definition: Matrix.h:333
void ConvertTexMatWithQTexture(float texMat1[2][3], const idMaterial *qtex1, float texMat2[2][3], const idMaterial *qtex2, float sScale=1.0, float tScale=1.0)
tuple f
Definition: idal.py:89
int g_axialAnchor
Definition: CamWnd.cpp:49
#define RAD2DEG(a)
Definition: Math.h:57
GLdouble y1
Definition: qgl.h:415
void BaseForPlane(const idVec3 &normal, const float dist)
Definition: Winding.cpp:66
idVec3D txl_vOrigin
void Brush_FlipTexture_BrushPrimit(brush_t *b, bool y)
#define DotProduct(a, b)
Definition: Vector.h:1994
void Face_SetAxialScale_BrushPrimit(face_t *face, bool y)
Definition: eax4.h:1413
void MatrixForPoints(idVec3D M[3], idVec3D D[2], brushprimit_texdef_t *T)
void TextureLockTransformation_BrushPrimit(face_t *f)
#define VectorScale(v, s, o)
Definition: Vector.h:1997
GLint j
Definition: qgl.h:264
char * va(const char *fmt,...)
Definition: Str.cpp:1568
#define max(x, y)
Definition: os.h:70
GLdouble GLdouble z
Definition: glext.h:3067
Definition: eax4.h:1413
idVec3D txl_origin
bool g_bAxialMode
Definition: CamWnd.cpp:51
void Face_RotateTexture_BrushPrimit(face_t *face, float amount, idVec3 origin)
void EmitBrushPrimitTextureCoordinates(face_t *f, idWinding *w, patchMesh_t *patch)
void FaceToBrushPrimitFace(face_t *f)
GLdouble GLdouble t
Definition: glext.h:2943
double SarrusDet(idVec3D a, idVec3D b, idVec3D c)