EditorBrushPrimit.cpp 41 KB

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