pmesh.cpp
来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 2,635 行 · 第 1/5 页
CPP
2,635 行
//
// Preliminary patch stuff
//
//
#include "stdafx.h"
#include "qe3.h"
#include "DialogInfo.h"
#include "CapDialog.h"
// externs
extern void MemFile_fprintf(CMemFile* pMemFile, const char* pText, ...);
extern face_t *Face_Alloc( void );
void _Write3DMatrix (FILE *f, int y, int x, int z, float *m);
void _Write3DMatrix (CMemFile *f, int y, int x, int z, float *m);
#define CBLOCK_SUBDIVISIONS 6
patchMesh_t* MakeNewPatch()
{
patchMesh_t *pm = reinterpret_cast<patchMesh_t*>(qmalloc(sizeof(patchMesh_t)));
if (g_qeglobals.bSurfacePropertiesPlugin)
{
pm->pData = static_cast<void *>( g_SurfaceTable.m_pfnPatchAlloc( pm ) );
}
return pm;
}
// FIXME: this needs to be dynamic
//#define MAX_PATCH_MESHES 4096
//patchMesh_t patchMeshes[MAX_PATCH_MESHES];
//int numPatchMeshes = 0;
// used for a save spot
patchMesh_t patchSave;
// Tracks the selected patch for point manipulation/update. FIXME: Need to revert back to a generalized
// brush approach
//--int g_nSelectedPatch = -1;
// HACK: for tracking which view generated the click
// as we dont want to deselect a point on a same point
// click if it is from a different view
int g_nPatchClickedView = -1;
bool g_bSameView = false;
// globals
bool g_bPatchShowBounds = true;
bool g_bPatchWireFrame = false;
bool g_bPatchWeld = true;
bool g_bPatchDrillDown = true;
bool g_bPatchInsertMode = false;
bool g_bPatchBendMode = false;
int g_nPatchBendState = -1;
int g_nPatchInsertState = -1;
int g_nBendOriginIndex = 0;
vec3_t g_vBendOrigin;
bool g_bPatchAxisOnRow = true;
int g_nPatchAxisIndex = 0;
bool g_bPatchLowerEdge = true;
// BEND states
enum
{
BEND_SELECT_ROTATION = 0,
BEND_SELECT_ORIGIN,
BEND_SELECT_EDGE,
BEND_BENDIT,
BEND_STATE_COUNT
};
const char *g_pBendStateMsg[] =
{
"Use TAB to cycle through available bend axis. Press ENTER when the desired one is highlighted.",
"Use TAB to cycle through available rotation axis. This will LOCK around that point. You may also use Shift + Middle Click to select an arbitrary point. Press ENTER when the desired one is highlighted",
"Use TAB to choose which side to bend. Press ENTER when the desired one is highlighted.",
"Use the MOUSE to bend the patch. It uses the same ui rules as Free Rotation. Press ENTER to accept the bend, press ESC to abandon it and exit Bend mode",
""
};
// INSERT states
enum
{
INSERT_SELECT_EDGE = 0,
INSERT_STATE_COUNT
};
const char* g_pInsertStateMsg[] =
{
"Use TAB to cycle through available rows/columns for insertion/deletion. Press INS to insert at the highlight, DEL to remove the pair"
};
float *g_InversePoints[1024];
const float fFullBright = 1.0;
const float fLowerLimit = .50;
const float fDec = .05;
void _SetColor(face_t* f, float fColor[3])
{
return;
fColor[0] = f->d_color[0];
fColor[1] = f->d_color[1];
fColor[2] = f->d_color[2];
qglColor3fv(fColor);
}
void _DecColor(float fColor[3])
{
return;
fColor[0] -= fDec;
fColor[1] -= fDec ;
fColor[2] -= fDec;
for (int i = 0; i < 3; i++)
{
if (fColor[i] <= fLowerLimit)
{
fColor[0] = fFullBright;
fColor[1] = fFullBright;
fColor[2] = fFullBright;
break;
}
}
qglColor3fv(fColor);
}
vec_t __VectorNormalize (vec3_t in, vec3_t out)
{
vec_t length, ilength;
length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
if (length == 0)
{
VectorClear (out);
return 0;
}
ilength = 1.0/length;
out[0] = in[0]*ilength;
out[1] = in[1]*ilength;
out[2] = in[2]*ilength;
return length;
}
void Patch_SetType(patchMesh_t *p, int nType)
{
p->type = (p->type & PATCH_STYLEMASK) | nType;
}
void Patch_SetStyle(patchMesh_t *p, int nStyle)
{
p->type = (p->type & PATCH_TYPEMASK) | nStyle;
}
/*
==================
Patch_MemorySize
==================
*/
int Patch_MemorySize(patchMesh_t *p)
{
return _msize(p);
}
/*
===============
InterpolateInteriorPoints
===============
*/
void InterpolateInteriorPoints( patchMesh_t *p )
{
int i, j, k;
int next, prev;
for ( i = 0 ; i < p->width ; i += 2 )
{
next = ( i == p->width - 1 ) ? 1 : ( i + 1 ) % p->width;
prev = ( i == 0 ) ? p->width - 2 : i - 1;
#if 0
if ( i == 0 )
{
next = ( i + 1 ) % p->width;
prev = p->width - 2; // joined wrap case
}
else if ( i == p->width - 1 )
{
next = 1;
prev = i - 1;
}
else
{
next = ( i + 1 ) % p->width;
prev = i - 1;
}
#endif
for ( j = 0 ; j < p->height ; j++ )
{
for ( k = 0 ; k < 3 ; k++ )
{
p->ctrl[i][j].xyz[k] = ( p->ctrl[next][j].xyz[k] + p->ctrl[prev][j].xyz[k] ) * 0.5;
}
}
}
}
/*
=================
MakeMeshNormals
=================
*/
int neighbors[8][2] = {
{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
};
void Patch_MeshNormals(patchMesh_t *in )
{
int i, j, k, dist;
vec3_t normal;
vec3_t sum;
int count;
vec3_t base;
vec3_t delta;
int x, y;
drawVert_t *dv;
vec3_t around[8], temp;
qboolean good[8];
qboolean wrapWidth, wrapHeight;
float len;
wrapWidth = false;
for ( i = 0 ; i < in->height ; i++ )
{
VectorSubtract( in->ctrl[0][i].xyz,
in->ctrl[in->width-1][i].xyz, delta );
len = VectorLength( delta );
if ( len > 1.0 )
{
break;
}
}
if ( i == in->height )
{
wrapWidth = true;
}
wrapHeight = false;
for ( i = 0 ; i < in->width ; i++ )
{
VectorSubtract( in->ctrl[i][0].xyz,
in->ctrl[i][in->height-1].xyz, delta );
len = VectorLength( delta );
if ( len > 1.0 )
{
break;
}
}
if ( i == in->width)
{
wrapHeight = true;
}
for ( i = 0 ; i < in->width ; i++ )
{
for ( j = 0 ; j < in->height ; j++ )
{
count = 0;
//--dv = reinterpret_cast<drawVert_t*>(in.ctrl[j*in.width+i]);
dv = &in->ctrl[i][j];
VectorCopy( dv->xyz, base );
for ( k = 0 ; k < 8 ; k++ )
{
VectorClear( around[k] );
good[k] = false;
for ( dist = 1 ; dist <= 3 ; dist++ )
{
x = i + neighbors[k][0] * dist;
y = j + neighbors[k][1] * dist;
if ( wrapWidth )
{
if ( x < 0 )
{
x = in->width - 1 + x;
}
else if ( x >= in->width )
{
x = 1 + x - in->width;
}
}
if ( wrapHeight )
{
if ( y < 0 )
{
y = in->height - 1 + y;
}
else if ( y >= in->height )
{
y = 1 + y - in->height;
}
}
if ( x < 0 || x >= in->width || y < 0 || y >= in->height )
{
break; // edge of patch
}
//--VectorSubtract( in.ctrl[y*in.width+x]->xyz, base, temp );
VectorSubtract( in->ctrl[x][y].xyz, base, temp );
if ( __VectorNormalize( temp, temp ) == 0 )
{
continue; // degenerate edge, get more dist
}
else
{
good[k] = true;
VectorCopy( temp, around[k] );
break; // good edge
}
}
}
VectorClear( sum );
for ( k = 0 ; k < 8 ; k++ )
{
if ( !good[k] || !good[(k+1)&7] )
{
continue; // didn't get two points
}
CrossProduct( around[(k+1)&7], around[k], normal );
if ( __VectorNormalize( normal, normal ) == 0 )
{
continue;
}
VectorAdd( normal, sum, sum );
count++;
}
if ( count == 0 )
{
//printf("bad normal\n");
count = 1;
//continue;
}
__VectorNormalize( sum, dv->normal );
}
}
}
/*
==================
Patch_CalcBounds
==================
*/
void Patch_CalcBounds(patchMesh_t *p, vec3_t& vMin, vec3_t& vMax)
{
vMin[0] = vMin[1] = vMin[2] = 99999;
vMax[0] = vMax[1] = vMax[2] = -99999;
p->bDirty = true;
for (int w = 0; w < p->width; w++)
{
for (int h = 0; h < p->height; h++)
{
for (int j = 0; j < 3; j++)
{
float f = p->ctrl[w][h].xyz[j];
if (f < vMin[j])
vMin[j] = f;
if (f > vMax[j])
vMax[j] = f;
}
}
}
}
/*
==================
Brush_RebuildBrush
==================
*/
void Brush_RebuildBrush(brush_t *b, vec3_t vMins, vec3_t vMaxs)
{
//
// Total hack job
// Rebuilds a brush
int i, j;
face_t *f, *next;
vec3_t pts[4][2];
texdef_t texdef;
// free faces
for (j = 0; j < 3; j++)
{
if ((int)vMins[j] == (int)vMaxs[j])
{
vMins[j] -= 4;
vMaxs[j] += 4;
}
}
for (f=b->brush_faces ; f ; f=next)
{
next = f->next;
if (f)
texdef = f->texdef;
Face_Free( f );
}
b->brush_faces = NULL;
// left the last face so we can use its texdef
for (i=0 ; i<3 ; i++)
if (vMaxs[i] < vMins[i])
Error ("Brush_RebuildBrush: backwards");
pts[0][0][0] = vMins[0];
pts[0][0][1] = vMins[1];
pts[1][0][0] = vMins[0];
pts[1][0][1] = vMaxs[1];
pts[2][0][0] = vMaxs[0];
pts[2][0][1] = vMaxs[1];
pts[3][0][0] = vMaxs[0];
pts[3][0][1] = vMins[1];
for (i=0 ; i<4 ; i++)
{
pts[i][0][2] = vMins[2];
pts[i][1][0] = pts[i][0][0];
pts[i][1][1] = pts[i][0][1];
pts[i][1][2] = vMaxs[2];
}
for (i=0 ; i<4 ; i++)
{
f = Face_Alloc();
f->texdef = texdef;
f->texdef.flags &= ~SURF_KEEP;
f->texdef.contents &= ~CONTENTS_KEEP;
f->texdef.flags |= SURF_PATCH;
f->next = b->brush_faces;
b->brush_faces = f;
j = (i+1)%4;
VectorCopy (pts[j][1], f->planepts[0]);
VectorCopy (pts[i][1], f->planepts[1]);
VectorCopy (pts[i][0], f->planepts[2]);
}
f = Face_Alloc();
f->texdef = texdef;
f->texdef.flags &= ~SURF_KEEP;
f->texdef.contents &= ~CONTENTS_KEEP;
f->texdef.flags |= SURF_PATCH;
f->next = b->brush_faces;
b->brush_faces = f;
VectorCopy (pts[0][1], f->planepts[0]);
VectorCopy (pts[1][1], f->planepts[1]);
VectorCopy (pts[2][1], f->planepts[2]);
f = Face_Alloc();
f->texdef = texdef;
f->texdef.flags &= ~SURF_KEEP;
f->texdef.contents &= ~CONTENTS_KEEP;
f->texdef.flags |= SURF_PATCH;
f->next = b->brush_faces;
b->brush_faces = f;
VectorCopy (pts[2][0], f->planepts[0]);
VectorCopy (pts[1][0], f->planepts[1]);
VectorCopy (pts[0][0], f->planepts[2]);
Brush_Build(b);
}
void WINAPI Patch_Rebuild(patchMesh_t *p)
{
vec3_t vMin, vMax;
Patch_CalcBounds(p, vMin, vMax);
Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
p->bDirty = true;
}
/*
==================
AddBrushForPatch
==================
adds a patch brush and ties it to this patch id
*/
brush_t* AddBrushForPatch(patchMesh_t *pm, bool bLinkToWorld )
{
// find the farthest points in x,y,z
vec3_t vMin, vMax;
Patch_CalcBounds(pm, vMin, vMax);
for (int j = 0; j < 3; j++)
{
if (vMin[j] == vMax[j])
{
vMin[j] -= 4;
vMax[j] += 4;
}
}
brush_t *b = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?