/* * Descent 3 * Copyright (C) 2024 Parallax Software * * This program 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. * * This program 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 this program. If not, see . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/editor/RoomUVs.cpp $ * $Revision: 1.1.1.1 $ * $Date: 2003-08-26 03:57:38 $ * $Author: kevinb $ * * Code to deal with texturing rooms * * $Log: not supported by cvs2svn $ * * 9 9/30/99 6:35p Matt * Added code to scale the UVs of a texture based on the size of the * texture when the texture is applied to a face. This will cause the * applied texture to have the make 3D texel size at the old texture. * * 8 4/25/99 2:38p Gwar * brought in HRoom.cpp and RoomUVs.cpp, and several misc game functions * were added to globals.cpp to make it possible * * 7 10/21/98 1:27p Jason * fixed texture u2,v2 sliding problems * * 6 10/07/98 3:19p Matt * Cleaned up and fixed Mike's old texture UV calculation code. Who ever * told that boy he could do 3D? * * 5 4/02/98 12:23p Jason * trimmed some fat from our structures * * 4 12/23/97 1:33p Samir * Added pserror.h * * 3 9/17/97 11:57a Matt * Ripped out segment code * * 2 7/18/97 7:38p Jason * finished room/terrain texture modifications * * $NoKeywords: $ */ #include "RoomUVs.h" #ifndef NEWEDITOR #include "d3edit.h" #else #include "..\neweditor\globals.h" #endif #include "pserror.h" // returns the magnatude of the 2d vector static float zhypot(float a, float b) { return sqrt(a * a + b * b); } // Given u,v coordinates at two vertices, assign u,v coordinates to the other vertices on a face. // va, vb = face-relative vertex indices corresponding to uva, uvb. Ie, they are always in 0..num_verts_in_face void AssignUVsToFace(room *rp, int facenum, roomUVL *uva, roomUVL *uvb, int va, int vb) { face *fp = &rp->faces[facenum]; int nv = fp->num_verts; int vlo, vhi; vector fvec, rvec, tvec; roomUVL ruvmag, fuvmag, uvlo, uvhi; float fmag, mag01; int i; float saveu2[MAX_VERTS_PER_FACE], savev2[MAX_VERTS_PER_FACE]; for (i = 0; i < fp->num_verts; i++) { saveu2[i] = fp->face_uvls[i].u2; savev2[i] = fp->face_uvls[i].v2; } ASSERT((va < nv) && (vb < nv)); ASSERT((abs(va - vb) == 1) || (abs(va - vb) == nv - 1)); // make sure the verticies specify an edge // We want vlo precedes vhi, ie vlo < vhi, or vlo = num_verts, vhi = 0 if (va == ((vb + 1) % nv)) { // va = vb + 1 vlo = vb; vhi = va; uvlo = *uvb; uvhi = *uva; } else { vlo = va; vhi = vb; uvlo = *uva; uvhi = *uvb; } ASSERT(((vlo + 1) % nv) == vhi); // If we are on an edge, then uvhi is one more than uvlo (mod num_verts) fp->face_uvls[vlo] = uvlo; fp->face_uvls[vhi] = uvhi; // Now we have vlo precedes vhi, compute vertices ((vhi+1) % nv) and ((vhi+2) % nv) // Assign u,v scale to a unit length right vector. fmag = zhypot(uvhi.v - uvlo.v, uvhi.u - uvlo.u); if (fmag < 0.001) { // mprintf(0,"Warning: fmag = %7.3f, using approximate u,v values\n",f2fl(fmag)); ruvmag.u = 256.0; ruvmag.v = 256.0; fuvmag.u = 256.0; fuvmag.v = 256.0; } else { ruvmag.u = uvhi.v - uvlo.v; ruvmag.v = uvlo.u - uvhi.u; fuvmag.u = uvhi.u - uvlo.u; fuvmag.v = uvhi.v - uvlo.v; } // Get pointers to our verts vector *vv0 = &rp->verts[fp->face_verts[vlo]], *vv1 = &rp->verts[fp->face_verts[vhi]]; // Get forward vector from our edge fvec = *vv1 - *vv0; mag01 = vm_NormalizeVector(&fvec); // Check for bad vector if (mag01 < 0.001) { OutrageMessageBox("U, V bogosity in room #%i, probably on face #%i. CLEAN UP YOUR MESS!", ROOMNUM(rp), facenum); return; } // Get right vector from the cross product of the forward vec with the surface normal rvec = fvec ^ fp->normal; // Normalize uv values ruvmag.u /= mag01; ruvmag.v /= mag01; fuvmag.u /= mag01; fuvmag.v /= mag01; // Compute UVs for each point for (i = 1; i < nv - 1; i++) { int fv = (vhi + i) % nv; // vert index in face int rv = fp->face_verts[fv]; // vert index in room // Get the vector for this edge tvec = rp->verts[rv] - *vv0; // Project the current edge onto our forward & right vectors float rproj = tvec * rvec, fproj = tvec * fvec; // Compute and assign UV values fp->face_uvls[fv].u = uvlo.u + (ruvmag.u * rproj) + (fuvmag.u * fproj); fp->face_uvls[fv].v = uvlo.v + (ruvmag.v * rproj) + (fuvmag.v * fproj); } } // Stretches the UVS of a face void StretchRoomUVs(room *rp, int facenum, int edge) { roomUVL uv0, uv1; int v0, v1; face *fp = &rp->faces[facenum]; int i; float saveu2[MAX_VERTS_PER_FACE], savev2[MAX_VERTS_PER_FACE]; for (i = 0; i < fp->num_verts; i++) { saveu2[i] = fp->face_uvls[i].u2; savev2[i] = fp->face_uvls[i].v2; } v0 = edge; v1 = (v0 + 1) % rp->faces[facenum].num_verts; uv0 = rp->faces[facenum].face_uvls[v0]; // copy uv AND l uv1 = rp->faces[facenum].face_uvls[v1]; AssignUVsToFace(rp, facenum, &uv0, &uv1, v0, v1); for (i = 0; i < fp->num_verts; i++) { fp->face_uvls[i].u2 = saveu2[i]; fp->face_uvls[i].v2 = savev2[i]; } } // Scale all the UV values in a face from the center point (as defined by averaging the u & v values) void ScaleFaceUVs(room *rp, int facenum, float scale) { face *fp = &rp->faces[facenum]; int i; float midu = 0, midv = 0; for (i = 0; i < fp->num_verts; i++) { midu += fp->face_uvls[i].u; midv += fp->face_uvls[i].v; } midu /= fp->num_verts; midv /= fp->num_verts; for (i = 0; i < fp->num_verts; i++) { fp->face_uvls[i].u = midu + (fp->face_uvls[i].u - midu) * scale; fp->face_uvls[i].v = midv + (fp->face_uvls[i].v - midv) * scale; } World_changed = 1; }