Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Editor.cpp
Go to the documentation of this file.
1 /* Project MAGIC
2  John DiCamillo Software Consulting
3  Copyright © 1994-1997. All Rights Reserved.
4 
5  SUBSYSTEM: Magic.exe Application
6  FILE: Editor.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Source file for implementation of Selector
13 */
14 
15 
16 #include "stdafx.h"
17 #include "Editor.h"
18 #include "MagicDoc.h"
19 #include "ModelView.h"
20 #include "Selection.h"
21 
22 // +----------------------------------------------------------------------+
23 
24 
25 static float project_u(Vec3& v, int style)
26 {
27  switch (style) {
28  case 0: return v.x; // PLAN
29  case 1: return v.x; // FRONT
30  case 2: return v.z; // SIDE
31  }
32 
33  return v.x;
34 }
35 
36 static float project_v(Vec3& v, int style)
37 {
38  switch (style) {
39  case 0: return -v.y; // PLAN
40  case 1: return -v.z; // FRONT
41  case 2: return -v.y; // SIDE
42  }
43 
44  return -v.y;
45 }
46 
47 static float project_u_cylindrical(Vec3& v, int axis)
48 {
49  float t = 0.0f;
50 
51  switch (axis) {
52  // PLAN
53  case 0: if (v.x == 0)
54  return 0.0f;
55  t = v.y/v.x;
56  return (float) atan(t);
57 
58  // FRONT
59  case 1: if (v.x == 0)
60  return 0.0f;
61  t = v.z/v.x;
62  return (float) atan(t);
63 
64  // SIDE
65  case 2: return (float) atan2(v.z, v.y); // SIDE
66  }
67 
68  return project_u(v, axis);
69 }
70 
71 static float project_v_cylindrical(Vec3& v, int axis)
72 {
73  switch (axis) {
74  case 0: return v.z; // PLAN
75  case 1: return v.y; // FRONT
76  case 2: return v.x; // SIDE
77  }
78 
79  return project_v(v, axis);
80 }
81 
82 void
84  int mapping, int axis, float scale_u, float scale_v,
85  int flip, int mirror, int rotate)
86 {
87  // save state:
88  EditCommand* command = new EditCommand("ApplyMaterial", document);
89  document->Exec(command);
90 
91  // do the job:
92  if (mapping == MAP_CYLINDRICAL) {
93  ApplyMaterialCylindrical(material, polys, axis, scale_u, scale_v, flip, mirror, rotate);
94  return;
95  }
96 
97  if (mapping == MAP_SPHERICAL) {
98  ApplyMaterialSpherical(material, polys, axis, scale_u, scale_v, flip, mirror, rotate);
99  return;
100  }
101 
102  VertexSet* vset = polys.first()->vertex_set;
103 
104  Vec3* loc = vset->loc;
105  float min_u = 100000.0f, max_u = -100000.0f;
106  float min_v = 100000.0f, max_v = -100000.0f;
107 
108  ListIter<Poly> iter = polys;
109 
110  // compute range and scale:
111  if (mapping == MAP_PLANAR) {
112  while (++iter) {
113  Poly* poly = iter.value();
114  for (int i = 0; i < poly->nverts; i++) {
115  int v = poly->verts[i];
116 
117  float u0 = project_u(loc[v], axis);
118  float v0 = project_v(loc[v], axis);
119 
120  if (u0 < min_u) min_u = u0;
121  if (v0 < min_v) min_v = v0;
122  if (u0 > max_u) max_u = u0;
123  if (v0 > max_v) max_v = v0;
124  }
125  }
126  }
127 
128  float base_u = 0.0f;
129  float base_v = 0.0f;
130 
131  if (max_u != min_u) base_u = 1.0f / (max_u - min_u);
132  if (max_v != min_v) base_v = 1.0f / (max_v - min_v);
133 
134  iter.reset();
135 
136  // assign texture id and coordinates:
137  while (++iter) {
138  Poly* poly = iter.value();
139 
140  poly->material = material;
141 
142  if (mapping == MAP_NONE)
143  continue;
144 
145  for (int i = 0; i < poly->nverts; i++) {
146  int v = poly->verts[i];
147 
148  // planar projection
149  if (mapping == MAP_PLANAR) {
150  if (!rotate) {
151  if (mirror)
152  vset->tu[v] = (1.0f - base_u * (project_u(loc[v], axis) - min_u)) * scale_u;
153  else
154  vset->tu[v] = (project_u(loc[v], axis) - min_u) * scale_u * base_u;
155 
156  if (flip)
157  vset->tv[v] = (1.0f - base_v * (project_v(loc[v], axis) - min_v)) * scale_v;
158  else
159  vset->tv[v] = (project_v(loc[v], axis) - min_v) * scale_v * base_v;
160  }
161  else {
162  if (!mirror)
163  vset->tv[v] = (1.0f - base_u * (project_u(loc[v], axis) - min_u)) * scale_u;
164  else
165  vset->tv[v] = (project_u(loc[v], axis) - min_u) * scale_u * base_u;
166 
167  if (flip)
168  vset->tu[v] = (1.0f - base_v * (project_v(loc[v], axis) - min_v)) * scale_v;
169  else
170  vset->tu[v] = (project_v(loc[v], axis) - min_v) * scale_v * base_v;
171  }
172  }
173 
174  // stretch to fit
175  else if (mapping == MAP_STRETCH) {
176  if (scale_u < 0.001) scale_u = 1;
177  if (scale_v < 0.001) scale_v = 1;
178 
179  if (!rotate) {
180  if (mirror)
181  vset->tu[v] = scale_u * (float) (i < 1 || i > 2);
182  else
183  vset->tu[v] = scale_u * (float) (i > 0 && i < 3);
184 
185  if (flip)
186  vset->tv[v] = scale_v * (float) (i <= 1);
187  else
188  vset->tv[v] = scale_v * (float) (i > 1);
189  }
190  else {
191  if (!mirror)
192  vset->tv[v] = scale_v * (float) (i < 1 || i > 2);
193  else
194  vset->tv[v] = scale_v * (float) (i > 0 && i < 3);
195 
196  if (flip)
197  vset->tu[v] = scale_u * (float) (i <= 1);
198  else
199  vset->tu[v] = scale_u * (float) (i > 1);
200  }
201  }
202  }
203  }
204 
205  Resegment();
206 }
207 
208 void
210  int axis, float scale_u, float scale_v,
211  int flip, int mirror, int rotate)
212 {
213  VertexSet* vset = polys.first()->vertex_set;
214 
215  Vec3* loc = vset->loc;
216  float min_u = 100000.0f, max_u = -100000.0f;
217  float min_v = 100000.0f, max_v = -100000.0f;
218 
219  ListIter<Poly> iter = polys;
220 
221  // compute range and scale:
222  while (++iter) {
223  Poly* poly = iter.value();
224  for (int i = 0; i < poly->nverts; i++) {
225  int v = poly->verts[i];
226 
227  float u0 = project_u_cylindrical(loc[v], axis);
228  float v0 = project_v_cylindrical(loc[v], axis);
229 
230  if (u0 < min_u) min_u = u0;
231  if (v0 < min_v) min_v = v0;
232  if (u0 > max_u) max_u = u0;
233  if (v0 > max_v) max_v = v0;
234  }
235  }
236 
237  float base_u = 0.0f;
238  float base_v = 0.0f;
239 
240  if (max_u != min_u) base_u = 1.0f / (max_u - min_u);
241  if (max_v != min_v) base_v = 1.0f / (max_v - min_v);
242 
243  iter.reset();
244 
245  // assign texture id and coordinates:
246  while (++iter) {
247  Poly* poly = iter.value();
248 
249  poly->material = material;
250 
251  for (int i = 0; i < poly->nverts; i++) {
252  int v = poly->verts[i];
253  float u0 = project_u_cylindrical(loc[v], axis);
254  float v0 = project_v_cylindrical(loc[v], axis);
255 
256  if (!rotate) {
257  if (mirror)
258  vset->tu[v] = (1.0f - base_u * (u0 - min_u)) * scale_u;
259  else
260  vset->tu[v] = (u0 - min_u) * scale_u * base_u;
261 
262  if (flip)
263  vset->tv[v] = (1.0f - base_v * (v0 - min_v)) * scale_v;
264  else
265  vset->tv[v] = (v0 - min_v) * scale_v * base_v;
266  }
267  else {
268  if (!mirror)
269  vset->tv[v] = (1.0f - base_u * (u0 - min_u)) * scale_u;
270  else
271  vset->tv[v] = (u0 - min_u) * scale_u * base_u;
272 
273  if (flip)
274  vset->tu[v] = (1.0f - base_v * (v0 - min_v)) * scale_v;
275  else
276  vset->tu[v] = (v0 - min_v) * scale_v * base_v;
277  }
278  }
279  }
280 
281  Resegment();
282 }
283 
284 void
286  int axis, float scale_u, float scale_v,
287  int flip, int mirror, int rotate)
288 {
289 }
290 
291 // +----------------------------------------------------------------------+
292 
293 static int mcomp(const void* a, const void* b)
294 {
295  Poly* pa = (Poly*) a;
296  Poly* pb = (Poly*) b;
297 
298  if (pa->sortval == pb->sortval)
299  return 0;
300 
301  if (pa->sortval < pb->sortval)
302  return -1;
303 
304  return 1;
305 }
306 
307 void
309 {
310  if (model) {
312  while (++iter) {
313  Surface* surface = iter.value();
314  Poly* polys = surface->GetPolys();
315  int npolys = surface->NumPolys();
316 
317  for (int n = 0; n < npolys; n++) {
318  Poly* p = polys + n;
319  Material* m = p->material;
320  int sortval = model->GetMaterials().index(m) + 1;
321 
322  if (p->sortval != sortval)
323  p->sortval = sortval;
324  }
325 
326  // destroy the old segments and video data:
327  VideoPrivateData* video_data = surface->GetVideoPrivateData();
328  surface->SetVideoPrivateData(0);
329  surface->GetSegments().destroy();
330 
331  delete video_data;
332 
333  // sort the polys by material index:
334  qsort((void*) polys, npolys, sizeof(Poly), mcomp);
335 
336  // create new cohesive segments:
337  Segment* segment = 0;
338 
339  for (int n = 0; n < npolys; n++) {
340  if (segment && segment->material == polys[n].material) {
341  segment->npolys++;
342  }
343  else {
344  segment = 0;
345  }
346 
347  if (!segment) {
348  segment = new Segment;
349 
350  segment->npolys = 1;
351  segment->polys = polys + n;
352  segment->material = segment->polys->material;
353 
354  surface->GetSegments().append(segment);
355  }
356  }
357  }
358  }
359 }
360 
361 
362 // +----------------------------------------------------------------------+
363 // +----------------------------------------------------------------------+
364 // +----------------------------------------------------------------------+
365 
367  : Command(n, d), model1(0), model2(0)
368 {
369 }
370 
372 {
373  delete model1;
374  delete model2;
375 }
376 
377 // +----------------------------------------------------------------------+
378 
379 void
381 {
382  if (document) {
383  Solid* solid = document->GetSolid();
384 
385  // first application:
386  if (!model2) {
387  if (!model1)
388  model1 = new Model(*solid->GetModel());
389  }
390  // re-do:
391  else {
392  solid->GetModel()->operator=(*model2);
393  }
394  }
395 }
396 
397 // +----------------------------------------------------------------------+
398 
399 void
401 {
402  if (document && model1) {
403  Solid* solid = document->GetSolid();
404 
405  // save current state for later re-do:
406  if (!model2)
407  model2 = new Model(*solid->GetModel());
408 
409  solid->GetModel()->operator=(*model1);
410  }
411 }
412