]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/DPatch.cpp
more eol-style
[xonotic/netradiant.git] / contrib / bobtoolz / DPatch.cpp
1 /*
2 BobToolz plugin for GtkRadiant
3 Copyright (C) 2001 Gordon Biggans
4
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.
9
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.
14
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
18 */
19
20 // DPatch.cpp: implementation of the DPatch class.
21 //
22 //////////////////////////////////////////////////////////////////////
23
24 #include "StdAfx.h"
25 #include "DPatch.h"
26 #include "misc.h"
27 #include "./dialogs/dialogs-gtk.h"
28
29 //////////////////////////////////////////////////////////////////////
30 // Construction/Destruction
31 //////////////////////////////////////////////////////////////////////
32
33 //              Added patch merging, wahey!
34
35 //
36 //              problem is, you cant put patches into entities as yet :(
37 //
38
39 DPatch::DPatch()
40 {
41         width = MIN_PATCH_WIDTH;
42         height = MIN_PATCH_HEIGHT;
43         QER_patch = NULL;
44         QER_brush = NULL;
45 }
46
47 DPatch::~DPatch()
48 {
49
50 }
51
52 void DPatch::SetTexture(const char *textureName)
53 {
54         strcpy(texture, textureName);
55 }
56
57 void CopyDrawVert(const drawVert_t* in, drawVert_t* out)
58 {
59         out->lightmap[0] = in->lightmap[0];
60         out->lightmap[1] = in->lightmap[1];
61         out->st[0] = in->st[0];
62         out->st[1] = in->st[1];
63         VectorCopy(in->normal, out->normal);
64         VectorCopy(in->xyz, out->xyz);
65 }
66
67 void DPatch::BuildInRadiant(void* entity)
68 {
69         int nIndex = g_FuncTable.m_pfnCreatePatchHandle();
70     //$ FIXME: m_pfnGetPatchHandle
71         patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData(nIndex);
72
73         pm->height = height;
74         pm->width = width;
75
76         for(int x = 0; x < width; x++)
77                 for(int y = 0; y < height; y++)
78                         CopyDrawVert(&points[x][y], &pm->ctrl[x][y]);
79
80         QER_patch = pm;
81
82 /*      if(entity)
83         {
84 //              strcpy(pm->d_texture->name, texture);
85
86                 brush_t* brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();
87                 brush->patchBrush = TRUE;
88                 brush->pPatch = pm;             
89
90                 pm->pSymbiot = brush;
91                 pm->bSelected = false;
92                 pm->bOverlay = false;   // bleh, f*cks up, just have to wait for a proper function
93                 pm->bDirty = true;              // or get my own patch out....
94                 pm->nListID = -1;
95
96                 g_FuncTable.m_pfnCommitBrushHandleToEntity(brush, entity);
97         }
98         else*/  // patch to entity just plain dont work atm
99
100   if(entity)
101     g_FuncTable.m_pfnCommitPatchHandleToEntity(nIndex, pm, texture, entity);
102   else
103                 g_FuncTable.m_pfnCommitPatchHandleToMap(nIndex, pm, texture);
104
105         QER_brush = pm->pSymbiot;
106 }
107
108 void DPatch::LoadFromBrush_t(brush_t* brush)
109 {
110         QER_brush = brush;
111         QER_patch = brush->pPatch;
112
113         SetTexture(QER_patch->pShader->getName());
114
115         for(int x = 0; x < QER_patch->width; x++)
116                 for(int y = 0; y < QER_patch->height; y++)
117                         CopyDrawVert(&QER_patch->ctrl[x][y], &points[x][y]);
118
119         width = QER_patch->width;
120         height = QER_patch->height;
121 }
122
123 void DPatch::RemoveFromRadiant()
124 {
125         if(QER_brush)
126                 g_FuncTable.m_pfnDeleteBrushHandle(QER_brush);
127 }
128
129 bool DPatch::ResetTextures(const char *oldTextureName, const char *newTextureName)
130 {
131         if( !oldTextureName || !strcmp(texture, oldTextureName))
132         {
133                 strcpy(texture, newTextureName);
134                 return TRUE;
135         }
136
137         return FALSE;
138 }
139
140 void Build1dArray(vec3_t* array, drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT], 
141                                   int startX, int startY, int number, bool horizontal, bool inverse)
142 {
143         int x = startX, y = startY, i, step;
144
145         if(inverse)
146                 step = -1;
147         else
148                 step = 1;
149
150         for(i = 0; i < number; i++)
151         {
152                 VectorCopy(points[x][y].xyz, array[i]);
153
154                 if(horizontal)
155                         x+=step;
156                 else
157                         y+=step;
158         }
159 }
160
161 void Print1dArray(vec3_t* array, int size)
162 {
163         for(int i = 0; i < size; i++)
164                 Sys_Printf("(%.0f %.0f %.0f)\t", array[i][0], array[i][1], array[i][2]);
165         Sys_Printf("\n");
166 }
167
168 bool Compare1dArrays(vec3_t* a1, vec3_t* a2, int size)
169 {
170         int i;
171         bool equal = true;
172
173         for(i = 0; i < size; i++)
174         {
175                 if(!VectorCompare(a1[i], a2[size-i-1]))
176                 {
177                         equal = false;
178                         break;
179                 }
180         }
181         return equal;
182 }
183
184 patch_merge_t DPatch::IsMergable(DPatch *other)
185 {
186         int i, j;
187         vec3_t p1Array[4][MAX_PATCH_HEIGHT];
188         vec3_t p2Array[4][MAX_PATCH_HEIGHT];
189
190         int p1ArraySizes[4];
191         int p2ArraySizes[4];
192
193         patch_merge_t merge_info;
194
195         Build1dArray(p1Array[0], this->points, 0,                               0,                              this->width,    true,   false);
196         Build1dArray(p1Array[1], this->points, this->width-1,   0,                              this->height,   false,  false);
197         Build1dArray(p1Array[2], this->points, this->width-1,   this->height-1, this->width,    true,   true);
198         Build1dArray(p1Array[3], this->points, 0,                               this->height-1, this->height,   false,  true);
199
200         Build1dArray(p2Array[0], other->points, 0,                              0,                                      other->width,   true,   false);
201         Build1dArray(p2Array[1], other->points, other->width-1, 0,                                      other->height,  false,  false);
202         Build1dArray(p2Array[2], other->points, other->width-1, other->height-1,        other->width,   true,   true);
203         Build1dArray(p2Array[3], other->points, 0,                              other->height-1,        other->height,  false,  true);
204
205         p1ArraySizes[0] = this->width;
206         p1ArraySizes[1] = this->height;
207         p1ArraySizes[2] = this->width;
208         p1ArraySizes[3] = this->height;
209
210         p2ArraySizes[0] = other->width;
211         p2ArraySizes[1] = other->height;
212         p2ArraySizes[2] = other->width;
213         p2ArraySizes[3] = other->height;
214
215         for(i = 0; i < 4; i++)
216         {
217                 for(j = 0; j < 4; j++)
218                 {
219                         if(p1ArraySizes[i] == p2ArraySizes[j])
220                         {
221                                 if(Compare1dArrays(p1Array[i], p2Array[j], p1ArraySizes[i]))
222                                 {
223                                         merge_info.pos1 = i;
224                                         merge_info.pos2 = j;
225                                         merge_info.mergable = true;
226                                         return merge_info;
227                                 }
228                         }
229                 }
230         }
231         
232         merge_info.mergable = false;
233         return merge_info;
234 }
235
236 DPatch* DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2)
237 {
238         while(merge_info.pos1 != 2)
239         {
240                 p1->Transpose();
241                 merge_info.pos1--;
242                 if(merge_info.pos1 < 0)
243                         merge_info.pos1 += 4;
244         }
245
246         while(merge_info.pos2 != 0)
247         {
248                 p2->Transpose();
249                 merge_info.pos2--;
250                 if(merge_info.pos2 < 0)
251                         merge_info.pos2 += 3;
252         }
253
254         int newHeight = p1->height + p2->height - 1;
255         if(newHeight > MAX_PATCH_HEIGHT)
256                 return NULL;
257
258         DPatch* newPatch = new DPatch();
259
260         newPatch->height        = newHeight;
261         newPatch->width         = p1->width;
262         newPatch->SetTexture(p1->texture);
263
264         int y = 0;
265         int i;
266         for(i = 0; i < p1->height; i++, y++)
267                 for(int x = 0; x < p1->width; x++)
268                         memcpy(&newPatch->points[x][y], &p1->points[x][i],      sizeof(drawVert_t));
269
270         for(i = 1; i < p2->height; i++, y++)
271                 for(int x = 0; x < p2->width; x++)
272                         memcpy(&newPatch->points[x][y], &p2->points[x][i],      sizeof(drawVert_t));
273
274 //      newPatch->Invert();
275
276         return newPatch;
277 }
278
279 void DPatch::Invert()
280 {
281         drawVert_t vertTemp;
282         int i, j;
283
284         for(i = 0 ; i < width ; i++ ) 
285         {
286                 for(j = 0; j < height / 2; j++)
287                 {
288                         memcpy(&vertTemp, &points[i][height - 1- j], sizeof (drawVert_t));
289                         memcpy(&points[i][height - 1 - j], &points[i][j], sizeof(drawVert_t));
290                         memcpy(&points[i][j], &vertTemp, sizeof(drawVert_t));
291                 }
292         }
293 }
294
295 void DPatch::Transpose()
296 {
297         int             i, j, w;
298         drawVert_t dv;
299
300         if ( width > height ) 
301         {
302                 for ( i = 0 ; i < height ; i++ ) 
303                 {
304                         for ( j = i + 1 ; j < width ; j++ ) 
305                         {
306                                 if ( j < height ) 
307                                 {
308                                         // swap the value
309                                         memcpy(&dv,                             &points[j][i],  sizeof(drawVert_t));
310                                         memcpy(&points[j][i],   &points[i][j],  sizeof(drawVert_t));
311                                         memcpy(&points[i][j],   &dv,                    sizeof(drawVert_t));
312                                 } 
313                                 else 
314                                 {
315                                 // just copy
316                                         memcpy(&points[i][j],   &points[j][i],  sizeof(drawVert_t));
317                         }
318                 }
319                  }
320         } 
321         else 
322         {
323                 for ( i = 0 ; i < width ; i++ ) 
324         {
325                         for ( j = i + 1 ; j < height ; j++ ) 
326                         {
327                         if ( j < width ) 
328                                 {
329                                         // swap the value
330                                         memcpy(&dv,                             &points[i][j],  sizeof(drawVert_t));
331                                         memcpy(&points[i][j],   &points[j][i],  sizeof(drawVert_t));
332                                 memcpy(&points[j][i],   &dv,                    sizeof(drawVert_t));
333                         } 
334                                 else 
335                                 {
336                                 // just copy
337                                         memcpy(&points[j][i],   &points[i][j],  sizeof(drawVert_t));
338                         }
339                 }
340         }
341     }
342
343         w = width;
344         width = height;
345         height = w;
346
347         Invert();
348 }
349
350 list<DPatch> DPatch::Split(bool rows, bool cols)
351 {
352         list<DPatch> patchList;
353         int i;
354         int x, y;
355
356         if(rows && height >= 5)
357         {
358                 for(i = 0; i < (height-1)/2; i++)
359                 {
360                         DPatch p;
361
362                         p.width = width;
363                         p.height = 3;
364                         p.SetTexture(texture);
365
366                         for(y = 0; y < 3; y++)
367                         {
368                                 for(x = 0; x < p.width; x++)
369                                 {
370                                         memcpy(&p.points[x][y], &points[x][(i*2)+y],    sizeof(drawVert_t));
371                                 }
372                         }
373                         patchList.push_back(p);
374                 }
375
376                 if(cols && width >= 5)
377                 {
378                         list<DPatch> patchList2;
379
380                         for(list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++)
381                         {
382                                 list<DPatch> patchList3 = (*patches).Split(false, true);
383                                 
384                                 for(list<DPatch>::iterator patches2 = patchList3.begin(); patches2 != patchList3.end(); patches2++)
385                                         patchList2.push_front(*patches2);
386                         }
387
388                         return patchList2;
389                 }
390         }
391         else if(cols && width >= 5)
392         {
393                 for(i = 0; i < (width-1)/2; i++)
394                 {
395                         DPatch p;
396
397                         p.height = height;
398                         p.width = 3;
399                         p.SetTexture(texture);
400
401                         for(x = 0; x < 3; x++)
402                         {
403                                 for(y = 0; y < p.height; y++)
404                                 {
405                                         memcpy(&p.points[x][y], &points[(i*2)+x][y],    sizeof(drawVert_t));
406                                 }
407                         }
408
409                         patchList.push_back(p);
410                 }
411         }
412
413         return patchList;
414 }