1 /* === S I N F G =========================================================== */
2 /*! \file metaballs.cpp
3 ** \brief Implements metaballs
5 ** $Id: metaballs.cpp,v 1.1.1.1 2005/01/04 01:23:09 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
31 #include <sinfg/string.h>
32 #include <sinfg/time.h>
33 #include <sinfg/context.h>
34 #include <sinfg/paramdesc.h>
35 #include <sinfg/renddesc.h>
36 #include <sinfg/surface.h>
37 #include <sinfg/value.h>
38 #include <sinfg/valuenode.h>
41 #include "metaballs.h"
45 /* === U S I N G =========================================================== */
49 using namespace sinfg;
51 /* === G L O B A L S ======================================================= */
53 SINFG_LAYER_INIT(Metaballs);
54 SINFG_LAYER_SET_NAME(Metaballs,"metaballs");
55 SINFG_LAYER_SET_LOCAL_NAME(Metaballs,_("Metaballs"));
56 SINFG_LAYER_SET_CATEGORY(Metaballs,_("Default"));
57 SINFG_LAYER_SET_VERSION(Metaballs,"0.1");
58 SINFG_LAYER_SET_CVS_ID(Metaballs,"$Id: metaballs.cpp,v 1.1.1.1 2005/01/04 01:23:09 darco Exp $");
60 /* === P R O C E D U R E S ================================================= */
62 /* === M E T H O D S ======================================================= */
64 /* === E N T R Y P O I N T ================================================= */
66 Metaballs::Metaballs():
67 Layer_Composite(1.0,Color::BLEND_STRAIGHT),
73 Metaballs::set_param(const String & param, const ValueBase &value)
75 if( param=="centers" && value.same_as(centers))
81 if( param=="weights" && value.same_as(weights))
87 if( param=="radii" && value.same_as(radii))
96 return Layer_Composite::set_param(param,value);
100 Metaballs::get_param(const String ¶m)const
112 return Layer_Composite::get_param(param);
116 Metaballs::get_param_vocab()const
118 Layer::Vocab ret(Layer_Composite::get_param_vocab());
120 ret.push_back(ParamDesc("color")
121 .set_local_name(_("Color"))
124 ret.push_back(ParamDesc("centers")
125 .set_local_name(_("Points"))
128 ret.push_back(ParamDesc("radii")
129 .set_local_name(_("Radii"))
132 ret.push_back(ParamDesc("weights")
133 .set_local_name(_("Weights"))
136 ret.push_back(ParamDesc("threshold")
137 .set_local_name(_("Threshold"))
143 static inline Real densityfunc(const sinfg::Point &p, const sinfg::Point &c, Real R)
145 const Real dx = p[0] - c[0];
146 const Real dy = p[1] - c[1];
148 const Real n = (1 - (dx*dx + dy*dy)/(R*R));
153 f'(d) = -6d * (1 - d^2)^2
155 could use this too...
157 f'(d) = -6d * (1 - d^2)
162 Metaballs::totaldensity(const Point &pos) const
166 //sum up weighted functions
167 for(unsigned int i=0;i<centers.size();i++)
169 density += weights[i] * densityfunc(pos,centers[i], radii[i]);
176 Metaballs::get_color(Context context, const Point &pos)const
178 Real dens = totaldensity(pos);
180 if(dens >= threshold)
183 return context.get_color(pos);
187 Metaballs::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
189 // Width and Height of a pixel
190 const Point br(renddesc.get_br()),
191 tl(renddesc.get_tl());
193 const int w = renddesc.get_w(),
194 h = renddesc.get_h();
196 Real pw = renddesc.get_pw();
197 Real ph = renddesc.get_ph();
199 SuperCallback supercb(cb,0,9000,10000);
201 if(!context.accelerated_render(surface,quality,renddesc,&supercb))
203 if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__));
207 Point pos(tl[0],tl[1]);
211 if(!context.accelerated_render(surface,quality,renddesc,&supercb))
213 if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__));
217 for(int y = 0; y < h; y++, pos[1] += ph)
220 for(int x = 0; x < w; x++, pos[0] += pw)
222 dens = totaldensity(pos);
224 if(dens >= threshold)
226 (*surface)[y][x] = Color::blend(color,(*surface)[y][x],get_amount(),get_blend_method());
231 // Mark our progress as finished
232 if(cb && !cb->amount_complete(10000,10000))