source: cpp/frams/model/geometry/modelgeoclass.cpp @ 661

Last change on this file since 661 was 661, checked in by Maciej Komosinski, 5 years ago

FramScript?'s ModelGeometr? converts and caches the input model so geometry calculation functions do not have to convert the model on each call

  • Property svn:eol-style set to native
File size: 4.2 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2016  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "modelgeoclass.h"
6#include "modelgeometryinfo.h"
7#include <frams/vm/classes/collectionobj.h>
8#include <frams/vm/classes/3dobject.h>
9
10#define FIELDSTRUCT ModelGeometry
11static ParamEntry modelgeo_paramtab[] =
12{
13        { "Creature: Geometry", 1, 5, "ModelGeometry",
14        "Approximately estimates sizes, volume, and area of a Model based on the geometry of its parts.\n"
15        "Example usage:\n"
16        "Simulator.print(ModelGeometry.forModel(Model.newFromString(\"//0\\np:sh=1\\n\")).area());\n\n"
17        "ModelGeometry.geom_density refers to the global simulator parameter (also available in GUI).\n"
18        "To set geom_density for individual ModelGeometry objects:\n"
19        "var mg=ModelGeometry.forModel(GenePools[0][0].getModel()); mg.geom_density=2; GenePools[0][0].data->area=mg.area();\n" },
20        { "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.
21        { "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." },
22        { "volume", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "volume", "p f()", PROCEDURE(p_volume), },
23        { "area", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "area", "p f()", PROCEDURE(p_area), },
24        { "sizesAndAxes", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "sizesAndAxes", "p oVector()", PROCEDURE(p_sizesandaxes), "The returned vector contains XYZ (sizes) and Orient (axes) objects." },
25        { 0, 0, 0, },
26};
27#undef FIELDSTRUCT
28
29ExtObject ModelGeometry::makeDynamicObject(ModelGeometry* mg)
30{
31        return ExtObject(&mg->par, mg);
32}
33
34ModelGeometry::ModelGeometry(ModelObj *mo)
35:par(modelgeo_paramtab, this)
36{
37        cached_for_density = -1; //invalid value, will be updated on first request
38        invalidateAllCached();
39        model = mo;
40        if (model != NULL)
41                model->incref();
42}
43
44ModelGeometry::~ModelGeometry()
45{
46        if (model != NULL)
47                model->decref();
48}
49
50// Mark all 3 results as invalid.
51// Validity of these 3 values must be maintained independently,
52// as each of them is calculated by an individual call.
53void ModelGeometry::invalidateAllCached()
54{
55        cached_volume = -1;
56        cached_area = -1;
57        cached_sizes.x = -1;
58}
59
60// Invalidates cached results if a new density is requested
61// (called in all geometry calculation functions)
62void ModelGeometry::onDensityChanged()
63{
64        if (cached_for_density != density)
65        {
66                invalidateAllCached();
67                cached_for_density = density;
68        }
69}
70
71void ModelGeometry::p_formodel(ExtValue *args, ExtValue *ret)
72{
73        Model *m = ModelObj::fromObject(*args);
74        if (m != NULL)
75        {
76                if (m->getShapeType() == Model::SHAPE_BALL_AND_STICK)
77                        {
78                        Model *converted = new Model;
79                        converted->open();
80                        converted->buildUsingSolidShapeTypes(*m, Part::SHAPE_CYLINDER, 0.2);
81                        converted->close();
82                        m=converted;
83                        }
84                ModelGeometry *mg = new ModelGeometry((ModelObj*)m);
85                mg->density = density;
86                ret->setObject(ModelGeometry::makeDynamicObject(mg));
87        }
88        else
89                ret->setEmpty();
90}
91
92void ModelGeometry::p_volume(ExtValue *args, ExtValue *ret)
93{
94        onDensityChanged();
95        if (cached_volume < 0) //calculate if invalid
96                cached_volume = ModelGeometryInfo::volume(*model, density);
97        ret->setDouble(cached_volume);
98}
99
100void ModelGeometry::p_area(ExtValue *args, ExtValue *ret)
101{
102        onDensityChanged();
103        if (cached_area < 0) //calculate if invalid
104                cached_area = ModelGeometryInfo::area(*model, density);
105        ret->setDouble(cached_area);
106}
107
108void ModelGeometry::p_sizesandaxes(ExtValue *args, ExtValue *ret)
109{
110        onDensityChanged();
111        if (cached_sizes.x < 0) //calculate if invalid
112                ModelGeometryInfo::findSizesAndAxes(*model, density, cached_sizes, cached_axes);
113
114        VectorObject* n = new VectorObject;
115        n->data += new ExtValue(Pt3D_Ext::makeDynamicObject(cached_sizes));
116        n->data += new ExtValue(Orient_Ext::makeDynamicObject(new Orient_Ext(cached_axes)));
117        ret->setObject(n->makeObject());
118}
Note: See TracBrowser for help on using the repository browser.