Descent3/legacy/editor/HTexture.cpp
JeodC a4ab78192c Join license header with historical commentrs
Join the license header with historical comments using a separator so IDEs can correctly parse the initial header.

Also use .gitattributes to ensure all files are LF.
2024-05-08 14:41:19 -04:00

918 lines
22 KiB
C++

/*
* 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 <http://www.gnu.org/licenses/>.
--- HISTORICAL COMMENTS FOLLOW ---
* $Logfile: /DescentIII/Main/editor/HTexture.cpp $
* $Revision: 1.1.1.1 $
* $Date: 2003-08-26 03:57:38 $
* $Author: kevinb $
*
* HTexture implementation
*
* $Log: not supported by cvs2svn $
*
* 37 12/27/99 8:26a Gwar
*
* 36 8/30/99 12:55p Gwar
* added a parameter to HTexturePropagateToFace to not change the texture
* of the target face
*
* 35 7/30/99 1:19p Gwar
* don't set World_changed in NEWEDITOR
*
* 34 7/24/99 5:25a Gwar
* NEWEDITOR changes to HTextureApplyToRoomFace
*
* 33 7/04/99 4:56p Gwar
* changes for texture management in NEWEDITOR
*
* 32 5/19/99 12:19a Gwar
* #define Curroomp, Curface, etc as members of prim struct in NEWEDITOR
* -- this allows the main room frame and level window to share these
* variables and makes them non-global (i.e. no more sync problem between
* world and room views)
*
* 31 5/03/99 2:06a Gwar
* added HTexture.cpp to project
*
* 30 1/20/99 10:50a Jason
* added new terrain
*
* 29 10/21/98 1:27p Jason
* fixed texture u2,v2 sliding problems
*
* 28 8/16/98 4:24p Matt
* When copying UVs from one face to another, only copy u & v, and not
* other fields in the uv structure.
*
* 27 8/15/98 5:04p Matt
* Added code to copy a texture & UVs from one face to another
*
* 26 6/15/98 4:00p Jason
* replaced monochromatic polymodel lighting with rgb lighting
*
* 25 4/16/98 10:42a Matt
* Made texture propagation work across rooms.
*
* 24 4/02/98 12:23p Jason
* trimmed some fat from our structures
*
* 23 9/23/97 12:20p Jason
* fixed bug where rotating a texture would cause alphas and u2,v2s to
* become corrupt
*
* 22 9/17/97 1:36p Samir
* Fixed some new prototypes.
*
* 21 9/17/97 11:57a Matt
* Ripped out segment code
*
* 19 8/21/97 6:01p Matt
* Use groovy new FindSharedEdge() function
*
* 18 8/13/97 9:52a Matt
* Combined slide left/right/up/down into one function, and the same with
* rotate left/right
*
* 17 8/07/97 5:06p Jason
* added new tiling system for terrain
*
* 16 8/07/97 3:19p Jason
* replaced old terrain tmap system with new one
*
* 15 8/01/97 4:53p Jason
* made a more general PropagateTextureToFace function call
*
* 14 7/22/97 7:08p Matt
* Cleaned up D3EditState, moving some vars in and some out, and renaming
* and changing a few others
*
* 13 7/18/97 7:38p Jason
* finished room/terrain texture modifications
*
* 12 7/16/97 6:31p Jason
* changed defaut texture uvs for terrain
*
* 15 6/24/97 12:41p Jason
* checked in for safety
*
* 14 6/18/97 11:14a Mark
* FROM JASON:Fixed dumb terrain rotational bug
*
* 13 6/17/97 4:16p Jason
* added some terrain features
*
* 12 6/17/97 11:35a Jason
* checked in for safety
*
* 11 6/06/97 4:57p Jason
* more nifty megacell/tmap2 features
*
* 10 6/04/97 1:32p Matt
* Changed Side_to_verts[] and Side_opposite[] to be arrays of ints, which
* should be faster than bytes.
*
* 9 5/30/97 3:32p Samir
* When rotating textures, lighting preserved
*
* 8 5/02/97 7:21p Matt
* Added code to rotate tmap2's
*
* 7 4/17/97 4:03p Samir
* Apply Tmap 1 and Tmap2 implemented, but no Tmap2 rendering is occurring
* yet.
*
* 6 3/31/97 5:58p Matt
* Revamped mine update flags
*
* 5 3/31/97 3:50p Samir
* Set default texture uvs should work for side not whole segment.
*
* 4 2/26/97 6:40p Samir
* changed g3s_uvl to g3UVL
*
* 3 2/26/97 3:59p Samir
* Most scaling, rotating, sliding and flipping work.
*
* 2 2/20/97 11:59a Samir
* Fixed bugs
*
* 1 2/20/97 11:50a Samir
*
* $NoKeywords: $
*/
#include "HTexture.h"
#ifndef NEWEDITOR
#include "d3edit.h"
#endif
#include "roomuvs.h"
#include "gametexture.h"
#include "terrain.h"
#include "room.h"
#include "descent.h"
#include "erooms.h"
#define HTEX_CALIB_VAL ((float)(1.0/128.0))
// ---------------------------------------------------------------------------
// internal function prototypes
// ---------------------------------------------------------------------------
void HTextureRoomStretch(room *rp, int facenum, int edge, int direction);
void HTextureRotUVPoint(g3UVL *uvrot, float *rotmat, roomUVL *uv, g3UVL *uvcenter);
void HTextureCreate2DRotMat(float *rotmat, angle ang);
void HTextureRotUVTerrainPoint(g3UVL *uvrot, float *rotmat, g3UVL *uv, g3UVL *uvcenter);
void GetUVLForRoomPoint (int roomnum,int facenum,int vertnum,roomUVL *uvl);
int HTextureGetTopVertexForFace (int roomnum,int facenum);
int HTextureGetBottomVertexForFace (int roomnum,int facenum);
int HTextureGetLeftVertexForFace (int roomnum,int facenum);
int HTextureGetRightVertexForFace (int roomnum,int facenum);
void HTextureRotUVPointsOnRoomFace(room *roomp, int facenum, float *rotmat, g3UVL *uvcenter);
void HTextureComputeUVRoomFaceCenter(g3UVL *uvcenter, room *roomp, int facenum);
void HTextureTerrainStretch( int edge, int direction);
// ---------------------------------------------------------------------------
// Functions to manipulate textures within the mine, through segments
// ---------------------------------------------------------------------------
//Apply the specified texture to the specified room:face
void HTextureApplyToRoomFace(room *rp,int facenum,int tnum)
{
ASSERT (rp->used);
#ifdef NEWEDITOR
if (tnum == -1)
return;
if (rp->faces[facenum].tmap>=0)
SwitchTexture(rp,rp->faces[facenum].tmap,tnum);
#endif
rp->faces[facenum].tmap=tnum;
}
//Copy texture from current face to adjacent face, tiling the UV coordinates
//Parameters: destrp,destface - room:face that the propagate is based on
// srcrp,srcface - room:face that is changed
//Return: 1 if success, 0 if faces not adjacent
int HTexturePropagateToFace(room *destrp,int destface,room *srcrp,int srcface,bool tex)
{
face *dfp = &destrp->faces[destface];
face *sfp = &srcrp->faces[srcface];
int v0,v1;
//Get shared edge
if (destrp != srcrp) { //Faces in different rooms
if (! FindSharedEdgeAcrossRooms(destrp,destface,srcrp,srcface,&v0,&v1))
return 0;
}
else { //Faces in same room
if (! FindSharedEdge(dfp,sfp,&v0,&v1))
return 0;
}
if (tex)
{
#ifdef NEWEDITOR
SwitchTexture(destrp,dfp->tmap,sfp->tmap);
#endif
//Copy texture from Curface
dfp->tmap = sfp->tmap;
}
//Assign uvs from shared edge to rest of verts in face
AssignUVsToFace(destrp, destface, &sfp->face_uvls[(v1+1)%sfp->num_verts], &sfp->face_uvls[v1], v0, (v0+1)%dfp->num_verts);
//Success
return 1;
}
//Copy texture UVs from one face to another
//Parameters: destrp,destface - room:face that is changed
// srcrp,srcface - room:face to copy from
// offset - vert 0 on source is assigned to vert offset on dest
//Return: 1 if success, 0 if faces don't have the same number of verts
int HTextureCopyUVsToFace(room *destrp,int destface,room *srcrp,int srcface,int offset)
{
face *dfp = &destrp->faces[destface];
face *sfp = &srcrp->faces[srcface];
//Make sure faces have the same number of vertices
if (dfp->num_verts != sfp->num_verts)
return 0;
//Copy UV values
for (int i=0;i<dfp->num_verts;i++) {
dfp->face_uvls[(i+offset)%dfp->num_verts].u = sfp->face_uvls[i].u;
dfp->face_uvls[(i+offset)%dfp->num_verts].v = sfp->face_uvls[i].v;
}
//Success!
#ifndef NEWEDITOR
World_changed = 1;
#endif
return 1;
}
// texture flipping
void HTextureFlipX()
{
int i;
if (Editor_view_mode==VM_TERRAIN)
{
//terrain_segment oldseg;
for (i=0;i<TERRAIN_DEPTH*TERRAIN_WIDTH;i++)
{
if (TerrainSelected[i])
{
/*oldseg=Terrain_seg[i];
Terrain_seg[i].u[0]=oldseg.u[1];
Terrain_seg[i].u[1]=oldseg.u[0];
Terrain_seg[i].u[2]=oldseg.u[3];
Terrain_seg[i].u[3]=oldseg.u[2];
Terrain_seg[i].v[0]=oldseg.v[1];
Terrain_seg[i].v[1]=oldseg.v[0];
Terrain_seg[i].v[2]=oldseg.v[3];
Terrain_seg[i].v[3]=oldseg.v[2];*/
}
}
}
else {
ASSERT (Curroomp->used);
for (int i=0;i<Curroomp->faces[Curface].num_verts;i++)
Curroomp->faces[Curface].face_uvls[i].u=1-Curroomp->faces[Curface].face_uvls[i].u;
}
#ifndef NEWEDITOR
World_changed = 1;
#endif
}
void HTextureFlipY()
{
int i;
if (Editor_view_mode==VM_TERRAIN)
{
terrain_segment oldseg;
for (i=0;i<TERRAIN_DEPTH*TERRAIN_WIDTH;i++)
{
if (TerrainSelected[i])
{
oldseg=Terrain_seg[i];
/*Terrain_seg[i].v[0]=oldseg.v[3];
Terrain_seg[i].v[1]=oldseg.v[2];
Terrain_seg[i].v[2]=oldseg.v[1];
Terrain_seg[i].v[3]=oldseg.v[0];
Terrain_seg[i].u[0]=oldseg.u[3];
Terrain_seg[i].u[1]=oldseg.u[2];
Terrain_seg[i].u[2]=oldseg.u[1];
Terrain_seg[i].u[3]=oldseg.u[0];*/
}
}
}
else {
ASSERT (Curroomp->used);
for (int i=0;i<Curroomp->faces[Curface].num_verts;i++)
Curroomp->faces[Curface].face_uvls[i].v=1-Curroomp->faces[Curface].face_uvls[i].v;
}
#ifndef NEWEDITOR
World_changed = 1;
#endif
}
void HTextureSlide(room *rp, int facenum, float right, float up)
{
ASSERT(rp != NULL);
ASSERT(rp->used);
if (Editor_view_mode==VM_TERRAIN)
{
/*int i;
for (i=0;i<TERRAIN_DEPTH*TERRAIN_WIDTH;i++)
{
if (TerrainSelected[i])
{
for (int t=0;t<4;t++)
{
float val=Terrain_UV_lookup[Terrain_seg[i].u[t]];
val+=(1.0/32.0);
Terrain_seg[i].u[t]=TerrainLookupUV(val);
}
}
}
*/
return;
}
else { //mine
for (int i=0;i<rp->faces[facenum].num_verts;i++) {
rp->faces[facenum].face_uvls[i].u -= right / 128.0f;
rp->faces[facenum].face_uvls[i].v += up / 128.0f;
}
}
#ifndef NEWEDITOR
World_changed = 1;
#endif
}
void HTextureRotate(room *roomp, int facenum, angle ang)
{
g3UVL uvcenter;
float rotmat[4];
HTextureCreate2DRotMat(rotmat, ang);
if (Editor_view_mode==VM_TERRAIN && ang==0x4000)
{
for (int i=0;i<TERRAIN_WIDTH*TERRAIN_DEPTH;i++)
{
if (TerrainSelected[i])
{
/*int f=(Terrain_seg[i].rotation_factor&0x0F);
f++;
f%=4;
Terrain_seg[i].rotation_factor&=0xF0;
Terrain_seg[i].rotation_factor|=(f);*/
}
}
return;
}
else
{
HTextureComputeUVRoomFaceCenter(&uvcenter, roomp, facenum);
HTextureRotUVPointsOnRoomFace(roomp, facenum, rotmat, &uvcenter);
}
#ifndef NEWEDITOR
World_changed = 1;
#endif
}
void HTextureStretchMore(room *rp, int face, int edge)
{
if (Editor_view_mode==VM_TERRAIN)
{
HTextureTerrainStretch(edge, 1*D3EditState.texscale);
}
else {
HTextureRoomStretch(rp, face, edge, 1*D3EditState.texscale);
}
}
void HTextureStretchLess(room *rp, int face, int edge)
{
if (Editor_view_mode==VM_TERRAIN)
{
HTextureTerrainStretch(edge, (-1*D3EditState.texscale));
}
else
{
HTextureRoomStretch(rp, face, edge, (-1*D3EditState.texscale));
}
}
void HTextureSetDefault(room *rp, int face)
{
if (Editor_view_mode==VM_TERRAIN)
{
for (int i=0;i<TERRAIN_WIDTH*TERRAIN_DEPTH;i++)
{
if (TerrainSelected[i])
{
int index=Terrain_seg[i].texseg_index;
Terrain_tex_seg[index].rotation=0;
}
}
World_changed = 1;
}
else if (Editor_view_mode==VM_ROOM)
{
//@@Stretch_scale_x = (float)1.0;
//@@Stretch_scale_y = (float)1.0;
for (int i=0;i<rp->faces[face].num_verts;i++)
{
float saveu2=rp->faces[face].face_uvls[i].u2;
float savev2=rp->faces[face].face_uvls[i].v2;
GetUVLForRoomPoint (ROOMNUM(rp),face,i,&rp->faces[face].face_uvls[i]);
rp->faces[face].face_uvls[i].u2=saveu2;
rp->faces[face].face_uvls[i].v2=savev2;
}
}
else {
//@@Stretch_scale_x = (float)1.0;
//@@Stretch_scale_y = (float)1.0;
for (int i=0;i<rp->faces[face].num_verts;i++)
{
float saveu2=rp->faces[face].face_uvls[i].u2;
float savev2=rp->faces[face].face_uvls[i].v2;
GetUVLForRoomPoint (ROOMNUM(rp),face,i,&rp->faces[face].face_uvls[i]);
rp->faces[face].face_uvls[i].u2=saveu2;
rp->faces[face].face_uvls[i].v2=savev2;
}
}
#ifndef NEWEDITOR
World_changed = 1;
#endif
}
void HTextureNextEdge()
{
Curedge++;
if (Editor_view_mode==VM_TERRAIN)
{
if (Curedge >= 4)
Curedge = 0;
}
else //mine
{
if (Curedge >= Curroomp->faces[Curface].num_verts)
Curedge = 0;
}
State_changed = 1;
}
// ---------------------------------------------------------------------------
// functions used by HTexture operations
// ---------------------------------------------------------------------------
// direction = -1 or 1 depending on direction
// Stretches all vertices towards or away from a given edge
// Depending on the geometry of the face, this can cause distortions
void HTextureRoomStretch(room *rp, int facenum, int edge, int direction)
{
int next_edge=(edge+1)%rp->faces[facenum].num_verts;
// find deltas
float du=rp->faces[facenum].face_uvls[next_edge].u-rp->faces[facenum].face_uvls[edge].u;
float dv=rp->faces[facenum].face_uvls[next_edge].v-rp->faces[facenum].face_uvls[edge].v;
// rotate delta's 90 degrees
float nu=-dv;
float nv=du;
// Find a magnitude to shift by
float mag=sqrt ((nv*nv) + (nu*nu));
nv/=mag;
nu/=mag;
nv/=64.0;
nu/=64.0;
// Apply to all verts except for our edge
for (int i=0;i<rp->faces[facenum].num_verts;i++)
{
if (i==edge || i==next_edge)
continue;
rp->faces[facenum].face_uvls[i].v-=(nv * direction);
rp->faces[facenum].face_uvls[i].u-=(nu * direction);
}
#ifndef NEWEDITOR
World_changed = 1;
#endif
}
void HTextureTerrainStretch( int edge, int direction)
{
int i;
for (i=0;i<TERRAIN_WIDTH*TERRAIN_DEPTH;i++)
{
if (TerrainSelected[i])
{
}
}
#ifndef NEWEDITOR
World_changed = 1;
#endif
}
void HTextureComputeUVRoomFaceCenter(g3UVL *uvcenter, room *roomp, int facenum)
{
int i;
face *facep = &roomp->faces[facenum];
uvcenter->u = 0;
uvcenter->v = 0;
for (i=0; i<facep->num_verts; i++)
{
uvcenter->u += facep->face_uvls[i].u;
uvcenter->v += facep->face_uvls[i].v;
}
uvcenter->u /= i;
uvcenter->v /= i;
}
void HTextureRotUVPoint(g3UVL *uvrot, float *rotmat, roomUVL *uv, g3UVL *uvcenter)
{
uvrot->u = ((uv->u - uvcenter->u)*rotmat[0]) + ((uv->v - uvcenter->v)*rotmat[1]) + uvcenter->u;
uvrot->v = ((uv->u - uvcenter->u)*rotmat[2]) + ((uv->v - uvcenter->v)*rotmat[3]) + uvcenter->v;
}
void HTextureRotUVPointsOnRoomFace(room *roomp, int facenum, float *rotmat, g3UVL *uvcenter)
{
int v;
face *facep = &roomp->faces[facenum];
g3UVL tuv;
for (v=0; v<facep->num_verts; v++) {
HTextureRotUVPoint(&tuv, rotmat, &facep->face_uvls[v], uvcenter);
facep->face_uvls[v].u = tuv.u;
facep->face_uvls[v].v = tuv.v;
}
}
void HTextureCreate2DRotMat(float *rotmat, angle ang)
{
float sinang, cosang;
sinang = FixSin(ang);
cosang = FixCos(ang);
rotmat[0] = cosang;
rotmat[1] = sinang;
rotmat[2] = -sinang;
rotmat[3] = cosang;
}
void HTextureRotUVTerrainPoint(g3UVL *uvrot, float *rotmat, g3UVL *uv, g3UVL *uvcenter)
{
uvrot->u = ((uv->u - uvcenter->u)*rotmat[0]) + ((uv->v - uvcenter->v)*rotmat[1]) + uvcenter->u;
uvrot->v = ((uv->u - uvcenter->u)*rotmat[2]) + ((uv->v - uvcenter->v)*rotmat[3]) + uvcenter->v;
}
// returns the index in the face_verts array for the leftmost point on this face
int HTextureGetLeftVertexForFace (int roomnum,int facenum)
{
matrix face_matrix,trans_matrix;
vector fvec;
vector avg_vert;
vector verts[MAX_VERTS_PER_FACE];
ASSERT (Rooms[roomnum].used);
ASSERT (Rooms[roomnum].faces[facenum].num_verts>=3);
// find the center point of this face
vm_MakeZero (&avg_vert);
for (int i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
avg_vert+=Rooms[roomnum].verts[Rooms[roomnum].faces[facenum].face_verts[i]];
avg_vert/=i;
// Make the orientation matrix
fvec=Rooms[roomnum].faces[facenum].normal;
vm_VectorToMatrix(&face_matrix,&fvec,NULL,NULL);
// Make the transformation matrix
angvec avec;
vm_ExtractAnglesFromMatrix(&avec,&face_matrix);
vm_AnglesToMatrix (&trans_matrix,avec.p,avec.h,avec.b);
// Rotate all the points
for (i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
{
vector vert=Rooms[roomnum].verts[Rooms[roomnum].faces[facenum].face_verts[i]];
vector rot_vert;
vert-=avg_vert;
vm_MatrixMulVector (&rot_vert,&vert,&trans_matrix);
verts[i]=rot_vert;
}
// Find left most point
int leftmost_point=-1;
float leftmost_x=900000.00f; // a big number
for (i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
{
if (verts[i].x<leftmost_x)
{
leftmost_point=i;
leftmost_x=verts[i].x;
}
}
ASSERT (leftmost_point!=-1);
return leftmost_point;
}
// returns the index in the face_verts array for the topmost point on this face
int HTextureGetTopVertexForFace (int roomnum,int facenum)
{
matrix face_matrix,trans_matrix;
vector fvec;
vector avg_vert;
vector verts[MAX_VERTS_PER_FACE];
ASSERT (Rooms[roomnum].used);
ASSERT (Rooms[roomnum].faces[facenum].num_verts>=3);
// find the center point of this face
vm_MakeZero (&avg_vert);
for (int i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
avg_vert+=Rooms[roomnum].verts[Rooms[roomnum].faces[facenum].face_verts[i]];
avg_vert/=i;
// Make the orientation matrix
fvec=Rooms[roomnum].faces[facenum].normal;
vm_VectorToMatrix(&face_matrix,&fvec,NULL,NULL);
// Make the transformation matrix
angvec avec;
vm_ExtractAnglesFromMatrix(&avec,&face_matrix);
vm_AnglesToMatrix (&trans_matrix,avec.p,avec.h,avec.b);
// Rotate all the points
for (i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
{
vector vert=Rooms[roomnum].verts[Rooms[roomnum].faces[facenum].face_verts[i]];
vector rot_vert;
vert-=avg_vert;
vm_MatrixMulVector (&rot_vert,&vert,&trans_matrix);
verts[i]=rot_vert;
}
// Find top most point
int topmost_point=-1;
float topmost_y=-900000.0f; // a big number
for (i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
{
if (verts[i].y>topmost_y)
{
topmost_point=i;
topmost_y=verts[i].y;
}
}
ASSERT (topmost_point!=-1);
return topmost_point;
}
// returns the index in the face_verts array for the rightmost point on this face
int HTextureGetRightVertexForFace (int roomnum,int facenum)
{
matrix face_matrix,trans_matrix;
vector fvec;
vector avg_vert;
vector verts[MAX_VERTS_PER_FACE];
ASSERT (Rooms[roomnum].used);
ASSERT (Rooms[roomnum].faces[facenum].num_verts>=3);
// find the center point of this face
vm_MakeZero (&avg_vert);
for (int i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
avg_vert+=Rooms[roomnum].verts[Rooms[roomnum].faces[facenum].face_verts[i]];
avg_vert/=i;
// Make the orientation matrix
fvec=Rooms[roomnum].faces[facenum].normal;
vm_VectorToMatrix(&face_matrix,&fvec,NULL,NULL);
// Make the transformation matrix
angvec avec;
vm_ExtractAnglesFromMatrix(&avec,&face_matrix);
vm_AnglesToMatrix (&trans_matrix,avec.p,avec.h,avec.b);
// Rotate all the points
for (i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
{
vector vert=Rooms[roomnum].verts[Rooms[roomnum].faces[facenum].face_verts[i]];
vector rot_vert;
vert-=avg_vert;
vm_MatrixMulVector (&rot_vert,&vert,&trans_matrix);
verts[i]=rot_vert;
}
// Find right most point
int rightmost_point=-1;
float rightmost_x=-900000.00f; // a big number
for (i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
{
if (verts[i].x>rightmost_x)
{
rightmost_point=i;
rightmost_x=verts[i].x;
}
}
ASSERT (rightmost_point!=-1);
return rightmost_point;
}
// returns the index in the face_verts array for the most point on this face
int HTextureGetBottomVertexForFace (int roomnum,int facenum)
{
matrix face_matrix,trans_matrix;
vector fvec;
vector avg_vert;
vector verts[MAX_VERTS_PER_FACE];
ASSERT (Rooms[roomnum].used);
ASSERT (Rooms[roomnum].faces[facenum].num_verts>=3);
// find the center point of this face
vm_MakeZero (&avg_vert);
for (int i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
avg_vert+=Rooms[roomnum].verts[Rooms[roomnum].faces[facenum].face_verts[i]];
avg_vert/=i;
// Make the orientation matrix
fvec=Rooms[roomnum].faces[facenum].normal;
vm_VectorToMatrix(&face_matrix,&fvec,NULL,NULL);
// Make the transformation matrix
angvec avec;
vm_ExtractAnglesFromMatrix(&avec,&face_matrix);
vm_AnglesToMatrix (&trans_matrix,avec.p,avec.h,avec.b);
// Rotate all the points
for (i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
{
vector vert=Rooms[roomnum].verts[Rooms[roomnum].faces[facenum].face_verts[i]];
vector rot_vert;
vert-=avg_vert;
vm_MatrixMulVector (&rot_vert,&vert,&trans_matrix);
verts[i]=rot_vert;
}
// Find bottom most point
int bottommost_point=-1;
float bottommost_y=900000.0f; // a big number
for (i=0;i<Rooms[roomnum].faces[facenum].num_verts;i++)
{
if (verts[i].y<bottommost_y)
{
bottommost_point=i;
bottommost_y=verts[i].y;
}
}
ASSERT (bottommost_point!=-1);
return bottommost_point;
}
/*void HTextureGetBoxUVLForFace (room *rp,facenum)
{
int l,r,t,b;
vector lpoint,rpoint,tpoint,bpoint;
g3UVL luvl,ruvl,tuvl,buvl,xchange,ychange;
b=HTextureGetBottomVertexForFace (roomnum,facenum);
t=HTextureGetTopVertexForFace (roomnum,facenum);
l=HTextureGetLeftVertexForFace (roomnum,facenum);
r=HTextureGetRightVertexForFace (roomnum,facenum);
lpoint=rp->verts[rp->faces[facenum].face_verts[l]];
rpoint=rp->verts[rp->faces[facenum].face_verts[r]];
tpoint=rp->verts[rp->faces[facenum].face_verts[t]];
bpoint=rp->verts[rp->faces[facenum].face_verts[b]];
luvl=rp->faces[facenum].face_uvls[l];
ruvl=rp->faces[facenum].face_uvls[r];
tuvl=rp->faces[facenum].face_uvls[t];
buvl=rp->faces[facenum].face_uvls[b];
xchange.u=ruvl.u-luvl.u;
xchange.v=ruvl.v-luvl.v;
ychange=buvl.u-tuvl.u;
ychange=buvl.v-tuvl.v;
}*/