1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- 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.
- 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.
- ===========================================================================
- */
- #include "../../idlib/precompiled.h"
- #pragma hdrstop
- #include "qe3.h"
- #define ZERO_EPSILON 1.0E-6
- class idVec3D {
- public:
- double x, y, z;
- double & operator[]( const int index ) {
- return (&x)[index];
- }
- void Zero() {
- x = y = z = 0.0;
- }
- };
- //
- // =======================================================================================================================
- // compute a determinant using Sarrus rule ++timo "inline" this with a macro NOTE:: the three idVec3D are understood as
- // columns of the matrix
- // =======================================================================================================================
- //
- double SarrusDet(idVec3D a, idVec3D b, idVec3D c) {
- 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];
- }
- //
- // =======================================================================================================================
- // ++timo replace everywhere texX by texS etc. ( > and in q3map !) NOTE:: ComputeAxisBase here and in q3map code must
- // always BE THE SAME ! WARNING:: special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere
- // when x == 0 rotation by (0,RotY,RotZ) assigns X to normal
- // =======================================================================================================================
- //
- void ComputeAxisBase(idVec3 &normal, idVec3D &texS, idVec3D &texT) {
- double RotY, RotZ;
- // do some cleaning
- if (idMath::Fabs(normal[0]) < 1e-6) {
- normal[0] = 0.0f;
- }
- if (idMath::Fabs(normal[1]) < 1e-6) {
- normal[1] = 0.0f;
- }
- if (idMath::Fabs(normal[2]) < 1e-6) {
- normal[2] = 0.0f;
- }
- RotY = -atan2(normal[2], idMath::Sqrt(normal[1] * normal[1] + normal[0] * normal[0]));
- RotZ = atan2(normal[1], normal[0]);
- // rotate (0,1,0) and (0,0,1) to compute texS and texT
- texS[0] = -sin(RotZ);
- texS[1] = cos(RotZ);
- texS[2] = 0;
- // the texT vector is along -Z ( T texture coorinates axis )
- texT[0] = -sin(RotY) * cos(RotZ);
- texT[1] = -sin(RotY) * sin(RotZ);
- texT[2] = -cos(RotY);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void FaceToBrushPrimitFace(face_t *f) {
- idVec3D texX, texY;
- idVec3D proj;
- // ST of (0,0) (1,0) (0,1)
- idVec5 ST[3]; // [ point index ] [ xyz ST ]
- //
- // ++timo not used as long as brushprimit_texdef and texdef are static
- // f->brushprimit_texdef.contents=f->texdef.contents;
- // f->brushprimit_texdef.flags=f->texdef.flags;
- // f->brushprimit_texdef.value=f->texdef.value;
- // strcpy(f->brushprimit_texdef.name,f->texdef.name);
- //
- #ifdef _DEBUG
- if (f->plane[0] == 0.0f && f->plane[1] == 0.0f && f->plane[2] == 0.0f) {
- common->Printf("Warning : f->plane.normal is (0,0,0) in FaceToBrushPrimitFace\n");
- }
- // check d_texture
- if (!f->d_texture) {
- common->Printf("Warning : f.d_texture is NULL in FaceToBrushPrimitFace\n");
- return;
- }
- #endif
- // compute axis base
- ComputeAxisBase(f->plane.Normal(), texX, texY);
- // compute projection vector
- VectorCopy( f->plane, proj );
- VectorScale(proj, -f->plane[3], proj);
- //
- // (0,0) in plane axis base is (0,0,0) in world coordinates + projection on the
- // affine plane (1,0) in plane axis base is texX in world coordinates + projection
- // on the affine plane (0,1) in plane axis base is texY in world coordinates +
- // projection on the affine plane use old texture code to compute the ST coords of
- // these points
- //
- VectorCopy(proj, ST[0]);
- EmitTextureCoordinates(ST[0], f->d_texture, f);
- VectorCopy(texX, ST[1]);
- VectorAdd(ST[1], proj, ST[1]);
- EmitTextureCoordinates(ST[1], f->d_texture, f);
- VectorCopy(texY, ST[2]);
- VectorAdd(ST[2], proj, ST[2]);
- EmitTextureCoordinates(ST[2], f->d_texture, f);
- // compute texture matrix
- f->brushprimit_texdef.coords[0][2] = ST[0][3];
- f->brushprimit_texdef.coords[1][2] = ST[0][4];
- f->brushprimit_texdef.coords[0][0] = ST[1][3] - f->brushprimit_texdef.coords[0][2];
- f->brushprimit_texdef.coords[1][0] = ST[1][4] - f->brushprimit_texdef.coords[1][2];
- f->brushprimit_texdef.coords[0][1] = ST[2][3] - f->brushprimit_texdef.coords[0][2];
- f->brushprimit_texdef.coords[1][1] = ST[2][4] - f->brushprimit_texdef.coords[1][2];
- }
- //
- // =======================================================================================================================
- // compute texture coordinates for the winding points
- // =======================================================================================================================
- //
- void EmitBrushPrimitTextureCoordinates(face_t *f, idWinding *w, patchMesh_t *patch) {
- idVec3D texX, texY;
- double x, y;
- if (f== NULL || (w == NULL && patch == NULL)) {
- return;
- }
- // compute axis base
- ComputeAxisBase(f->plane.Normal(), texX, texY);
- //
- // in case the texcoords matrix is empty, build a default one same behaviour as if
- // scale[0]==0 && scale[1]==0 in old code
- //
- if ( f->brushprimit_texdef.coords[0][0] == 0 &&
- f->brushprimit_texdef.coords[1][0] == 0 &&
- f->brushprimit_texdef.coords[0][1] == 0 &&
- f->brushprimit_texdef.coords[1][1] == 0 ) {
- f->brushprimit_texdef.coords[0][0] = 1.0f;
- f->brushprimit_texdef.coords[1][1] = 1.0f;
- ConvertTexMatWithQTexture(&f->brushprimit_texdef, NULL, &f->brushprimit_texdef, f->d_texture);
- }
- int i;
- if (w) {
- for (i = 0; i < w->GetNumPoints(); i++) {
- x = DotProduct((*w)[i], texX);
- y = DotProduct((*w)[i], texY);
- (*w)[i][3] = f->brushprimit_texdef.coords[0][0] * x + f->brushprimit_texdef.coords[0][1] * y + f->brushprimit_texdef.coords[0][2];
- (*w)[i][4] = f->brushprimit_texdef.coords[1][0] * x + f->brushprimit_texdef.coords[1][1] * y + f->brushprimit_texdef.coords[1][2];
- }
- }
-
- if (patch) {
- int j;
- for ( i = 0; i < patch->width; i++ ) {
- for ( j = 0; j < patch->height; j++ ) {
- x = DotProduct(patch->ctrl(i, j).xyz, texX);
- y = DotProduct(patch->ctrl(i, j).xyz, texY);
- 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];
- 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];
- }
- }
- }
- }
- //
- // =======================================================================================================================
- // parse a brush in brush primitive format
- // =======================================================================================================================
- //
- void BrushPrimit_Parse(brush_t *b, bool newFormat, const idVec3 origin) {
- face_t *f;
- int i, j;
- GetToken(true);
- if (strcmp(token, "{")) {
- Warning("parsing brush primitive");
- return;
- }
- do {
- if (!GetToken(true)) {
- break;
- }
- if (!strcmp(token, "}")) {
- break;
- }
- // reading of b->epairs if any
- if (strcmp(token, "(")) {
- ParseEpair(&b->epairs);
- }
- else { // it's a face
- f = Face_Alloc();
- f->next = NULL;
- if (!b->brush_faces) {
- b->brush_faces = f;
- }
- else {
- face_t *scan;
- for (scan = b->brush_faces; scan->next; scan = scan->next)
- ;
- scan->next = f;
- }
- if (newFormat) {
- // read the three point plane definition
- idPlane plane;
- for (j = 0; j < 4; j++) {
- GetToken(false);
- plane[j] = atof(token);
- }
- f->plane = plane;
- f->originalPlane = plane;
- f->dirty = false;
- //idWinding *w = Brush_MakeFaceWinding(b, f, true);
- idWinding w;
- w.BaseForPlane( plane );
- for (j = 0; j < 3; j++) {
- f->planepts[j].x = w[j].x + origin.x;
- f->planepts[j].y = w[j].y + origin.y;
- f->planepts[j].z = w[j].z + origin.z;
- }
- GetToken(false);
- }
- else {
- for (i = 0; i < 3; i++) {
- if (i != 0) {
- GetToken(true);
- }
- if (strcmp(token, "(")) {
- Warning("parsing brush");
- return;
- }
- for (j = 0; j < 3; j++) {
- GetToken(false);
- f->planepts[i][j] = atof(token);
- }
- GetToken(false);
- if (strcmp(token, ")")) {
- Warning("parsing brush");
- return;
- }
- }
- }
- // texture coordinates
- GetToken(false);
- if (strcmp(token, "(")) {
- Warning("parsing brush primitive");
- return;
- }
- GetToken(false);
- if (strcmp(token, "(")) {
- Warning("parsing brush primitive");
- return;
- }
- for (j = 0; j < 3; j++) {
- GetToken(false);
- f->brushprimit_texdef.coords[0][j] = atof(token);
- }
- GetToken(false);
- if (strcmp(token, ")")) {
- Warning("parsing brush primitive");
- return;
- }
- GetToken(false);
- if (strcmp(token, "(")) {
- Warning("parsing brush primitive");
- return;
- }
- for (j = 0; j < 3; j++) {
- GetToken(false);
- f->brushprimit_texdef.coords[1][j] = atof(token);
- }
- GetToken(false);
- if (strcmp(token, ")")) {
- Warning("parsing brush primitive");
- return;
- }
- GetToken(false);
- if (strcmp(token, ")")) {
- Warning("parsing brush primitive");
- return;
- }
- // read the texturedef
- GetToken(false);
- // strcpy(f->texdef.name, token);
- if (g_qeglobals.mapVersion < 2.0) {
- f->texdef.SetName(va("textures/%s", token));
- }
- else {
- f->texdef.SetName(token);
- }
- if (TokenAvailable()) {
- GetToken(false);
- GetToken(false);
- GetToken(false);
- f->texdef.value = atoi(token);
- }
- }
- } while (1);
- }
- //
- // =======================================================================================================================
- // compute a fake shift scale rot representation from the texture matrix these shift scale rot values are to be
- // understood in the local axis base
- // =======================================================================================================================
- //
- void TexMatToFakeTexCoords(float texMat[2][3], float shift[2], float *rot, float scale[2])
- {
- #ifdef _DEBUG
- // check this matrix is orthogonal
- if (idMath::Fabs(texMat[0][0] * texMat[0][1] + texMat[1][0] * texMat[1][1]) > ZERO_EPSILON) {
- common->Printf("Warning : non orthogonal texture matrix in TexMatToFakeTexCoords\n");
- }
- #endif
- scale[0] = idMath::Sqrt(texMat[0][0] * texMat[0][0] + texMat[1][0] * texMat[1][0]);
- scale[1] = idMath::Sqrt(texMat[0][1] * texMat[0][1] + texMat[1][1] * texMat[1][1]);
- #ifdef _DEBUG
- if (scale[0] < ZERO_EPSILON || scale[1] < ZERO_EPSILON) {
- common->Printf("Warning : unexpected scale==0 in TexMatToFakeTexCoords\n");
- }
- #endif
- // compute rotate value
- if (idMath::Fabs(texMat[0][0]) < ZERO_EPSILON)
- {
- #ifdef _DEBUG
- // check brushprimit_texdef[1][0] is not zero
- if (idMath::Fabs(texMat[1][0]) < ZERO_EPSILON) {
- common->Printf("Warning : unexpected texdef[1][0]==0 in TexMatToFakeTexCoords\n");
- }
- #endif
- // rotate is +-90
- if (texMat[1][0] > 0) {
- *rot = 90.0f;
- }
- else {
- *rot = -90.0f;
- }
- }
- else {
- *rot = RAD2DEG(atan2(texMat[1][0], texMat[0][0]));
- }
- shift[0] = -texMat[0][2];
- shift[1] = texMat[1][2];
- }
- //
- // =======================================================================================================================
- // compute back the texture matrix from fake shift scale rot the matrix returned must be understood as a qtexture_t
- // with width=2 height=2 ( the default one )
- // =======================================================================================================================
- //
- void FakeTexCoordsToTexMat(float shift[2], float rot, float scale[2], float texMat[2][3]) {
- texMat[0][0] = scale[0] * cos(DEG2RAD(rot));
- texMat[1][0] = scale[0] * sin(DEG2RAD(rot));
- texMat[0][1] = -1.0f * scale[1] * sin(DEG2RAD(rot));
- texMat[1][1] = scale[1] * cos(DEG2RAD(rot));
- texMat[0][2] = -shift[0];
- texMat[1][2] = shift[1];
- }
- //
- // =======================================================================================================================
- // convert a texture matrix between two qtexture_t if NULL for qtexture_t, basic 2x2 texture is assumed ( straight
- // mapping between s/t coordinates and geometric coordinates )
- // =======================================================================================================================
- //
- void ConvertTexMatWithQTexture(float texMat1[2][3], const idMaterial *qtex1, float texMat2[2][3], const idMaterial *qtex2, float sScale = 1.0, float tScale = 1.0) {
- float s1, s2;
- s1 = (qtex1 ? static_cast<float>(qtex1->GetEditorImage()->uploadWidth) : 2.0f) / (qtex2 ? static_cast<float>(qtex2->GetEditorImage()->uploadWidth) : 2.0f);
- s2 = (qtex1 ? static_cast<float>(qtex1->GetEditorImage()->uploadHeight) : 2.0f) / (qtex2 ? static_cast<float>(qtex2->GetEditorImage()->uploadHeight) : 2.0f);
- s1 *= sScale;
- s2 *= tScale;
- texMat2[0][0] = s1 * texMat1[0][0];
- texMat2[0][1] = s1 * texMat1[0][1];
- texMat2[0][2] = s1 * texMat1[0][2];
- texMat2[1][0] = s2 * texMat1[1][0];
- texMat2[1][1] = s2 * texMat1[1][1];
- texMat2[1][2] = s2 * texMat1[1][2];
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void ConvertTexMatWithQTexture(brushprimit_texdef_t *texMat1, const idMaterial *qtex1, brushprimit_texdef_t *texMat2, const idMaterial *qtex2, float sScale, float tScale) {
- ConvertTexMatWithQTexture(texMat1->coords, qtex1, texMat2->coords, qtex2, sScale, tScale);
- }
- //
- // =======================================================================================================================
- // texture locking
- // =======================================================================================================================
- //
- void Face_MoveTexture_BrushPrimit(face_t *f, idVec3 delta) {
- idVec3D texS, texT;
- double tx, ty;
- idVec3D M[3]; // columns of the matrix .. easier that way
- double det;
- idVec3D D[2];
- // compute plane axis base ( doesn't change with translation )
- ComputeAxisBase(f->plane.Normal(), texS, texT);
- // compute translation vector in plane axis base
- tx = DotProduct(delta, texS);
- ty = DotProduct(delta, texT);
- // fill the data vectors
- M[0][0] = tx;
- M[0][1] = 1.0f + tx;
- M[0][2] = tx;
- M[1][0] = ty;
- M[1][1] = ty;
- M[1][2] = 1.0f + ty;
- M[2][0] = 1.0f;
- M[2][1] = 1.0f;
- M[2][2] = 1.0f;
- D[0][0] = f->brushprimit_texdef.coords[0][2];
- D[0][1] = f->brushprimit_texdef.coords[0][0] + f->brushprimit_texdef.coords[0][2];
- D[0][2] = f->brushprimit_texdef.coords[0][1] + f->brushprimit_texdef.coords[0][2];
- D[1][0] = f->brushprimit_texdef.coords[1][2];
- D[1][1] = f->brushprimit_texdef.coords[1][0] + f->brushprimit_texdef.coords[1][2];
- D[1][2] = f->brushprimit_texdef.coords[1][1] + f->brushprimit_texdef.coords[1][2];
- // solve
- det = SarrusDet(M[0], M[1], M[2]);
- f->brushprimit_texdef.coords[0][0] = SarrusDet(D[0], M[1], M[2]) / det;
- f->brushprimit_texdef.coords[0][1] = SarrusDet(M[0], D[0], M[2]) / det;
- f->brushprimit_texdef.coords[0][2] = SarrusDet(M[0], M[1], D[0]) / det;
- f->brushprimit_texdef.coords[1][0] = SarrusDet(D[1], M[1], M[2]) / det;
- f->brushprimit_texdef.coords[1][1] = SarrusDet(M[0], D[1], M[2]) / det;
- f->brushprimit_texdef.coords[1][2] = SarrusDet(M[0], M[1], D[1]) / det;
- }
- //
- // =======================================================================================================================
- // call Face_MoveTexture_BrushPrimit after idVec3D computation
- // =======================================================================================================================
- //
- void Select_ShiftTexture_BrushPrimit(face_t *f, float x, float y, bool autoAdjust) {
- #if 0
- idVec3D texS, texT;
- idVec3D delta;
- ComputeAxisBase(f->plane.normal, texS, texT);
- VectorScale(texS, x, texS);
- VectorScale(texT, y, texT);
- VectorCopy(texS, delta);
- VectorAdd(delta, texT, delta);
- Face_MoveTexture_BrushPrimit(f, delta);
- #else
- if (autoAdjust) {
- x /= f->d_texture->GetEditorImage()->uploadWidth;
- y /= f->d_texture->GetEditorImage()->uploadHeight;
- }
- f->brushprimit_texdef.coords[0][2] += x;
- f->brushprimit_texdef.coords[1][2] += y;
- EmitBrushPrimitTextureCoordinates(f, f->face_winding);
- #endif
- }
- //
- // =======================================================================================================================
- // best fitted 2D vector is x.X+y.Y
- // =======================================================================================================================
- //
- void ComputeBest2DVector(idVec3 v, idVec3 X, idVec3 Y, int &x, int &y) {
- double sx, sy;
- sx = DotProduct(v, X);
- sy = DotProduct(v, Y);
- if (idMath::Fabs(sy) > idMath::Fabs(sx)) {
- x = 0;
- if (sy > 0.0) {
- y = 1;
- }
- else {
- y = -1;
- }
- }
- else {
- y = 0;
- if (sx > 0.0) {
- x = 1;
- }
- else {
- x = -1;
- }
- }
- }
- //
- // =======================================================================================================================
- // 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 *
- // 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
- // particular case .. need to make sure before calling NOTE: the third coord of the A,B,C point is ignored NOTE: see
- // the commented out section to fill M and D ++timo TODO: update the other members to use this when possible
- // =======================================================================================================================
- //
- void MatrixForPoints(idVec3D M[3], idVec3D D[2], brushprimit_texdef_t *T) {
- //
- // idVec3D M[3]; // columns of the matrix .. easier that way (the indexing is not
- // standard! it's column-line .. later computations are easier that way)
- //
- double det;
- // idVec3D D[2];
- M[2][0] = 1.0f;
- M[2][1] = 1.0f;
- M[2][2] = 1.0f;
- #if 0
- // fill the data vectors
- M[0][0] = A2[0];
- M[0][1] = B2[0];
- M[0][2] = C2[0];
- M[1][0] = A2[1];
- M[1][1] = B2[1];
- M[1][2] = C2[1];
- M[2][0] = 1.0f;
- M[2][1] = 1.0f;
- M[2][2] = 1.0f;
- D[0][0] = A1[0];
- D[0][1] = B1[0];
- D[0][2] = C1[0];
- D[1][0] = A1[1];
- D[1][1] = B1[1];
- D[1][2] = C1[1];
- #endif
- // solve
- det = SarrusDet(M[0], M[1], M[2]);
- T->coords[0][0] = SarrusDet(D[0], M[1], M[2]) / det;
- T->coords[0][1] = SarrusDet(M[0], D[0], M[2]) / det;
- T->coords[0][2] = SarrusDet(M[0], M[1], D[0]) / det;
- T->coords[1][0] = SarrusDet(D[1], M[1], M[2]) / det;
- T->coords[1][1] = SarrusDet(M[0], D[1], M[2]) / det;
- T->coords[1][2] = SarrusDet(M[0], M[1], D[1]) / det;
- }
- //
- // =======================================================================================================================
- // ++timo FIXME quick'n dirty hack, doesn't care about current texture settings (angle) can be improved .. bug #107311
- // mins and maxs are the face bounding box ++timo fixme: we use the face info, mins and maxs are irrelevant
- // =======================================================================================================================
- //
- void Face_FitTexture_BrushPrimit(face_t *f, idVec3 mins, idVec3 maxs, float height, float width) {
- idVec3D BBoxSTMin, BBoxSTMax;
- idWinding *w;
- int i, j;
- double val;
- idVec3D M[3], D[2];
- // idVec3D N[2],Mf[2];
- brushprimit_texdef_t N;
- idVec3D Mf[2];
-
- //memset(f->brushprimit_texdef.coords, 0, sizeof(f->brushprimit_texdef.coords));
- //f->brushprimit_texdef.coords[0][0] = 1.0f;
- //f->brushprimit_texdef.coords[1][1] = 1.0f;
- //ConvertTexMatWithQTexture(&f->brushprimit_texdef, NULL, &f->brushprimit_texdef, f->d_texture);
- //
- // we'll be working on a standardized texture size ConvertTexMatWithQTexture(
- // &f->brushprimit_texdef, f->d_texture, &f->brushprimit_texdef, NULL ); compute
- // the BBox in ST coords
- //
- EmitBrushPrimitTextureCoordinates(f, f->face_winding);
- BBoxSTMin[0] = BBoxSTMin[1] = BBoxSTMin[2] = 999999;
- BBoxSTMax[0] = BBoxSTMax[1] = BBoxSTMax[2] = -999999;
- w = f->face_winding;
- if (w) {
- for (i = 0; i < w->GetNumPoints(); i++) {
- // AddPointToBounds in 2D on (S,T) coordinates
- for (j = 0; j < 2; j++) {
- val = (*w)[i][j + 3];
- if (val < BBoxSTMin[j]) {
- BBoxSTMin[j] = val;
- }
- if (val > BBoxSTMax[j]) {
- BBoxSTMax[j] = val;
- }
- }
- }
- }
- //
- // we have the three points of the BBox (BBoxSTMin[0].BBoxSTMin[1])
- // (BBoxSTMax[0],BBoxSTMin[1]) (BBoxSTMin[0],BBoxSTMax[1]) in ST space the BP
- // matrix we are looking for gives (0,0) (nwidth,0) (0,nHeight) coordinates in
- // (Sfit,Tfit) space to these three points we have A(Sfit,Tfit) = (0,0) = Mf *
- // A(TexS,TexT) = N * M * A(TexS,TexT) = N * A(S,T) so we solve the system for N
- // and then Mf = N * M
- //
- M[0][0] = BBoxSTMin[0];
- M[0][1] = BBoxSTMax[0];
- M[0][2] = BBoxSTMin[0];
- M[1][0] = BBoxSTMin[1];
- M[1][1] = BBoxSTMin[1];
- M[1][2] = BBoxSTMax[1];
- D[0][0] = 0.0f;
- D[0][1] = width;
- D[0][2] = 0.0f;
- D[1][0] = 0.0f;
- D[1][1] = 0.0f;
- D[1][2] = height;
- MatrixForPoints(M, D, &N);
- #if 0
- //
- // FIT operation gives coordinates of three points of the bounding box in (S',T'),
- // our target axis base A(S',T')=(0,0) B(S',T')=(nWidth,0) C(S',T')=(0,nHeight)
- // and we have them in (S,T) axis base: A(S,T)=(BBoxSTMin[0],BBoxSTMin[1])
- // B(S,T)=(BBoxSTMax[0],BBoxSTMin[1]) C(S,T)=(BBoxSTMin[0],BBoxSTMax[1]) we
- // compute the N transformation so that: A(S',T') = N * A(S,T)
- //
- N[0][0] = (BBoxSTMax[0] - BBoxSTMin[0]) / width;
- N[0][1] = 0.0f;
- N[0][2] = BBoxSTMin[0];
- N[1][0] = 0.0f;
- N[1][1] = (BBoxSTMax[1] - BBoxSTMin[1]) / height;
- N[1][2] = BBoxSTMin[1];
- #endif
- // the final matrix is the product (Mf stands for Mfit)
- Mf[0][0] = N.coords[0][0] *
- f->brushprimit_texdef.coords[0][0] +
- N.coords[0][1] *
- f->brushprimit_texdef.coords[1][0];
- Mf[0][1] = N.coords[0][0] *
- f->brushprimit_texdef.coords[0][1] +
- N.coords[0][1] *
- f->brushprimit_texdef.coords[1][1];
- Mf[0][2] = N.coords[0][0] *
- f->brushprimit_texdef.coords[0][2] +
- N.coords[0][1] *
- f->brushprimit_texdef.coords[1][2] +
- N.coords[0][2];
- Mf[1][0] = N.coords[1][0] *
- f->brushprimit_texdef.coords[0][0] +
- N.coords[1][1] *
- f->brushprimit_texdef.coords[1][0];
- Mf[1][1] = N.coords[1][0] *
- f->brushprimit_texdef.coords[0][1] +
- N.coords[1][1] *
- f->brushprimit_texdef.coords[1][1];
- Mf[1][2] = N.coords[1][0] *
- f->brushprimit_texdef.coords[0][2] +
- N.coords[1][1] *
- f->brushprimit_texdef.coords[1][2] +
- N.coords[1][2];
- // copy back
- VectorCopy(Mf[0], f->brushprimit_texdef.coords[0]);
- VectorCopy(Mf[1], f->brushprimit_texdef.coords[1]);
- //
- // handle the texture size ConvertTexMatWithQTexture( &f->brushprimit_texdef,
- // NULL, &f->brushprimit_texdef, f->d_texture );
- //
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void Face_ScaleTexture_BrushPrimit(face_t *face, float sS, float sT) {
- if (!g_qeglobals.m_bBrushPrimitMode) {
- Sys_Status("BP mode required\n");
- return;
- }
- brushprimit_texdef_t *pBP = &face->brushprimit_texdef;
- BPMatScale(pBP->coords, sS, sT);
- // now emit the coordinates on the winding
- EmitBrushPrimitTextureCoordinates(face, face->face_winding);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void Face_RotateTexture_BrushPrimit(face_t *face, float amount, idVec3 origin) {
- brushprimit_texdef_t *pBP = &face->brushprimit_texdef;
- if (amount) {
- float x = pBP->coords[0][0];
- float y = pBP->coords[0][1];
- float x1 = pBP->coords[1][0];
- float y1 = pBP->coords[1][1];
- float s = sin( DEG2RAD( amount ) );
- float c = cos( DEG2RAD( amount ) );
- pBP->coords[0][0] = (((x - origin[0]) * c) - ((y - origin[1]) * s)) + origin[0];
- pBP->coords[0][1] = (((x - origin[0]) * s) + ((y - origin[1]) * c)) + origin[1];
- pBP->coords[1][0] = (((x1 - origin[0]) * c) - ((y1 - origin[1]) * s)) + origin[0];
- pBP->coords[1][1] = (((x1 - origin[0]) * s) + ((y1 - origin[1]) * c)) + origin[1];
- EmitBrushPrimitTextureCoordinates(face, face->face_winding);
- }
- }
- //
- // TEXTURE LOCKING (Relevant to the editor only?)
- // internally used for texture locking on rotation and flipping the general
- // algorithm is the same for both lockings, it's only the geometric transformation
- // part that changes so I wanted to keep it in a single function if there are more
- // linear transformations that need the locking, going to a C++ or code pointer
- // solution would be best (but right now I want to keep brush_primit.cpp striclty
- // C)
- //
- bool txlock_bRotation;
- // rotation locking params
- int txl_nAxis;
- double txl_fDeg;
- idVec3D txl_vOrigin;
- // flip locking params
- idVec3D txl_matrix[3];
- idVec3D txl_origin;
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void TextureLockTransformation_BrushPrimit(face_t *f) {
- idVec3D Orig, texS, texT; // axis base of initial plane
- // used by transformation algo
- idVec3D temp;
- int j;
- //idVec3D vRotate; // rotation vector
- idVec3D rOrig, rvecS, rvecT; // geometric transformation of (0,0) (1,0) (0,1) { initial plane axis base }
- idVec3 rNormal;
- idVec3D rtexS, rtexT; // axis base for the transformed plane
- idVec3D lOrig, lvecS, lvecT; // [2] are not used ( but usefull for debugging )
- idVec3D M[3];
- double det;
- idVec3D D[2];
- // silence compiler warnings
- rOrig.Zero();
- rvecS = rOrig;
- rvecT = rOrig;
- rNormal.x = rOrig.x;
- rNormal.y = rOrig.y;
- rNormal.z = rOrig.z;
- // compute plane axis base
- ComputeAxisBase(f->plane.Normal(), texS, texT);
- Orig.x = vec3_origin.x;
- Orig.y = vec3_origin.y;
- Orig.z = vec3_origin.z;
- //
- // compute coordinates of (0,0) (1,0) (0,1) ( expressed in initial plane axis base
- // ) after transformation (0,0) (1,0) (0,1) ( expressed in initial plane axis base
- // ) <-> (0,0,0) texS texT ( expressed world axis base ) input: Orig, texS, texT
- // (and the global locking params) ouput: rOrig, rvecS, rvecT, rNormal
- //
- if (txlock_bRotation) {
- /*
- // rotation vector
- vRotate.x = vec3_origin.x;
- vRotate.y = vec3_origin.y;
- vRotate.z = vec3_origin.z;
- vRotate[txl_nAxis] = txl_fDeg;
- VectorRotate3Origin(Orig, vRotate, txl_vOrigin, rOrig);
- VectorRotate3Origin(texS, vRotate, txl_vOrigin, rvecS);
- VectorRotate3Origin(texT, vRotate, txl_vOrigin, rvecT);
- // compute normal of plane after rotation
- VectorRotate3(f->plane.Normal(), vRotate, rNormal);
- */
- }
- else {
- VectorSubtract(Orig, txl_origin, temp);
- for (j = 0; j < 3; j++) {
- rOrig[j] = DotProduct(temp, txl_matrix[j]) + txl_origin[j];
- }
- VectorSubtract(texS, txl_origin, temp);
- for (j = 0; j < 3; j++) {
- rvecS[j] = DotProduct(temp, txl_matrix[j]) + txl_origin[j];
- }
- VectorSubtract(texT, txl_origin, temp);
- for (j = 0; j < 3; j++) {
- rvecT[j] = DotProduct(temp, txl_matrix[j]) + txl_origin[j];
- }
- //
- // we also need the axis base of the target plane, apply the transformation matrix
- // to the normal too..
- //
- for (j = 0; j < 3; j++) {
- rNormal[j] = DotProduct(f->plane, txl_matrix[j]);
- }
- }
- // compute rotated plane axis base
- ComputeAxisBase(rNormal, rtexS, rtexT);
- // compute S/T coordinates of the three points in rotated axis base ( in M matrix )
- lOrig[0] = DotProduct(rOrig, rtexS);
- lOrig[1] = DotProduct(rOrig, rtexT);
- lvecS[0] = DotProduct(rvecS, rtexS);
- lvecS[1] = DotProduct(rvecS, rtexT);
- lvecT[0] = DotProduct(rvecT, rtexS);
- lvecT[1] = DotProduct(rvecT, rtexT);
- M[0][0] = lOrig[0];
- M[1][0] = lOrig[1];
- M[2][0] = 1.0f;
- M[0][1] = lvecS[0];
- M[1][1] = lvecS[1];
- M[2][1] = 1.0f;
- M[0][2] = lvecT[0];
- M[1][2] = lvecT[1];
- M[2][2] = 1.0f;
- // fill data vector
- D[0][0] = f->brushprimit_texdef.coords[0][2];
- D[0][1] = f->brushprimit_texdef.coords[0][0] + f->brushprimit_texdef.coords[0][2];
- D[0][2] = f->brushprimit_texdef.coords[0][1] + f->brushprimit_texdef.coords[0][2];
- D[1][0] = f->brushprimit_texdef.coords[1][2];
- D[1][1] = f->brushprimit_texdef.coords[1][0] + f->brushprimit_texdef.coords[1][2];
- D[1][2] = f->brushprimit_texdef.coords[1][1] + f->brushprimit_texdef.coords[1][2];
- // solve
- det = SarrusDet(M[0], M[1], M[2]);
- f->brushprimit_texdef.coords[0][0] = SarrusDet(D[0], M[1], M[2]) / det;
- f->brushprimit_texdef.coords[0][1] = SarrusDet(M[0], D[0], M[2]) / det;
- f->brushprimit_texdef.coords[0][2] = SarrusDet(M[0], M[1], D[0]) / det;
- f->brushprimit_texdef.coords[1][0] = SarrusDet(D[1], M[1], M[2]) / det;
- f->brushprimit_texdef.coords[1][1] = SarrusDet(M[0], D[1], M[2]) / det;
- f->brushprimit_texdef.coords[1][2] = SarrusDet(M[0], M[1], D[1]) / det;
- }
- //
- // =======================================================================================================================
- // texture locking called before the points on the face are actually rotated
- // =======================================================================================================================
- //
- void RotateFaceTexture_BrushPrimit(face_t *f, int nAxis, float fDeg, idVec3 vOrigin) {
- // this is a placeholder to call the general texture locking algorithm
- txlock_bRotation = true;
- txl_nAxis = nAxis;
- txl_fDeg = fDeg;
- VectorCopy(vOrigin, txl_vOrigin);
- TextureLockTransformation_BrushPrimit(f);
- }
- //
- // =======================================================================================================================
- // compute the new brush primit texture matrix for a transformation matrix and a flip order flag (change plane o
- // rientation) this matches the select_matrix algo used in select.cpp this needs to be called on the face BEFORE any
- // geometric transformation it will compute the texture matrix that will represent the same texture on the face after
- // the geometric transformation is done
- // =======================================================================================================================
- //
- void ApplyMatrix_BrushPrimit(face_t *f, idMat3 matrix, idVec3 origin) {
- // this is a placeholder to call the general texture locking algorithm
- txlock_bRotation = false;
- VectorCopy(matrix[0], txl_matrix[0]);
- VectorCopy(matrix[1], txl_matrix[1]);
- VectorCopy(matrix[2], txl_matrix[2]);
- VectorCopy(origin, txl_origin);
- TextureLockTransformation_BrushPrimit(f);
- }
- //
- // =======================================================================================================================
- // don't do C==A!
- // =======================================================================================================================
- //
- void BPMatMul(float A[2][3], float B[2][3], float C[2][3]) {
- C[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0];
- C[1][0] = A[1][0] * B[0][0] + A[1][1] * B[1][0];
- C[0][1] = A[0][0] * B[0][1] + A[0][1] * B[1][1];
- C[1][1] = A[1][0] * B[0][1] + A[1][1] * B[1][1];
- C[0][2] = A[0][0] * B[0][2] + A[0][1] * B[1][2] + A[0][2];
- C[1][2] = A[1][0] * B[0][2] + A[1][1] * B[1][2] + A[1][2];
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void BPMatDump(float A[2][3]) {
- 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]);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void BPMatRotate(float A[2][3], float theta) {
- float m[2][3];
- float aux[2][3];
- memset(&m, 0, sizeof (float) *6);
- m[0][0] = cos( DEG2RAD( theta ) );
- m[0][1] = -sin( DEG2RAD( theta ) );
- m[1][0] = -m[0][1];
- m[1][1] = m[0][0];
- BPMatMul(A, m, aux);
- BPMatCopy(aux, A);
- }
- void Face_GetScale_BrushPrimit(face_t *face, float *s, float *t, float *rot) {
- idVec3D texS, texT;
- ComputeAxisBase(face->plane.Normal(), texS, texT);
- if (face == NULL || face->face_winding == NULL) {
- return;
- }
- // find ST coordinates for the center of the face
- double Os = 0, Ot = 0;
- for (int i = 0; i < face->face_winding->GetNumPoints(); i++) {
- Os += DotProduct((*face->face_winding)[i], texS);
- Ot += DotProduct((*face->face_winding)[i], texT);
- }
- Os /= face->face_winding->GetNumPoints();
- Ot /= face->face_winding->GetNumPoints();
- brushprimit_texdef_t *pBP = &face->brushprimit_texdef;
- // here we have a special case, M is a translation and it's inverse is easy
- float BPO[2][3];
- float aux[2][3];
- float m[2][3];
- memset(&m, 0, sizeof (float) *6);
- m[0][0] = 1;
- m[1][1] = 1;
- m[0][2] = -Os;
- m[1][2] = -Ot;
- BPMatMul(m, pBP->coords, aux);
- m[0][2] = Os;
- m[1][2] = Ot; // now M^-1
- BPMatMul(aux, m, BPO);
- // apply a given scale (on S and T)
- ConvertTexMatWithQTexture(BPO, face->d_texture, aux, NULL);
- *s = idMath::Sqrt(aux[0][0] * aux[0][0] + aux[1][0] * aux[1][0]);
- *t = idMath::Sqrt(aux[0][1] * aux[0][1] + aux[1][1] * aux[1][1]);
- // compute rotate value
- if (idMath::Fabs(face->brushprimit_texdef.coords[0][0]) < ZERO_EPSILON)
- {
- // rotate is +-90
- if (face->brushprimit_texdef.coords[1][0] > 0) {
- *rot = 90.0f;
- }
- else {
- *rot = -90.0f;
- }
- }
- else {
- *rot = RAD2DEG(atan2(face->brushprimit_texdef.coords[1][0] / (*s) ? (*s) : 1.0f, face->brushprimit_texdef.coords[0][0] / (*t) ? (*t) : 1.0f));
- }
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void Face_SetExplicitScale_BrushPrimit(face_t *face, float s, float t) {
- idVec3D texS, texT;
- ComputeAxisBase(face->plane.Normal(), texS, texT);
- // find ST coordinates for the center of the face
- double Os = 0, Ot = 0;
- for (int i = 0; i < face->face_winding->GetNumPoints(); i++) {
- Os += DotProduct((*face->face_winding)[i], texS);
- Ot += DotProduct((*face->face_winding)[i], texT);
- }
- Os /= face->face_winding->GetNumPoints();
- Ot /= face->face_winding->GetNumPoints();
- brushprimit_texdef_t *pBP = &face->brushprimit_texdef;
- // here we have a special case, M is a translation and it's inverse is easy
- float BPO[2][3];
- float aux[2][3];
- float m[2][3];
- memset(&m, 0, sizeof (float) *6);
- m[0][0] = 1;
- m[1][1] = 1;
- m[0][2] = -Os;
- m[1][2] = -Ot;
- BPMatMul(m, pBP->coords, aux);
- m[0][2] = Os;
- m[1][2] = Ot; // now M^-1
- BPMatMul(aux, m, BPO);
- // apply a given scale (on S and T)
- ConvertTexMatWithQTexture(BPO, face->d_texture, aux, NULL);
- // reset the scale (normalize the matrix)
- double v1, v2;
- v1 = idMath::Sqrt(aux[0][0] * aux[0][0] + aux[1][0] * aux[1][0]);
- v2 = idMath::Sqrt(aux[0][1] * aux[0][1] + aux[1][1] * aux[1][1]);
- if (s == 0.0) {
- s = v1;
- }
- if (t == 0.0) {
- t = v2;
- }
- double sS, sT;
- // put the values for scale on S and T here:
- sS = s / v1;
- sT = t / v2;
- aux[0][0] *= sS;
- aux[1][0] *= sS;
- aux[0][1] *= sT;
- aux[1][1] *= sT;
- ConvertTexMatWithQTexture(aux, NULL, BPO, face->d_texture);
- BPMatMul(m, BPO, aux); // m is M^-1
- m[0][2] = -Os;
- m[1][2] = -Ot;
- BPMatMul(aux, m, pBP->coords);
- // now emit the coordinates on the winding
- EmitBrushPrimitTextureCoordinates(face, face->face_winding);
- }
- void Face_FlipTexture_BrushPrimit(face_t *f, bool y) {
- float s, t, rot;
- Face_GetScale_BrushPrimit(f, &s, &t, &rot);
- if (y) {
- Face_SetExplicitScale_BrushPrimit(f, 0.0, -t);
- } else {
- Face_SetExplicitScale_BrushPrimit(f, -s, 0.0);
- }
- #if 0
- idVec3D texS, texT;
- ComputeAxisBase(f->plane.normal, texS, texT);
- double Os = 0, Ot = 0;
- for (int i = 0; i < f->face_winding->numpoints; i++) {
- Os += DotProduct(f->face_winding->p[i], texS);
- Ot += DotProduct(f->face_winding->p[i], texT);
- }
- Ot = abs(Ot);
- Ot *= t;
- Ot /= f->d_texture->GetEditorImage()->uploadHeight;
- Os = abs(Os);
- Os *= s;
- Os /= f->d_texture->GetEditorImage()->uploadWidth;
-
- if (y) {
- Face_FitTexture_BrushPrimit(f, texS, texT, -Ot, 1.0);
- } else {
- Face_FitTexture_BrushPrimit(f, texS, texT, 1.0, -Os);
- }
- EmitBrushPrimitTextureCoordinates(f, f->face_winding);
- #endif
- }
- void Brush_FlipTexture_BrushPrimit(brush_t *b, bool y) {
- for (face_t *f = b->brush_faces; f; f = f->next) {
- Face_FlipTexture_BrushPrimit(f, y);
- }
- }
- void Face_SetAxialScale_BrushPrimit(face_t *face, bool y) {
- if (!face) {
- return;
- }
- if (!face->face_winding) {
- return;
- }
- //float oldS, oldT, oldR;
- //Face_GetScale_BrushPrimit(face, &oldS, &oldT, &oldR);
- idVec3D min, max;
- min.x = min.y = min.z = 999999.0;
- max.x = max.y = max.z = -999999.0;
- for (int i = 0; i < face->face_winding->GetNumPoints(); i++) {
- for (int j = 0; j < 3; j++) {
- if ((*face->face_winding)[i][j] < min[j]) {
- min[j] = (*face->face_winding)[i][j];
- }
- if ((*face->face_winding)[i][j] > max[j]) {
- max[j] = (*face->face_winding)[i][j];
- }
- }
- }
-
- idVec3 len;
- if (g_bAxialMode) {
- if (g_axialAnchor >= 0 && g_axialAnchor < face->face_winding->GetNumPoints() &&
- g_axialDest >= 0 && g_axialDest < face->face_winding->GetNumPoints() &&
- g_axialAnchor != g_axialDest) {
- len = (*face->face_winding)[g_axialDest].ToVec3() - (*face->face_winding)[g_axialAnchor].ToVec3();
- } else {
- return;
- }
- } else {
- if (y) {
- len = (*face->face_winding)[2].ToVec3() - (*face->face_winding)[1].ToVec3();
- } else {
- len = (*face->face_winding)[1].ToVec3() - (*face->face_winding)[0].ToVec3();
- }
- }
- double dist = len.Length();
- double width = idMath::Fabs(max.x - min.x);
- double height = idMath::Fabs(max.z - min.z);
- //len = maxs[2] - mins[2];
- //double yDist = len.Length();
- if (dist != 0.0) {
- if (dist > face->d_texture->GetEditorImage()->uploadHeight) {
- height = 1.0 / (dist / face->d_texture->GetEditorImage()->uploadHeight);
- } else {
- height /= dist;
- }
- if (dist > face->d_texture->GetEditorImage()->uploadWidth) {
- width = 1.0 / (dist / face->d_texture->GetEditorImage()->uploadWidth);
- } else {
- width /= dist;
- }
- }
- if (y) {
- Face_SetExplicitScale_BrushPrimit(face, 0.0, height);
- //oldT = oldT / height * 10;
- //Select_ShiftTexture_BrushPrimit(face, 0, -oldT, true);
- } else {
- Face_SetExplicitScale_BrushPrimit(face, width, 0.0);
- }
- /*
- common->Printf("Face x: %f y: %f xr: %f yr: %f\n", x, y, xRatio, yRatio);
- common->Printf("Texture x: %i y: %i \n",face->d_texture->GetEditorImage()->uploadWidth, face->d_texture->GetEditorImage()->uploadHeight);
- idVec3D texS, texT;
- ComputeAxisBase(face->plane.normal, texS, texT);
- float Os = 0, Ot = 0;
- for (int i = 0; i < face->face_winding->numpoints; i++) {
- Os += DotProduct(face->face_winding->p[i], texS);
- Ot += DotProduct(face->face_winding->p[i], texT);
- }
- common->Printf("Face2 x: %f y: %f \n", Os, Ot);
- Os /= face->face_winding->numpoints;
- Ot /= face->face_winding->numpoints;
- //Os /= face->face_winding->numpoints;
- //Ot /= face->face_winding->numpoints;
- */
- }
|