gtkradiant/contrib/bobtoolz/DPatch.cpp
spog 0f319946a6 fixed warnings
git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@79 8a3a26a2-13c4-0310-b231-cf6edde360e5
2006-06-11 11:20:33 +00:00

463 lines
10 KiB
C++

/*
BobToolz plugin for GtkRadiant
Copyright (C) 2001 Gordon Biggans
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// DPatch.cpp: implementation of the DPatch class.
//
//////////////////////////////////////////////////////////////////////
#include "DPatch.h"
#include <list>
#include "str.h"
#include "scenelib.h"
#include "ipatch.h"
#include "misc.h"
#include "./dialogs/dialogs-gtk.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// Added patch merging, wahey!
//
// problem is, you cant put patches into entities as yet :(
//
DPatch::DPatch()
{
width = MIN_PATCH_WIDTH;
height = MIN_PATCH_HEIGHT;
QER_entity = NULL;
QER_brush = NULL;
}
DPatch::~DPatch()
{
}
void DPatch::SetTexture(const char *textureName)
{
strcpy(texture, textureName);
}
void CopyDrawVert(const drawVert_t* in, drawVert_t* out)
{
out->lightmap[0] = in->lightmap[0];
out->lightmap[1] = in->lightmap[1];
out->st[0] = in->st[0];
out->st[1] = in->st[1];
VectorCopy(in->normal, out->normal);
VectorCopy(in->xyz, out->xyz);
}
void DPatch::BuildInRadiant(scene::Node* entity)
{
NodeSmartReference patch(GlobalPatchCreator().createPatch());
scene::Node& parent = entity != 0 ? *entity : GlobalRadiant().getMapWorldEntity();
Node_getTraversable(parent)->insert(patch);
GlobalPatchCreator().Patch_setShader(patch, texture);
GlobalPatchCreator().Patch_resize(patch, height, width);
PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch);
for(int x = 0; x < height; x++)
{
for(int y = 0; y < width; y++)
{
PatchControl& p = matrix(y, x);
p.m_vertex[0] = points[x][y].xyz[0];
p.m_vertex[1] = points[x][y].xyz[1];
p.m_vertex[2] = points[x][y].xyz[2];
p.m_texcoord[0] = points[x][y].st[0];
p.m_texcoord[1] = points[x][y].st[1];
}
}
GlobalPatchCreator().Patch_controlPointsChanged(patch);
QER_entity = entity;
QER_brush = patch.get_pointer();
#if 0
int nIndex = g_FuncTable.m_pfnCreatePatchHandle();
//$ FIXME: m_pfnGetPatchHandle
patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData(nIndex);
b->patchBrush = true;
b->pPatch = Patch_Alloc();
b->pPatch->setDims(width,height);
for(int x = 0; x < width; x++)
for(int y = 0; y < height; y++)
CopyDrawVert(&points[x][y], &pm->ctrl[x][y]);
/* if(entity)
{
// strcpy(pm->d_texture->name, texture);
brush_t* brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();
brush->patchBrush = true;
brush->pPatch = pm;
pm->pSymbiot = brush;
pm->bSelected = false;
pm->bOverlay = false; // bleh, f*cks up, just have to wait for a proper function
pm->bDirty = true; // or get my own patch out....
pm->nListID = -1;
g_FuncTable.m_pfnCommitBrushHandleToEntity(brush, entity);
}
else*/ // patch to entity just plain dont work atm
if(entity)
g_FuncTable.m_pfnCommitPatchHandleToEntity(nIndex, pm, texture, entity);
else
g_FuncTable.m_pfnCommitPatchHandleToMap(nIndex, pm, texture);
QER_brush = pm->pSymbiot;
#endif
}
void DPatch::LoadFromPatch(scene::Instance& patch)
{
QER_entity = patch.path().parent().get_pointer();
QER_brush = patch.path().top().get_pointer();
PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch.path().top());
width = static_cast<int>(matrix.x());
height = static_cast<int>(matrix.y());
for(int x = 0; x < height; x++)
{
for(int y = 0; y < width; y++)
{
PatchControl& p = matrix(y, x);
points[x][y].xyz[0] = p.m_vertex[0];
points[x][y].xyz[1] = p.m_vertex[1];
points[x][y].xyz[2] = p.m_vertex[2];
points[x][y].st[0] = p.m_texcoord[0];
points[x][y].st[1] = p.m_texcoord[1];
}
}
SetTexture(GlobalPatchCreator().Patch_getShader(patch.path().top()));
#if 0
SetTexture(brush->pPatch->GetShader());
width = brush->pPatch->getWidth();
height = brush->pPatch->getHeight();
for(int x = 0; x < height; x++)
{
for(int y = 0; y < width; y++)
{
float *p = brush->pPatch->ctrlAt(ROW,x,y);
p[0] = points[x][y].xyz[0];
p[1] = points[x][y].xyz[1];
p[2] = points[x][y].xyz[2];
p[3] = points[x][y].st[0];
p[4] = points[x][y].st[1];
}
}
#endif
}
bool DPatch::ResetTextures(const char *oldTextureName, const char *newTextureName)
{
if( !oldTextureName || !strcmp(texture, oldTextureName))
{
strcpy(texture, newTextureName);
return true;
}
return false;
}
void Build1dArray(vec3_t* array, drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT],
int startX, int startY, int number, bool horizontal, bool inverse)
{
int x = startX, y = startY, i, step;
if(inverse)
step = -1;
else
step = 1;
for(i = 0; i < number; i++)
{
VectorCopy(points[x][y].xyz, array[i]);
if(horizontal)
x+=step;
else
y+=step;
}
}
void Print1dArray(vec3_t* array, int size)
{
for(int i = 0; i < size; i++)
globalOutputStream() << "(" << array[i][0] << " " << array[i][1] << " " << array[i][2] << ")\t";
globalOutputStream() << "\n";
}
bool Compare1dArrays(vec3_t* a1, vec3_t* a2, int size)
{
int i;
bool equal = true;
for(i = 0; i < size; i++)
{
if(!VectorCompare(a1[i], a2[size-i-1]))
{
equal = false;
break;
}
}
return equal;
}
patch_merge_t DPatch::IsMergable(DPatch *other)
{
int i, j;
vec3_t p1Array[4][MAX_PATCH_HEIGHT];
vec3_t p2Array[4][MAX_PATCH_HEIGHT];
int p1ArraySizes[4];
int p2ArraySizes[4];
patch_merge_t merge_info;
Build1dArray(p1Array[0], this->points, 0, 0, this->width, true, false);
Build1dArray(p1Array[1], this->points, this->width-1, 0, this->height, false, false);
Build1dArray(p1Array[2], this->points, this->width-1, this->height-1, this->width, true, true);
Build1dArray(p1Array[3], this->points, 0, this->height-1, this->height, false, true);
Build1dArray(p2Array[0], other->points, 0, 0, other->width, true, false);
Build1dArray(p2Array[1], other->points, other->width-1, 0, other->height, false, false);
Build1dArray(p2Array[2], other->points, other->width-1, other->height-1, other->width, true, true);
Build1dArray(p2Array[3], other->points, 0, other->height-1, other->height, false, true);
p1ArraySizes[0] = this->width;
p1ArraySizes[1] = this->height;
p1ArraySizes[2] = this->width;
p1ArraySizes[3] = this->height;
p2ArraySizes[0] = other->width;
p2ArraySizes[1] = other->height;
p2ArraySizes[2] = other->width;
p2ArraySizes[3] = other->height;
for(i = 0; i < 4; i++)
{
for(j = 0; j < 4; j++)
{
if(p1ArraySizes[i] == p2ArraySizes[j])
{
if(Compare1dArrays(p1Array[i], p2Array[j], p1ArraySizes[i]))
{
merge_info.pos1 = i;
merge_info.pos2 = j;
merge_info.mergable = true;
return merge_info;
}
}
}
}
merge_info.mergable = false;
return merge_info;
}
DPatch* DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2)
{
while(merge_info.pos1 != 2)
{
p1->Transpose();
merge_info.pos1--;
if(merge_info.pos1 < 0)
merge_info.pos1 += 4;
}
while(merge_info.pos2 != 0)
{
p2->Transpose();
merge_info.pos2--;
if(merge_info.pos2 < 0)
merge_info.pos2 += 3;
}
int newHeight = p1->height + p2->height - 1;
if(newHeight > MAX_PATCH_HEIGHT)
return NULL;
DPatch* newPatch = new DPatch();
newPatch->height = newHeight;
newPatch->width = p1->width;
newPatch->SetTexture(p1->texture);
int y = 0;
int i;
for(i = 0; i < p1->height; i++, y++)
for(int x = 0; x < p1->width; x++)
newPatch->points[x][y] = p1->points[x][i];
for(i = 1; i < p2->height; i++, y++)
for(int x = 0; x < p2->width; x++)
newPatch->points[x][y] = p2->points[x][i];
// newPatch->Invert();
return newPatch;
}
void DPatch::Invert()
{
int i, j;
for(i = 0 ; i < width ; i++ )
{
for(j = 0; j < height / 2; j++)
{
std::swap(points[i][height - 1- j], points[i][j]);
}
}
}
void DPatch::Transpose()
{
int i, j, w;
if ( width > height )
{
for ( i = 0 ; i < height ; i++ )
{
for ( j = i + 1 ; j < width ; j++ )
{
if ( j < height )
{
// swap the value
std::swap(points[j][i], points[i][j]);
}
else
{
// just copy
points[i][j] = points[j][i];
}
}
}
}
else
{
for ( i = 0 ; i < width ; i++ )
{
for ( j = i + 1 ; j < height ; j++ )
{
if ( j < width )
{
// swap the value
std::swap(points[i][j], points[j][i]);
}
else
{
// just copy
points[j][i] = points[i][j];
}
}
}
}
w = width;
width = height;
height = w;
Invert();
}
std::list<DPatch> DPatch::Split(bool rows, bool cols)
{
std::list<DPatch> patchList;
int i;
int x, y;
if(rows && height >= 5)
{
for(i = 0; i < (height-1)/2; i++)
{
DPatch p;
p.width = width;
p.height = 3;
p.SetTexture(texture);
for(y = 0; y < 3; y++)
{
for(x = 0; x < p.width; x++)
{
p.points[x][y] = points[x][(i*2)+y];
}
}
patchList.push_back(p);
}
if(cols && width >= 5)
{
std::list<DPatch> patchList2;
for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++)
{
std::list<DPatch> patchList3 = (*patches).Split(false, true);
for(std::list<DPatch>::iterator patches2 = patchList3.begin(); patches2 != patchList3.end(); patches2++)
patchList2.push_front(*patches2);
}
return patchList2;
}
}
else if(cols && width >= 5)
{
for(i = 0; i < (width-1)/2; i++)
{
DPatch p;
p.height = height;
p.width = 3;
p.SetTexture(texture);
for(x = 0; x < 3; x++)
{
for(y = 0; y < p.height; y++)
{
p.points[x][y] = points[(i*2)+x][y];
}
}
patchList.push_back(p);
}
}
return patchList;
}