00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "SIM_SolverHair.h"
00029 #include <UT/UT_DSOVersion.h>
00030 #include <GU/GU_PrimPoly.h>
00031 #include <PRM/PRM_Include.h>
00032 #include <SIM/SIM_DopDescription.h>
00033 #include <SIM/SIM_GeometryCopy.h>
00034 #include <SIM/SIM_DataFilter.h>
00035 #include <SIM/SIM_Object.h>
00036 #include <SIM/SIM_ObjectArray.h>
00037 #include <SIM/SIM_Engine.h>
00038 #include <SIM/SIM_Force.h>
00039
00040 using namespace HDK_Sample;
00041
00042 void
00043 initializeSIM(void *)
00044 {
00045 IMPLEMENT_DATAFACTORY(SIM_SolverHair);
00046 }
00047
00048 namespace HDK_Sample {
00049
00050 class SIM_HairForceCallback : public SIM_PointForceCallback,
00051 public SIM_EachDataCallback
00052 {
00053 public:
00054 SIM_HairForceCallback(GU_Detail &gdp,
00055 const SIM_Object &object,
00056 const UT_DMatrix4 &xform,
00057 fpreal timestep,
00058 int massoffset,
00059 int veloffset);
00060 virtual ~SIM_HairForceCallback();
00061
00062 virtual void callbackConst(const SIM_Data *data,
00063 const char *name);
00064 virtual void forceCallback(int ptnum,
00065 const UT_Vector3 &force,
00066 const UT_Vector3 &torque);
00067
00068 private:
00069 GU_Detail &myGdp;
00070 const SIM_Object &myObject;
00071 const UT_DMatrix4 myTransform;
00072 fpreal myTimestep;
00073 int myMassOffset;
00074 int myVelOffset;
00075 };
00076
00077 }
00078
00079 SIM_HairForceCallback::SIM_HairForceCallback(GU_Detail &gdp,
00080 const SIM_Object &object,
00081 const UT_DMatrix4 &xform,
00082 fpreal timestep,
00083 int massoffset,
00084 int veloffset)
00085 : myGdp(gdp),
00086 myObject(object),
00087 myTransform(xform),
00088 myTimestep(timestep),
00089 myMassOffset(massoffset),
00090 myVelOffset(veloffset)
00091 {
00092 }
00093
00094 SIM_HairForceCallback::~SIM_HairForceCallback()
00095 {
00096 }
00097
00098 void
00099 SIM_HairForceCallback::callbackConst(const SIM_Data *data, const char *)
00100 {
00101 const SIM_Force *force = SIM_DATA_CASTCONST(data, SIM_Force);
00102 GU_DetailHandle gdh;
00103
00104 gdh.allocateAndSet(&myGdp, false);
00105 force->getPointForces(*this, myObject, gdh, myTransform, 0, 0, false);
00106 }
00107
00108 void
00109 SIM_HairForceCallback::forceCallback(int ptnum,
00110 const UT_Vector3 &force,
00111 const UT_Vector3 &)
00112 {
00113 GEO_Point *ppt = myGdp.points()(ptnum);
00114 UT_Vector3 *vel;
00115 float mass;
00116
00117 mass = *ppt->castAttribData<float>(myMassOffset);
00118 vel = ppt->castAttribData<UT_Vector3>(myVelOffset);
00119 *vel += (force/mass) * myTimestep;
00120 }
00121
00122 SIM_SolverHair::SIM_SolverHair(const SIM_DataFactory *factory)
00123 : BaseClass(factory),
00124 SIM_OptionsUser(this)
00125 {
00126 }
00127
00128 SIM_SolverHair::~SIM_SolverHair()
00129 {
00130 }
00131
00132 const SIM_DopDescription *
00133 SIM_SolverHair::getSolverHairDopDescription()
00134 {
00135 static PRM_Template theTemplates[] = {
00136 PRM_Template()
00137 };
00138
00139 static SIM_DopDescription theDopDescription(true,
00140 "hdk_hairsolver",
00141 "Hair Solver",
00142 SIM_SOLVER_DATANAME,
00143 classname(),
00144 theTemplates);
00145
00146 return &theDopDescription;
00147 }
00148
00149 void
00150 SIM_SolverHair::solveHair(SIM_GeometryCopy &hairgeo,
00151 const SIM_ObjectArray &srcobjs,
00152 const SIM_Object &object,
00153 const SIM_Time ×tep) const
00154 {
00155 GU_DetailHandleAutoWriteLock gdl(hairgeo.lockGeometry());
00156 GU_Detail &gdp = *gdl.getGdp();
00157 UT_DMatrix4 xform;
00158 UT_Vector4 startpos, midline;
00159 UT_Vector3 dp, dv;
00160 const UT_Vector3 zero(0.0, 0.0, 0.0);
00161 const float one = 1.0;
00162 GEO_Primitive *hairpoly;
00163 GEO_Point *hairpt0, *hairpt1, *hairpt2;
00164 int massoffset, veloffset;
00165 int primnum, ptnum, geonum, numhairprims;
00166
00167 hairgeo.getTransform(xform);
00168 primnum = 0;
00169 numhairprims = gdp.primitives().entries();
00170 for( geonum = 0; geonum < srcobjs.entries(); geonum++ )
00171 {
00172 const SIM_Object *sourceobj = srcobjs(geonum);
00173 const SIM_Geometry *sourcegeo = sourceobj->getGeometry();
00174 if(!sourcegeo || sourcegeo->getGeometry().isNull())
00175 continue;
00176
00177 GU_DetailHandleAutoReadLock sourcegdl(sourcegeo->getGeometry());
00178 const GU_Detail *sourcegdp = sourcegdl.getGdp();
00179 const GEO_Point *sourcept;
00180 UT_DMatrix4 sourcexform;
00181
00182 SIMgetGeometryTransform(sourcexform, *sourceobj);
00183 massoffset = gdp.addPointAttrib(
00184 gdp.getStdAttributeName(GEO_ATTRIBUTE_MASS),
00185 sizeof(float), GB_ATTRIB_FLOAT, &one);
00186 veloffset = gdp.addPointAttrib(
00187 gdp.getStdAttributeName(GEO_ATTRIBUTE_VELOCITY),
00188 sizeof(UT_Vector3), GB_ATTRIB_VECTOR, &zero);
00189
00190
00191 SIM_HairForceCallback callback(gdp, object, xform, timestep,
00192 massoffset, veloffset);
00193 object.forEachConstSubData(callback,
00194 SIM_DataFilterByType("SIM_Force"),
00195 SIM_FORCES_DATANAME,
00196 SIM_DataFilterNone());
00197
00198
00199 FOR_ALL_GPOINTS((&gdp), hairpt0)
00200 {
00201 dp = *(hairpt0->castAttribData<UT_Vector3>(veloffset));
00202 dp *= timestep;
00203
00204 hairpt0->getPos() = hairpt0->getPos() + dp;
00205 }
00206
00207
00208
00209 FOR_ALL_GPOINTS(sourcegdp, sourcept)
00210 {
00211 if( primnum >= numhairprims )
00212 break;
00213
00214 startpos = sourcept->getPos();
00215 startpos *= sourcexform;
00216 hairpoly = gdp.primitives()(primnum);
00217 if( hairpoly->getPrimitiveId() == GEOPRIMPOLY &&
00218 hairpoly->getVertexCount() == 10 )
00219 {
00220 hairpt0 = hairpoly->getVertex(0).getPt();
00221 hairpt1 = hairpoly->getVertex(1).getPt();
00222
00223
00224
00225
00226 dp = startpos - hairpt0->getPos();
00227 dv = dp / timestep;
00228 *(hairpt0->castAttribData<UT_Vector3>(veloffset)) += dv;
00229
00230 *(hairpt0->castAttribData<UT_Vector3>(veloffset)) *= 0.8;
00231 hairpt0->getPos() = hairpt0->getPos() + dp;
00232 for( ptnum = 1; ptnum < 10; ptnum++ )
00233 {
00234 if( ptnum < 9 )
00235 hairpt2 = hairpoly->getVertex(ptnum + 1).getPt();
00236 midline = hairpt2->getPos() - hairpt0->getPos();
00237
00238
00239
00240
00241 dp = midline * (0.1 / midline.length()) +
00242 hairpt0->getPos() - hairpt1->getPos();
00243 dv = dp / timestep;
00244 *(hairpt1->castAttribData<UT_Vector3>(veloffset)) += dv;
00245
00246 *(hairpt1->castAttribData<UT_Vector3>(veloffset)) *= 0.8;
00247 hairpt1->getPos() = hairpt1->getPos() + dp;
00248 hairpt0 = hairpt1;
00249 hairpt1 = hairpt2;
00250 }
00251 }
00252 primnum++;
00253 }
00254 }
00255
00256 hairgeo.releaseGeometry();
00257 }
00258
00259 void
00260 SIM_SolverHair::createHairFromSource(SIM_GeometryCopy &hairgeo,
00261 const SIM_ObjectArray &srcobjs) const
00262 {
00263 GU_DetailHandleAutoWriteLock gdl(hairgeo.lockGeometry());
00264 GU_Detail &gdp = *gdl.getGdp();
00265 UT_Vector4 startpos;
00266 GEO_Point *newpt;
00267 GEO_Face *newpoly;
00268 int i, geonum;
00269
00270 for( geonum = 0; geonum < srcobjs.entries(); geonum++ )
00271 {
00272 const SIM_Object *sourceobj = srcobjs(geonum);
00273 const SIM_Geometry *sourcegeo = sourceobj->getGeometry();
00274 if(!sourcegeo || sourcegeo->getGeometry().isNull())
00275 continue;
00276
00277 GU_DetailHandleAutoReadLock sourcegdl(sourcegeo->getGeometry());
00278 const GU_Detail *sourcegdp = sourcegdl.getGdp();
00279 const GEO_Point *sourcept;
00280 UT_DMatrix4 sourcexform;
00281
00282 SIMgetGeometryTransform(sourcexform, *sourceobj);
00283 FOR_ALL_GPOINTS(sourcegdp, sourcept)
00284 {
00285 startpos = sourcept->getPos();
00286 startpos *= sourcexform;
00287 newpoly = GU_PrimPoly::build(&gdp, 0, GU_POLY_OPEN, 0);
00288 for( i = 0; i < 10; i++ )
00289 {
00290 newpt = gdp.appendPoint();
00291 newpt->getPos().assign(startpos.x(),
00292 startpos.y() + (fpreal)i * 0.1,
00293 startpos.z(),
00294 1.0);
00295 newpoly->appendVertex(newpt);
00296 }
00297 }
00298 }
00299
00300 hairgeo.releaseGeometry();
00301 }
00302
00303 SIM_Solver::SIM_Result
00304 SIM_SolverHair::solveSingleObjectSubclass(SIM_Engine & ,
00305 SIM_Object &object,
00306 SIM_ObjectArray &,
00307 const SIM_Time ×tep,
00308 bool newobject)
00309 {
00310 SIM_GeometryCopy *hairgeo = 0;
00311 SIM_ObjectArray sourceobjects;
00312
00313 if( newobject )
00314 {
00315 if( !SIM_DATA_GET(object, SIM_GEOMETRY_DATANAME, SIM_GeometryCopy) )
00316 {
00317 hairgeo = SIM_DATA_CREATE(object, SIM_GEOMETRY_DATANAME,
00318 SIM_GeometryCopy, 0);
00319 object.getAffectors(sourceobjects, "SIM_RelationshipSource");
00320 if( hairgeo && sourceobjects.entries() > 0 )
00321 createHairFromSource(*hairgeo, sourceobjects);
00322 }
00323 }
00324 else
00325 {
00326 hairgeo = SIM_DATA_GET(object, SIM_GEOMETRY_DATANAME, SIM_GeometryCopy);
00327 if( hairgeo )
00328 {
00329 object.getAffectors(sourceobjects, "SIM_RelationshipSource");
00330 if( hairgeo && sourceobjects.entries() > 0 )
00331 solveHair(*hairgeo, sourceobjects, object, timestep);
00332 }
00333 }
00334
00335 return hairgeo ? SIM_SOLVER_SUCCESS : SIM_SOLVER_FAIL;
00336 }
00337