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

Last change on this file since 605 was 343, checked in by Maciej Komosinski, 10 years ago

Code formatting

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