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

Last change on this file since 997 was 661, checked in by Maciej Komosinski, 8 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
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[548]2// Copyright (C) 1999-2016  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[271]4
[235]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
[242]11static ParamEntry modelgeo_paramtab[] =
[235]12{
[242]13        { "Creature: Geometry", 1, 5, "ModelGeometry",
[548]14        "Approximately estimates sizes, volume, and area of a Model based on the geometry of its parts.\n"
[242]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"
[548]19        "var mg=ModelGeometry.forModel(GenePools[0][0].getModel()); mg.geom_density=2; GenePools[0][0].data->area=mg.area();\n" },
[242]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, },
[235]26};
27#undef FIELDSTRUCT
28
29ExtObject ModelGeometry::makeDynamicObject(ModelGeometry* mg)
[242]30{
31        return ExtObject(&mg->par, mg);
32}
[235]33
34ModelGeometry::ModelGeometry(ModelObj *mo)
[242]35:par(modelgeo_paramtab, this)
[235]36{
[242]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();
[235]42}
43
44ModelGeometry::~ModelGeometry()
45{
[242]46        if (model != NULL)
47                model->decref();
[235]48}
49
[242]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()
[235]54{
[242]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)
[235]65        {
[242]66                invalidateAllCached();
67                cached_for_density = density;
[235]68        }
69}
70
[242]71void ModelGeometry::p_formodel(ExtValue *args, ExtValue *ret)
[235]72{
[242]73        Model *m = ModelObj::fromObject(*args);
74        if (m != NULL)
75        {
[661]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                        }
[242]84                ModelGeometry *mg = new ModelGeometry((ModelObj*)m);
85                mg->density = density;
86                ret->setObject(ModelGeometry::makeDynamicObject(mg));
87        }
88        else
89                ret->setEmpty();
[235]90}
91
[242]92void ModelGeometry::p_volume(ExtValue *args, ExtValue *ret)
[235]93{
[242]94        onDensityChanged();
95        if (cached_volume < 0) //calculate if invalid
96                cached_volume = ModelGeometryInfo::volume(*model, density);
97        ret->setDouble(cached_volume);
[235]98}
99
[242]100void ModelGeometry::p_area(ExtValue *args, ExtValue *ret)
[235]101{
[242]102        onDensityChanged();
103        if (cached_area < 0) //calculate if invalid
104                cached_area = ModelGeometryInfo::area(*model, density);
105        ret->setDouble(cached_area);
[235]106}
[242]107
108void ModelGeometry::p_sizesandaxes(ExtValue *args, ExtValue *ret)
109{
110        onDensityChanged();
111        if (cached_sizes.x < 0) //calculate if invalid
[658]112                ModelGeometryInfo::findSizesAndAxes(*model, density, cached_sizes, cached_axes);
[242]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.