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 < height; x++)
85 for(int y = 0; y < width; y++)
87 PatchControl& p = matrix(y, x);
88 p.m_vertex[0] = points[x][y].xyz[0];
89 p.m_vertex[1] = points[x][y].xyz[1];
90 p.m_vertex[2] = points[x][y].xyz[2];
91 p.m_texcoord[0] = points[x][y].st[0];
92 p.m_texcoord[1] = points[x][y].st[1];
95 GlobalPatchCreator().Patch_controlPointsChanged(patch);
98 QER_brush = patch.get_pointer();
102 int nIndex = g_FuncTable.m_pfnCreatePatchHandle();
103 //$ FIXME: m_pfnGetPatchHandle
104 patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData(nIndex);
106 b->patchBrush = true;
107 b->pPatch = Patch_Alloc();
108 b->pPatch->setDims(width,height);
110 for(int x = 0; x < width; x++)
111 for(int y = 0; y < height; y++)
112 CopyDrawVert(&points[x][y], &pm->ctrl[x][y]);
116 // strcpy(pm->d_texture->name, texture);
118 brush_t* brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();
119 brush->patchBrush = true;
122 pm->pSymbiot = brush;
123 pm->bSelected = false;
124 pm->bOverlay = false; // bleh, f*cks up, just have to wait for a proper function
125 pm->bDirty = true; // or get my own patch out....
128 g_FuncTable.m_pfnCommitBrushHandleToEntity(brush, entity);
130 else*/ // patch to entity just plain dont work atm
133 g_FuncTable.m_pfnCommitPatchHandleToEntity(nIndex, pm, texture, entity);
135 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 < height; x++)
153 for(int y = 0; y < width; y++)
155 PatchControl& p = matrix(y, x);
156 points[x][y].xyz[0] = p.m_vertex[0];
157 points[x][y].xyz[1] = p.m_vertex[1];
158 points[x][y].xyz[2] = p.m_vertex[2];
159 points[x][y].st[0] = p.m_texcoord[0];
160 points[x][y].st[1] = p.m_texcoord[1];
163 SetTexture(GlobalPatchCreator().Patch_getShader(patch.path().top()));
166 SetTexture(brush->pPatch->GetShader());
168 width = brush->pPatch->getWidth();
169 height = brush->pPatch->getHeight();
171 for(int x = 0; x < height; x++)
173 for(int y = 0; y < width; y++)
175 float *p = brush->pPatch->ctrlAt(ROW,x,y);
176 p[0] = points[x][y].xyz[0];
177 p[1] = points[x][y].xyz[1];
178 p[2] = points[x][y].xyz[2];
179 p[3] = points[x][y].st[0];
180 p[4] = points[x][y].st[1];
186 bool DPatch::ResetTextures(const char *oldTextureName, const char *newTextureName)
188 if( !oldTextureName || !strcmp(texture, oldTextureName))
190 strcpy(texture, newTextureName);
197 void Build1dArray(vec3_t* array, drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT],
198 int startX, int startY, int number, bool horizontal, bool inverse)
200 int x = startX, y = startY, i, step;
207 for(i = 0; i < number; i++)
209 VectorCopy(points[x][y].xyz, array[i]);
218 void Print1dArray(vec3_t* array, int size)
220 for(int i = 0; i < size; i++)
221 globalOutputStream() << "(" << array[i][0] << " " << array[i][1] << " " << array[i][2] << ")\t";
222 globalOutputStream() << "\n";
225 bool Compare1dArrays(vec3_t* a1, vec3_t* a2, int size)
230 for(i = 0; i < size; i++)
232 if(!VectorCompare(a1[i], a2[size-i-1]))
241 patch_merge_t DPatch::IsMergable(DPatch *other)
244 vec3_t p1Array[4][MAX_PATCH_HEIGHT];
245 vec3_t p2Array[4][MAX_PATCH_HEIGHT];
250 patch_merge_t merge_info;
252 Build1dArray(p1Array[0], this->points, 0, 0, this->width, true, false);
253 Build1dArray(p1Array[1], this->points, this->width-1, 0, this->height, false, false);
254 Build1dArray(p1Array[2], this->points, this->width-1, this->height-1, this->width, true, true);
255 Build1dArray(p1Array[3], this->points, 0, this->height-1, this->height, false, true);
257 Build1dArray(p2Array[0], other->points, 0, 0, other->width, true, false);
258 Build1dArray(p2Array[1], other->points, other->width-1, 0, other->height, false, false);
259 Build1dArray(p2Array[2], other->points, other->width-1, other->height-1, other->width, true, true);
260 Build1dArray(p2Array[3], other->points, 0, other->height-1, other->height, false, true);
262 p1ArraySizes[0] = this->width;
263 p1ArraySizes[1] = this->height;
264 p1ArraySizes[2] = this->width;
265 p1ArraySizes[3] = this->height;
267 p2ArraySizes[0] = other->width;
268 p2ArraySizes[1] = other->height;
269 p2ArraySizes[2] = other->width;
270 p2ArraySizes[3] = other->height;
272 for(i = 0; i < 4; i++)
274 for(j = 0; j < 4; j++)
276 if(p1ArraySizes[i] == p2ArraySizes[j])
278 if(Compare1dArrays(p1Array[i], p2Array[j], p1ArraySizes[i]))
282 merge_info.mergable = true;
289 merge_info.mergable = false;
293 DPatch* DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2)
295 while(merge_info.pos1 != 2)
299 if(merge_info.pos1 < 0)
300 merge_info.pos1 += 4;
303 while(merge_info.pos2 != 0)
307 if(merge_info.pos2 < 0)
308 merge_info.pos2 += 3;
311 /* The Patch will never be reaching max, previous comparissions make sure,
312 for 2 patches with 3x3 size. Results always in a patch of 3x5. (31 is max currently)
313 int newHeight = p1->height + p2->height - 1; anyway = 5
314 if(newHeight > MAX_PATCH_HEIGHT)
316 int newWidth = p1->width + p2->width - 1;
317 if(newWidth > MAX_PATCH_WIDTH)
320 DPatch* newPatch = new DPatch();
322 newPatch->height = 3;
324 newPatch->SetTexture(p1->texture);
326 for(int y = 0; y < 3; y++)
327 for(int x = 0; x < 3; x++)
328 newPatch->points[x][y] = p1->points[x][y];
330 for(int y = 1; y < 3; y++)
331 for(int x = 0; x < 3; x++)
332 newPatch->points[x][y+2] = p2->points[x][y];
334 // newPatch->Invert();
338 void DPatch::Invert()
342 for(i = 0 ; i < width ; i++ )
344 for(j = 0; j < height / 2; j++)
346 std::swap(points[i][height - 1- j], points[i][j]);
351 void DPatch::Transpose()
355 if ( width > height )
357 for ( i = 0 ; i < height ; i++ )
359 for ( j = i + 1 ; j < width ; j++ )
364 std::swap(points[j][i], points[i][j]);
369 points[i][j] = points[j][i];
376 for ( i = 0 ; i < width ; i++ )
378 for ( j = i + 1 ; j < height ; j++ )
383 std::swap(points[i][j], points[j][i]);
388 points[j][i] = points[i][j];
401 std::list<DPatch> DPatch::SplitRows()
403 std::list<DPatch> patchList;
409 for(i = 0; i < (height-1)/2; i++)
415 p.SetTexture(texture);
416 for(x = 0; x < 3; x++)
418 for(y = 0; y < p.width; y++)
420 p.points[x][y] = points[(i*2)+x][y];
423 patchList.push_back(p);
426 //This returns exactly what comes in.. I don't know better :/
427 //If nothing is returned, the Patch in Radiant is just deleted - I suppose for evil follow up erros.
432 p.SetTexture(texture);
434 for(x = 0; x < p.height; x++)
436 for(y = 0; y < p.width; y++)
438 p.points[x][y] = points[x][y];
441 patchList.push_back(p);
446 std::list<DPatch> DPatch::SplitCols()
448 std::list<DPatch> patchList;
454 for(i = 0; i < (width-1)/2; i++)
460 p.SetTexture(texture);
462 for(x = 0; x < p.height; x++)
464 for(y = 0; y < 3; y++)
466 p.points[x][y] = points[x][(i*2)+y];
469 patchList.push_back(p);
473 //This returns exactly what comes in.. I don't know better :/
474 //If nothing is returned, the Patch in Radiant is just deleted - I suppose for evil follow up erros.
479 p.SetTexture(texture);
481 for(x = 0; x < p.height; x++)
483 for(y = 0; y < p.width; y++)
485 p.points[x][y] = points[x][y];
488 patchList.push_back(p);
493 std::list<DPatch> DPatch::Split()
495 std::list<DPatch> patchList;
501 for(i = 0; i < (width-1)/2; i++)
507 p.SetTexture(texture);
509 for(x = 0; x < p.height; x++)
511 for(y = 0; y < 3; y++)
513 p.points[x][y] = points[x][(i*2)+y];
516 patchList.push_back(p);
518 std::list<DPatch> patchList2;
519 for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++)
521 std::list<DPatch> patchList3 = (*patches).SplitRows();
522 for(std::list<DPatch>::iterator patches2 = patchList3.begin(); patches2 != patchList3.end(); patches2++)
523 patchList2.push_front(*patches2);
527 } else if(height >= 5)
529 for(i = 0; i < (height-1)/2; i++)
535 p.SetTexture(texture);
536 for(x = 0; x < 3; x++)
538 for(y = 0; y < p.width; y++)
540 p.points[x][y] = points[(i*2)+x][y];
543 patchList.push_back(p);
545 std::list<DPatch> patchList2;
546 for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++)
548 std::list<DPatch> patchList3 = (*patches).SplitCols();
549 for(std::list<DPatch>::iterator patches2 = patchList3.begin(); patches2 != patchList3.end(); patches2++)
550 patchList2.push_front(*patches2);
556 //This returns exactly what comes in.. I don't know better :/
557 //If nothing is returned, the Patch in Radiant is just deleted - I suppose for evil follow up erros.
562 p.SetTexture(texture);
564 for(x = 0; x < p.height; x++)
566 for(y = 0; y < p.width; y++)
568 p.points[x][y] = points[x][y];
571 patchList.push_back(p);