2 BobToolz plugin for GtkRadiant
3 Copyright (C) 2001 Gordon Biggans
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // DPatch.cpp: implementation of the DPatch class.
22 //////////////////////////////////////////////////////////////////////
33 #include "./dialogs/dialogs-gtk.h"
35 //////////////////////////////////////////////////////////////////////
36 // Construction/Destruction
37 //////////////////////////////////////////////////////////////////////
39 // Added patch merging, wahey!
42 // problem is, you cant put patches into entities as yet :(
47 width = MIN_PATCH_WIDTH;
48 height = MIN_PATCH_HEIGHT;
58 void DPatch::SetTexture(const char *textureName)
60 strcpy(texture, textureName);
63 void CopyDrawVert(const drawVert_t *in, drawVert_t *out)
65 out->lightmap[0] = in->lightmap[0];
66 out->lightmap[1] = in->lightmap[1];
67 out->st[0] = in->st[0];
68 out->st[1] = in->st[1];
69 VectorCopy(in->normal, out->normal);
70 VectorCopy(in->xyz, out->xyz);
73 void DPatch::BuildInRadiant(scene::Node *entity)
75 NodeSmartReference patch(GlobalPatchCreator().createPatch());
77 scene::Node &parent = entity != 0 ? *entity : GlobalRadiant().getMapWorldEntity();
78 Node_getTraversable(parent)->insert(patch);
80 GlobalPatchCreator().Patch_setShader(patch, texture);
81 GlobalPatchCreator().Patch_resize(patch, height, width);
82 PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch);
83 for (int x = 0; x < width; x++) {
84 for (int y = 0; y < height; y++) {
85 PatchControl &p = matrix(x, y);
86 p.m_vertex[0] = points[x][y].xyz[0];
87 p.m_vertex[1] = points[x][y].xyz[1];
88 p.m_vertex[2] = points[x][y].xyz[2];
89 p.m_texcoord[0] = points[x][y].st[0];
90 p.m_texcoord[1] = points[x][y].st[1];
93 GlobalPatchCreator().Patch_controlPointsChanged(patch);
96 QER_brush = patch.get_pointer();
100 int nIndex = g_FuncTable.m_pfnCreatePatchHandle();
101 //$ FIXME: m_pfnGetPatchHandle
102 patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData( nIndex );
104 b->patchBrush = true;
105 b->pPatch = Patch_Alloc();
106 b->pPatch->setDims( width,height );
108 for ( int x = 0; x < width; x++ )
109 for ( int y = 0; y < height; y++ )
110 CopyDrawVert( &points[x][y], &pm->ctrl[x][y] );
114 // strcpy(pm->d_texture->name, texture);
116 brush_t* brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();
117 brush->patchBrush = true;
120 pm->pSymbiot = brush;
121 pm->bSelected = false;
122 pm->bOverlay = false; // bleh, f*cks up, just have to wait for a proper function
123 pm->bDirty = true; // or get my own patch out....
126 g_FuncTable.m_pfnCommitBrushHandleToEntity(brush, entity);
128 else*/ // patch to entity just plain dont work atm
131 g_FuncTable.m_pfnCommitPatchHandleToEntity( nIndex, pm, texture, entity );
134 g_FuncTable.m_pfnCommitPatchHandleToMap( nIndex, pm, texture );
137 QER_brush = pm->pSymbiot;
141 void DPatch::LoadFromPatch(scene::Instance &patch)
143 QER_entity = patch.path().parent().get_pointer();
144 QER_brush = patch.path().top().get_pointer();
146 PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch.path().top());
148 width = static_cast<int>( matrix.x());
149 height = static_cast<int>( matrix.y());
151 for (int x = 0; x < width; x++) {
152 for (int y = 0; y < height; y++) {
153 PatchControl &p = matrix(x, y);
154 points[x][y].xyz[0] = p.m_vertex[0];
155 points[x][y].xyz[1] = p.m_vertex[1];
156 points[x][y].xyz[2] = p.m_vertex[2];
157 points[x][y].st[0] = p.m_texcoord[0];
158 points[x][y].st[1] = p.m_texcoord[1];
161 SetTexture(GlobalPatchCreator().Patch_getShader(patch.path().top()));
164 SetTexture( brush->pPatch->GetShader() );
166 width = brush->pPatch->getWidth();
167 height = brush->pPatch->getHeight();
169 for ( int x = 0; x < height; x++ )
171 for ( int y = 0; y < width; y++ )
173 float *p = brush->pPatch->ctrlAt( ROW,x,y );
174 p[0] = points[x][y].xyz[0];
175 p[1] = points[x][y].xyz[1];
176 p[2] = points[x][y].xyz[2];
177 p[3] = points[x][y].st[0];
178 p[4] = points[x][y].st[1];
184 bool DPatch::ResetTextures(const char *oldTextureName, const char *newTextureName)
186 if (!oldTextureName || !strcmp(texture, oldTextureName)) {
187 strcpy(texture, newTextureName);
194 void Build1dArray(vec3_t *array, drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT],
195 int startX, int startY, int number, bool horizontal, bool inverse)
197 int x = startX, y = startY, i, step;
205 for (i = 0; i < number; i++) {
206 VectorCopy(points[x][y].xyz, array[i]);
216 void Print1dArray(vec3_t *array, int size)
218 for (int i = 0; i < size; i++) {
219 globalOutputStream() << "(" << array[i][0] << " " << array[i][1] << " " << array[i][2] << ")\t";
221 globalOutputStream() << "\n";
224 bool Compare1dArrays(vec3_t *a1, vec3_t *a2, int size)
229 for (i = 0; i < size; i++) {
230 if (!VectorCompare(a1[i], a2[size - i - 1])) {
238 patch_merge_t DPatch::IsMergable(DPatch *other)
241 vec3_t p1Array[4][MAX_PATCH_HEIGHT];
242 vec3_t p2Array[4][MAX_PATCH_HEIGHT];
247 patch_merge_t merge_info;
249 Build1dArray(p1Array[0], this->points, 0, 0, this->width, true, false);
250 Build1dArray(p1Array[1], this->points, this->width - 1, 0, this->height, false, false);
251 Build1dArray(p1Array[2], this->points, this->width - 1, this->height - 1, this->width, true, true);
252 Build1dArray(p1Array[3], this->points, 0, this->height - 1, this->height, false, true);
254 Build1dArray(p2Array[0], other->points, 0, 0, other->width, true, false);
255 Build1dArray(p2Array[1], other->points, other->width - 1, 0, other->height, false, false);
256 Build1dArray(p2Array[2], other->points, other->width - 1, other->height - 1, other->width, true, true);
257 Build1dArray(p2Array[3], other->points, 0, other->height - 1, other->height, false, true);
259 p1ArraySizes[0] = this->width;
260 p1ArraySizes[1] = this->height;
261 p1ArraySizes[2] = this->width;
262 p1ArraySizes[3] = this->height;
264 p2ArraySizes[0] = other->width;
265 p2ArraySizes[1] = other->height;
266 p2ArraySizes[2] = other->width;
267 p2ArraySizes[3] = other->height;
269 for (i = 0; i < 4; i++) {
270 for (j = 0; j < 4; j++) {
271 if (p1ArraySizes[i] == p2ArraySizes[j]) {
272 if (Compare1dArrays(p1Array[i], p2Array[j], p1ArraySizes[i])) {
275 merge_info.mergable = true;
282 merge_info.mergable = false;
286 DPatch *DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2)
288 while (merge_info.pos1 != 2) {
291 if (merge_info.pos1 < 0) {
292 merge_info.pos1 += 4;
296 while (merge_info.pos2 != 0) {
299 if (merge_info.pos2 < 0) {
300 merge_info.pos2 += 3;
304 int newHeight = p1->height + p2->height - 1;
305 if (newHeight > MAX_PATCH_HEIGHT) {
309 DPatch *newPatch = new DPatch();
311 newPatch->height = newHeight;
312 newPatch->width = p1->width;
313 newPatch->SetTexture(p1->texture);
315 for (int y = 0; y < p1->height; y++) {
316 for (int x = 0; x < p1->width; x++) {
317 newPatch->points[x][y] = p1->points[x][y];
321 for (int y = 1; y < p2->height; y++) {
322 for (int x = 0; x < p2->width; x++) {
323 newPatch->points[x][(y + p1->height - 1)] = p2->points[x][y];
327 // newPatch->Invert();
331 void DPatch::Invert()
335 for (i = 0; i < width; i++) {
336 for (j = 0; j < height / 2; j++) {
337 std::swap(points[i][height - 1 - j], points[i][j]);
343 //Was used for debugging, obsolete function
344 DPatch* DPatch::TransposePatch(DPatch *p1)
346 globalOutputStream() << "Source patch ";
349 globalOutputStream() << "Transposed";
352 DPatch* newPatch = new DPatch();
353 newPatch->height = p1->height;
354 newPatch->width = p1->width;
355 newPatch->SetTexture(p1->texture);
357 for(int x = 0; x < p1->height; x++)
359 for(int y = 0; y < p1->width; y++)
361 newPatch->points[x][y] = p1->points[x][y];
367 //Function to figure out what is actually going wrong.
368 void DPatch::DebugPrint()
370 globalOutputStream() << "width: " << width << "\theight: " << height << "\n";
371 for(int x = 0; x < height; x++)
373 for(int y = 0; y < width; y++)
375 globalOutputStream() << "\t(" << points[x][y].xyz[0] << " " << points[x][y].xyz[1] << " " << points[x][y].xyz[2] << ")\t";
377 globalOutputStream() << "\n";
382 void DPatch::Transpose()
386 if (width > height) {
387 for (i = 0; i < height; i++) {
388 for (j = i + 1; j < width; j++) {
391 std::swap(points[j][i], points[i][j]);
394 points[i][j] = points[j][i];
399 for (i = 0; i < width; i++) {
400 for (j = i + 1; j < height; j++) {
403 std::swap(points[i][j], points[j][i]);
406 points[j][i] = points[i][j];
419 std::list<DPatch> DPatch::SplitCols()
421 std::list<DPatch> patchList;
426 for (i = 0; i < (height - 1) / 2; i++) {
430 p.height = MIN_PATCH_HEIGHT;
431 p.SetTexture(texture);
432 for (x = 0; x < p.width; x++) {
433 for (y = 0; y < MIN_PATCH_HEIGHT; y++) {
434 p.points[x][y] = points[x][(i * 2) + y];
437 patchList.push_back(p);
440 //globalErrorStream() << "bobToolz SplitPatchRows: Patch has not enough rows for splitting.\n";
441 patchList.push_back(*this);
446 std::list<DPatch> DPatch::SplitRows()
448 std::list<DPatch> patchList;
453 for (i = 0; i < (width - 1) / 2; i++) {
456 p.width = MIN_PATCH_WIDTH;
458 p.SetTexture(texture);
460 for (x = 0; x < MIN_PATCH_WIDTH; x++) {
461 for (y = 0; y < p.height; y++) {
462 p.points[x][y] = points[(i * 2) + x][y];
465 patchList.push_back(p);
468 patchList.push_back(*this);
473 std::list<DPatch> DPatch::Split()
475 std::list<DPatch> patchList;
480 std::list<DPatch> patchColList = SplitCols();
481 for (std::list<DPatch>::iterator patchesCol = patchColList.begin();
482 patchesCol != patchColList.end(); patchesCol++) {
483 std::list<DPatch> patchRowList = (*patchesCol).SplitRows();
484 for (std::list<DPatch>::iterator patchesRow = patchRowList.begin();
485 patchesRow != patchRowList.end(); patchesRow++) {
486 patchList.push_front(*patchesRow);
489 } else if (height >= 5) {
490 std::list<DPatch> patchRowList = SplitRows();
491 for (std::list<DPatch>::iterator patchesRow = patchRowList.begin();
492 patchesRow != patchRowList.end(); patchesRow++) {
493 patchList.push_front(*patchesRow);
496 //globalErrorStream() << "bobToolz SplitPatchRows: Patch has not enough rows for splitting.\n";
497 patchList.push_back(*this);