1 | #include "modelgeoclass.h" |
---|
2 | #include "modelgeometryinfo.h" |
---|
3 | #include <frams/vm/classes/collectionobj.h> |
---|
4 | #include <frams/vm/classes/3dobject.h> |
---|
5 | |
---|
6 | #define FIELDSTRUCT ModelGeometry |
---|
7 | static ParamEntry modelgeo_paramtab[] = |
---|
8 | { |
---|
9 | { "Creature: Geometry", 1, 5, "ModelGeometry", |
---|
10 | "Example usage:\n" |
---|
11 | "Simulator.print(ModelGeometry.forModel(Model.newFromString(\"//0\\np:sh=1\\n\")).area());\n\n" |
---|
12 | "ModelGeometry.geom_density refers to the global simulator parameter (also available in GUI).\n" |
---|
13 | "To set geom_density for individual ModelGeometry objects:\n" |
---|
14 | "var mg=ModelGeometry.forModel(GenePools[0][0].getModel()); mg.geom_density=2; GenePools[0][0].user1=mg.area();\n" }, |
---|
15 | { "geom_density", 0, 0, "Density", "f 0.01 100.0 1.0", FIELD(density), "Affects the geometry calculation precision" }, //note: we used 'geom_density' instead of 'density' to make the name more unique - because sim_params merges all configuration fields in a single namespace. |
---|
16 | { "forModel", 0, PARAM_USERHIDDEN, "", "p oModelGeometry(oModel)", PROCEDURE(p_formodel), "The returned ModelGeometry object can be used to calculate geometric properties (volume, area, sizes) of the associated model. The density is copied from the current global ModelGeometry.geom_density on object creation." }, |
---|
17 | { "volume", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "volume", "p f()", PROCEDURE(p_volume), }, |
---|
18 | { "area", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "area", "p f()", PROCEDURE(p_area), }, |
---|
19 | { "sizesAndAxes", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "sizesAndAxes", "p oVector()", PROCEDURE(p_sizesandaxes), "The returned vector contains XYZ (sizes) and Orient (axes) objects." }, |
---|
20 | { 0, 0, 0, }, |
---|
21 | }; |
---|
22 | #undef FIELDSTRUCT |
---|
23 | |
---|
24 | ExtObject ModelGeometry::makeDynamicObject(ModelGeometry* mg) |
---|
25 | { |
---|
26 | return ExtObject(&mg->par, mg); |
---|
27 | } |
---|
28 | |
---|
29 | ModelGeometry::ModelGeometry(ModelObj *mo) |
---|
30 | :par(modelgeo_paramtab, this) |
---|
31 | { |
---|
32 | cached_for_density = -1; //invalid value, will be updated on first request |
---|
33 | invalidateAllCached(); |
---|
34 | model = mo; |
---|
35 | if (model != NULL) |
---|
36 | model->incref(); |
---|
37 | } |
---|
38 | |
---|
39 | ModelGeometry::~ModelGeometry() |
---|
40 | { |
---|
41 | if (model != NULL) |
---|
42 | model->decref(); |
---|
43 | } |
---|
44 | |
---|
45 | // Mark all 3 results as invalid. |
---|
46 | // Validity of these 3 values must be maintained independently, |
---|
47 | // as each of them is calculated by an individual call. |
---|
48 | void ModelGeometry::invalidateAllCached() |
---|
49 | { |
---|
50 | cached_volume = -1; |
---|
51 | cached_area = -1; |
---|
52 | cached_sizes.x = -1; |
---|
53 | } |
---|
54 | |
---|
55 | // Invalidates cached results if a new density is requested |
---|
56 | // (called in all geometry calculation functions) |
---|
57 | void ModelGeometry::onDensityChanged() |
---|
58 | { |
---|
59 | if (cached_for_density != density) |
---|
60 | { |
---|
61 | invalidateAllCached(); |
---|
62 | cached_for_density = density; |
---|
63 | } |
---|
64 | } |
---|
65 | |
---|
66 | void ModelGeometry::p_formodel(ExtValue *args, ExtValue *ret) |
---|
67 | { |
---|
68 | Model *m = ModelObj::fromObject(*args); |
---|
69 | if (m != NULL) |
---|
70 | { |
---|
71 | ModelGeometry *mg = new ModelGeometry((ModelObj*)m); |
---|
72 | mg->density = density; |
---|
73 | ret->setObject(ModelGeometry::makeDynamicObject(mg)); |
---|
74 | } |
---|
75 | else |
---|
76 | ret->setEmpty(); |
---|
77 | } |
---|
78 | |
---|
79 | void ModelGeometry::p_volume(ExtValue *args, ExtValue *ret) |
---|
80 | { |
---|
81 | onDensityChanged(); |
---|
82 | if (cached_volume < 0) //calculate if invalid |
---|
83 | cached_volume = ModelGeometryInfo::volume(*model, density); |
---|
84 | ret->setDouble(cached_volume); |
---|
85 | } |
---|
86 | |
---|
87 | void ModelGeometry::p_area(ExtValue *args, ExtValue *ret) |
---|
88 | { |
---|
89 | onDensityChanged(); |
---|
90 | if (cached_area < 0) //calculate if invalid |
---|
91 | cached_area = ModelGeometryInfo::area(*model, density); |
---|
92 | ret->setDouble(cached_area); |
---|
93 | } |
---|
94 | |
---|
95 | void ModelGeometry::p_sizesandaxes(ExtValue *args, ExtValue *ret) |
---|
96 | { |
---|
97 | onDensityChanged(); |
---|
98 | if (cached_sizes.x < 0) //calculate if invalid |
---|
99 | ModelGeometryInfo::findSizesAndAxesOfModel(*model, density, cached_sizes, cached_axes); |
---|
100 | |
---|
101 | VectorObject* n = new VectorObject; |
---|
102 | n->data += new ExtValue(Pt3D_Ext::makeDynamicObject(cached_sizes)); |
---|
103 | n->data += new ExtValue(Orient_Ext::makeDynamicObject(new Orient_Ext(cached_axes))); |
---|
104 | ret->setObject(n->makeObject()); |
---|
105 | } |
---|