source: cpp/frams/vm/classes/3dobject.cpp @ 247

Last change on this file since 247 was 247, checked in by Maciej Komosinski, 9 years ago

Sources support both 32-bit and 64-bit, and more compilers

  • Property svn:eol-style set to native
File size: 13.8 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include <frams/util/3d.h>
6#include "3dobject.h"
7#include <frams/param/param.h>
8#include "collectionobj.h"
9
10ParamEntry* Pt3D_Ext::getStaticParamtab()
11{
12#define FIELDSTRUCT Pt3D_Ext
13static ParamEntry paramtab[]=
14{
15{"XYZ",1,18,"XYZ","3D vector"},
16
17{"x",0,PARAM_NOSTATIC,"x","f",FIELD(p.x),},
18{"y",0,PARAM_NOSTATIC,"y","f",FIELD(p.y),},
19{"z",0,PARAM_NOSTATIC,"z","f",FIELD(p.z),},
20{"new",0,0,"create new XYZ object","p oXYZ(f x,f y,f z)",PROCEDURE(p_new),"3D vectors objects can be also created using the (x,y,z) notation, i.e. var v=(1,2,3) is the same as var v=XYZ.new(1,2,3);",},
21{"newFromVector",0,0,"create new XYZ object","p oXYZ(oVector)",PROCEDURE(p_newFromVector),"used for deserialization"},
22{"clone",0,PARAM_NOSTATIC,"create new XYZ object copying the coordinates","p oXYZ()",PROCEDURE(p_clone),"Note: copying object references does not create new objects. Use clone() if a new object is needed.\n\nExample:\nvar o1=(1,2,3), o2=o1, o3=o1.clone();\no1.y=9999;\n//o2 is now (1,9999,3) but o3 is still (1,2,3)",},
23{"set",0,PARAM_NOSTATIC,"set (copy) coordinates from another XYZ object","p(oXYZ)",PROCEDURE(p_set),},
24{"set3",0,PARAM_NOSTATIC,"set individual 3 coordinates","p(f x,f y,f z)",PROCEDURE(p_set3),},
25{"add",0,PARAM_NOSTATIC,"add","p(oXYZ)",PROCEDURE(p_addvec),"Note: it does not return a new object, just modifies the existing one"},
26{"sub",0,PARAM_NOSTATIC,"subtract","p(oXYZ)",PROCEDURE(p_subvec),"Note: it does not return a new object, just modifies the existing one"},
27{"scale",0,PARAM_NOSTATIC,"multiply by scalar","p(f)",PROCEDURE(p_scale),},
28{"length",0,PARAM_READONLY | PARAM_NOSTATIC,"length","f",GETONLY(length),},
29{"normalize",0,PARAM_NOSTATIC,"normalize","p()",PROCEDURE(p_normalize),"scales the vector length to 1.0"},
30{"toString",0,PARAM_READONLY | PARAM_NOSTATIC,"textual form","s",GETONLY(toString),},
31{"toVector",0,PARAM_READONLY | PARAM_NOSTATIC,"vector of [x,y,z]","oVector",GETONLY(toVector),},
32{"rotate",0,PARAM_NOSTATIC,"rotate using Orient object","p(oOrient)",PROCEDURE(p_rotate),},
33{"revRotate",0,PARAM_NOSTATIC,"reverse rotate using Orient object","p(oOrient)",PROCEDURE(p_revrotate),},
34{"get",0,PARAM_NOSTATIC,"get one of coordinates","p f(d index)",PROCEDURE(p_get),"this function makes the XYZ objects \"indexable\" (so you can use [] for accessing subsequent fields, like in Vector)",},
35{0,0,0,},
36};
37#undef FIELDSTRUCT
38return paramtab;
39}
40
41void Pt3D_Ext::p_new(ExtValue *args,ExtValue *ret)
42{
43*ret=makeDynamicObject(new Pt3D_Ext(args[2].getDouble(),args[1].getDouble(),args[0].getDouble()));
44}
45
46static double doubleFromVec(VectorObject *vec,int i)
47{
48if (i>=vec->data.size()) return 0;
49ExtValue *v=(ExtValue*)vec->data.get(i);
50if (v)
51        return v->getDouble();
52return 0;
53}
54
55static Pt3D pt3DFromVec(VectorObject* v,int offset=0)
56{
57return Pt3D(doubleFromVec(v,offset),doubleFromVec(v,offset+1),doubleFromVec(v,offset+2));
58}
59
60void Pt3D_Ext::p_newFromVector(ExtValue *args,ExtValue *ret)
61{
62VectorObject *vec=VectorObject::fromObject(args->getObject());
63if (vec)
64        *ret=makeDynamicObject(new Pt3D_Ext(pt3DFromVec(vec)));
65else
66        ret->setEmpty();
67}
68
69void Pt3D_Ext::p_clone(ExtValue *args,ExtValue *ret)
70{
71*ret=makeDynamicObject(new Pt3D_Ext(p.x,p.y,p.z));
72}
73
74void Pt3D_Ext::p_set3(ExtValue *args,ExtValue *ret)
75{
76p.x=args[2].getDouble();
77p.y=args[1].getDouble();
78p.z=args[0].getDouble();
79ret->setEmpty();
80}
81
82void Pt3D_Ext::p_set(ExtValue *args,ExtValue *ret)
83{
84Pt3D_Ext *other=fromObject(args[0]);
85if (other)
86        p=other->p;
87ret->setEmpty();
88}
89
90void Pt3D_Ext::get_length(ExtValue *ret)
91{
92ret->setDouble(p.length());
93}
94
95void Pt3D_Ext::get_toString(ExtValue *ret)
96{
97SString s="(";
98ExtValue v;
99v.setDouble(p.x); s+=v.getString();
100s+=",";
101v.setDouble(p.y); s+=v.getString();
102s+=",";
103v.setDouble(p.z); s+=v.getString();
104s+=")";
105ret->setString(s);
106}
107
108static void add3Coords(VectorObject* vec,const Pt3D& p)
109{
110vec->data+=new ExtValue(p.x);
111vec->data+=new ExtValue(p.y);
112vec->data+=new ExtValue(p.z);
113}
114
115void Pt3D_Ext::get_toVector(ExtValue *ret)
116{
117VectorObject *vec=new VectorObject;
118add3Coords(vec,p);
119ret->setObject(ExtObject(&VectorObject::par,vec));
120}
121
122void Pt3D_Ext::p_addvec(ExtValue *args,ExtValue *ret)
123{
124Pt3D_Ext *other=fromObject(args[0]);
125if (other)
126        p+=other->p;
127ret->setEmpty();
128}
129
130void Pt3D_Ext::p_subvec(ExtValue *args,ExtValue *ret)
131{
132Pt3D_Ext *other=fromObject(args[0]);
133if (other)
134        p-=other->p;
135ret->setEmpty();
136}
137
138void Pt3D_Ext::p_scale(ExtValue *args,ExtValue *ret)
139{
140double d=args[0].getDouble();
141p.x*=d; p.y*=d; p.z*=d;
142ret->setEmpty();
143}
144
145void Pt3D_Ext::p_normalize(ExtValue *args,ExtValue *ret)
146{
147p.normalize();
148ret->setEmpty();
149}
150
151void Pt3D_Ext::p_rotate(ExtValue *args,ExtValue *ret)
152{
153Orient_Ext *o=Orient_Ext::fromObject(args[0]);
154if (o)
155        {
156        Pt3D tmp=p;
157        o->o.transform(p,tmp);
158        }
159ret->setEmpty();
160}
161
162void Pt3D_Ext::p_revrotate(ExtValue *args,ExtValue *ret)
163{
164Orient_Ext *o=Orient_Ext::fromObject(args[0]);
165if (o)
166        {
167        Pt3D tmp=p;
168        o->o.revTransform(p,tmp);
169        }
170ret->setEmpty();
171}
172
173void Pt3D_Ext::p_get(ExtValue *args,ExtValue *ret)
174{
175int index=args->getInt();
176if ((index<0)||(index>2))
177        ret->setEmpty();
178else
179        ret->setDouble((&p.x)[index]);
180}
181
182Param& Pt3D_Ext::getStaticParam()
183{
184#ifdef __CODEGUARD__
185static Pt3D_Ext static_pt3dobj;
186static Param static_pt3dparam(getStaticParamtab(),&static_pt3dobj);
187#else
188static Param static_pt3dparam(getStaticParamtab());
189#endif
190return static_pt3dparam;
191}
192
193Pt3D_Ext* Pt3D_Ext::fromObject(const ExtValue& v,bool warn)
194{
195return (Pt3D_Ext*)v.getObjectTarget(getStaticParam().getName(), warn);
196}
197
198ParamInterface* Pt3D_Ext::getInterface() {return &getStaticParam();}
199
200ExtObject Pt3D_Ext::makeStaticObject(Pt3D* p)
201{return ExtObject(&getStaticParam(),((char*)p)+(((char*)&p->x)-((char*)&((Pt3D_Ext*)p)->p.x)));}
202
203ExtObject Pt3D_Ext::makeDynamicObject(Pt3D_Ext* p)
204{return ExtObject(&getStaticParam(),p);}
205
206ExtObject Pt3D_Ext::makeDynamicObject(const Pt3D& p)
207{
208Pt3D_Ext *pe=new Pt3D_Ext(p);
209return ExtObject(&getStaticParam(),pe);
210}
211
212//////////////////////////////////////
213
214ParamEntry* Orient_Ext::getStaticParamtab()
215{
216#define FIELDSTRUCT Orient_Ext
217static ParamEntry paramtab[]=
218{
219{"Orient",1,29,"Orient","3D orientation, stored as 3x3 matrix."},
220
221{"xx",1,PARAM_NOSTATIC,"orientation.x.x","f",FIELD(o.x.x),},
222{"xy",1,PARAM_NOSTATIC,"orientation.x.y","f",FIELD(o.x.y),},
223{"xz",1,PARAM_NOSTATIC,"orientation.x.z","f",FIELD(o.x.z),},
224{"yx",1,PARAM_NOSTATIC,"orientation.y.x","f",FIELD(o.y.x),},
225{"yy",1,PARAM_NOSTATIC,"orientation.y.y","f",FIELD(o.y.y),},
226{"yz",1,PARAM_NOSTATIC,"orientation.y.z","f",FIELD(o.y.z),},
227{"zx",1,PARAM_NOSTATIC,"orientation.z.x","f",FIELD(o.z.x),},
228{"zy",1,PARAM_NOSTATIC,"orientation.z.y","f",FIELD(o.z.y),},
229{"zz",1,PARAM_NOSTATIC,"orientation.z.z","f",FIELD(o.z.z),},
230
231{"x",0,PARAM_NOSTATIC | PARAM_READONLY,"x vector","oXYZ",GETONLY(x),},
232{"y",0,PARAM_NOSTATIC | PARAM_READONLY,"y vector","oXYZ",GETONLY(y),},
233{"z",0,PARAM_NOSTATIC | PARAM_READONLY,"z vector","oXYZ",GETONLY(z),},
234
235{"new",0,0,"create new Orient object","p oOrient()",PROCEDURE(p_new),},
236{"newFromVector",0,0,"create new Orient object","p oOrient(oVector)",PROCEDURE(p_newFromVector),},
237{"toVector",0,PARAM_READONLY | PARAM_NOSTATIC,"vector representation","oVector",GETONLY(toVector),"for serialization"},
238{"clone",0,PARAM_NOSTATIC,"create new Orient object","p oOrient()",PROCEDURE(p_clone),},
239{"set",0,PARAM_NOSTATIC,"copy from another Orient object","p(oOrient)",PROCEDURE(p_set),},
240{"reset",0,PARAM_NOSTATIC,"set identity matrix","p()",PROCEDURE(p_reset),},
241{"rotate3",0,PARAM_NOSTATIC,"rotate around 3 axes","p(f x,f y,f z)",PROCEDURE(p_rotate3),},
242{"rotate",0,PARAM_NOSTATIC,"rotate using Orient object","p(oOrient)",PROCEDURE(p_rotate),},
243{"revRotate",0,PARAM_NOSTATIC,"reverse rotate using Orient object","p(oOrient)",PROCEDURE(p_revrotate),},
244{"lookAt",0,PARAM_NOSTATIC,"calculate rotation from 2 vectors","p(oXYZ direction,oXYZ up)",PROCEDURE(p_lookat),},
245{"normalize",0,PARAM_NOSTATIC,"normalize","p()",PROCEDURE(p_normalize),},
246{"between2",0,PARAM_NOSTATIC,"interpolate orientation","p(oOrient,oOrient,f amount)",PROCEDURE(p_between2),"The calling Orient receives the orientation interpolated from 2 input orientations.\nExample:\n"
247        "var o1=Orient.new(), o2=Orient.new(), o3=Orient.new();\n"
248        "o2.rotate3(0,Math.pi/2,0);\n"
249        "o3.between2(o1,o2,0); // o3 equals o2\n"
250        "o3.between2(o1,o2,1); // o3 equals o1\n"
251        "o3.between2(o1,o2,0.5); // o3 is halfway between o1 and o2\n"},
252{"betweenOV",0,PARAM_NOSTATIC,"interpolate orientation","p(oOrient,oXYZ,f amount)",PROCEDURE(p_betweenOV),"Like between2(), but the second Orient is composed of the supplied XYZ vector (X component) and Y Z vectors from the calling object.\n"
253        "Example:\n"
254        "var o=Orient.new();\n"
255        "o.betweenOV(o,(0,1,0),1); //no change, o remains 100 010 001\n"
256        "o.betweenOV(o,(0,1,0),0.9); //o is slightly rotated towards (0,1,0)\n"
257        "o.betweenOV(o,(0,1,0),0); //o is completely transformed, o.x=(0,1,0)\n"
258        },
259{"localToWorld",0,PARAM_NOSTATIC,"transform coordinates","p oXYZ(oXYZ point,oXYZ center)",PROCEDURE(p_localToWorld),},
260{"worldToLocal",0,PARAM_NOSTATIC,"transform coordinates","p oXYZ(oXYZ point,oXYZ center)",PROCEDURE(p_worldToLocal),},
261{"angles",0,PARAM_READONLY | PARAM_NOSTATIC,"Euler angles representation","oXYZ",GETONLY(angles),},
262{"toString",0,PARAM_READONLY | PARAM_NOSTATIC,"textual form","s",GETONLY(toString),},
263{0,0,0,},
264};
265#undef FIELDSTRUCT
266return paramtab;
267}
268
269void Orient_Ext::p_new(ExtValue *args,ExtValue *ret)
270{
271*ret=makeDynamicObject(new Orient_Ext());
272}
273
274void Orient_Ext::p_newFromVector(ExtValue *args,ExtValue *ret)
275{
276VectorObject *vec=VectorObject::fromObject(args->getObject());
277if (vec)
278        *ret=makeDynamicObject(new Orient_Ext(Orient(pt3DFromVec(vec,0),pt3DFromVec(vec,3),pt3DFromVec(vec,6))));
279else
280        ret->setEmpty();
281}
282
283void Orient_Ext::get_toVector(ExtValue *ret)
284{
285VectorObject *vec=new VectorObject;
286add3Coords(vec,o.x);
287add3Coords(vec,o.y);
288add3Coords(vec,o.z);
289ret->setObject(ExtObject(&VectorObject::par,vec));
290}
291
292void Orient_Ext::p_clone(ExtValue *args,ExtValue *ret)
293{
294*ret=makeDynamicObject(new Orient_Ext(o));
295}
296
297void Orient_Ext::p_set(ExtValue *args,ExtValue *ret)
298{
299Orient_Ext *other=fromObject(args[0]);
300if (other)
301        o=other->o;
302ret->setEmpty();
303}
304
305void Orient_Ext::p_reset(ExtValue *args,ExtValue *ret)
306{
307o=Orient_1;
308ret->setEmpty();
309}
310
311void Orient_Ext::get_x(PARAMGETARGS)
312{
313*ret=Pt3D_Ext::makeStaticObject(&o.x);
314}
315
316void Orient_Ext::get_y(PARAMGETARGS)
317{
318*ret=Pt3D_Ext::makeStaticObject(&o.y);
319}
320
321void Orient_Ext::get_z(PARAMGETARGS)
322{
323*ret=Pt3D_Ext::makeStaticObject(&o.z);
324}
325
326void Orient_Ext::p_lookat(ExtValue *args,ExtValue *ret)
327{
328Pt3D_Ext *dir=Pt3D_Ext::fromObject(args[1]),*up=Pt3D_Ext::fromObject(args[0]);
329if (dir&&up)
330        o.lookAt(dir->p,up->p);
331ret->setEmpty();
332}
333
334void Orient_Ext::p_rotate3(ExtValue *args,ExtValue *ret)
335{
336Pt3D p(args[2].getDouble(),args[1].getDouble(),args[0].getDouble());
337o.rotate(p);
338ret->setEmpty();
339}
340
341void Orient_Ext::p_rotate(ExtValue *args,ExtValue *ret)
342{
343Orient_Ext *obj=Orient_Ext::fromObject(args[0]);
344if (!obj)
345        {
346        Orient tmp=o;
347        obj->o.transform(o,tmp);
348        }
349ret->setEmpty();
350}
351
352void Orient_Ext::p_revrotate(ExtValue *args,ExtValue *ret)
353{
354Orient_Ext *obj=Orient_Ext::fromObject(args[0]);
355if (obj)
356        {
357        Orient tmp=o;
358        obj->o.revTransform(o,tmp);
359        }
360ret->setEmpty();
361}
362
363void Orient_Ext::p_normalize(ExtValue *args,ExtValue *ret)
364{
365o.normalize();
366ret->setEmpty();
367}
368
369void Orient_Ext::p_between2(ExtValue *args,ExtValue *ret)
370{
371Orient_Ext *o1=Orient_Ext::fromObject(args[2]);
372Orient_Ext *o2=Orient_Ext::fromObject(args[1]);
373if (o1&&o2)
374        {
375        double q1=args[0].getDouble(),q2=1.0-q1;
376        o.x.x=q1*o1->o.x.x+q2*o2->o.x.x;
377        o.x.y=q1*o1->o.x.y+q2*o2->o.x.y;
378        o.x.z=q1*o1->o.x.z+q2*o2->o.x.z;
379        o.y.x=q1*o1->o.y.x+q2*o2->o.y.x;
380        o.y.y=q1*o1->o.y.y+q2*o2->o.y.y;
381        o.y.z=q1*o1->o.y.z+q2*o2->o.y.z;
382        o.z.x=q1*o1->o.z.x+q2*o2->o.z.x;
383        o.z.y=q1*o1->o.z.y+q2*o2->o.z.y;
384        o.z.z=q1*o1->o.z.z+q2*o2->o.z.z;
385        o.normalize();
386        }
387ret->setEmpty();
388}
389
390void Orient_Ext::p_betweenOV(ExtValue *args,ExtValue *ret)
391{
392Orient_Ext *o1=Orient_Ext::fromObject(args[2]);
393Pt3D_Ext *p2=Pt3D_Ext::fromObject(args[1]);
394if (o1&&p2)
395        {
396        double q1=args[0].getDouble(),q2=1.0-q1;
397        o.x.x=q1*o1->o.x.x+q2*p2->p.x;
398        o.x.y=q1*o1->o.x.y+q2*p2->p.y;
399        o.x.z=q1*o1->o.x.z+q2*p2->p.z;
400        o.normalize();
401        }
402ret->setEmpty();
403}
404
405void Orient_Ext::p_localToWorld(ExtValue *args,ExtValue *ret)
406{
407Pt3D_Ext *center,*point;
408point=Pt3D_Ext::fromObject(args[1]);
409center=Pt3D_Ext::fromObject(args[0]);
410if (center && point)
411        {
412        Pt3D d;
413        Pt3D src=point->p;
414        o.transform(d,src);
415        d+=center->p;
416        *ret=Pt3D_Ext::makeDynamicObject(new Pt3D_Ext(d));
417        }
418else
419        ret->setEmpty();
420}
421
422void Orient_Ext::p_worldToLocal(ExtValue *args,ExtValue *ret)
423{
424Pt3D_Ext *center,*point;
425point=Pt3D_Ext::fromObject(args[1]);
426center=Pt3D_Ext::fromObject(args[0]);
427if (center && point)
428        {
429        Pt3D d;
430        Pt3D src=point->p;
431        d-=center->p;
432        o.revTransform(d,src);
433        *ret=Pt3D_Ext::makeDynamicObject(new Pt3D_Ext(d));
434        }
435else
436        ret->setEmpty();
437}
438
439void Orient_Ext::get_angles(ExtValue *ret)
440{
441*ret=Pt3D_Ext::makeDynamicObject(new Pt3D_Ext(o.getAngles()));
442}
443
444void Orient_Ext::get_toString(ExtValue *ret)
445{
446Pt3D a=o.getAngles();
447ret->setString(SString::sprintf("Orient@(%g,%g,%g)",a.x,a.y,a.z));
448}
449
450Param& Orient_Ext::getStaticParam()
451{
452#ifdef __CODEGUARD__
453static Orient_Ext static_orientobj;
454static Param static_orientparam(getStaticParamtab(),&static_orientobj);
455#else
456static Param static_orientparam(getStaticParamtab());
457#endif
458return static_orientparam;
459}
460
461Orient_Ext* Orient_Ext::fromObject(const ExtValue& v)
462{
463return (Orient_Ext*)v.getObjectTarget(getStaticParam().getName());
464}
465
466ParamInterface* Orient_Ext::getInterface() {return &getStaticParam();}
467
468ExtObject Orient_Ext::makeStaticObject(Orient* o)
469{return ExtObject(&getStaticParam(),((char*)o)+(((char*)&o->x)-((char*)&((Orient_Ext*)o)->o.x)));}
470
471ExtObject Orient_Ext::makeDynamicObject(Orient_Ext* p)
472{return ExtObject(&getStaticParam(),p);}
473
474/////////////
475
476REGISTER_DESERIALIZABLE(Pt3D_Ext)
477REGISTER_DESERIALIZABLE(Orient_Ext)
Note: See TracBrowser for help on using the repository browser.