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 const GB_AttributeRef &massoffset,
00059 const GB_AttributeRef &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 GB_AttributeRef myMassOffset;
00074 GB_AttributeRef 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 const GB_AttributeRef &massoffset,
00084 const GB_AttributeRef &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 float mass;
00115
00116 mass = ppt->getValue<float>(myMassOffset);
00117 ppt->setValue<UT_Vector3>(myVelOffset,
00118 ppt->getValue<UT_Vector3>(myVelOffset) + (force/mass)*myTimestep);
00119 }
00120
00121 SIM_SolverHair::SIM_SolverHair(const SIM_DataFactory *factory)
00122 : BaseClass(factory),
00123 SIM_OptionsUser(this)
00124 {
00125 }
00126
00127 SIM_SolverHair::~SIM_SolverHair()
00128 {
00129 }
00130
00131 const SIM_DopDescription *
00132 SIM_SolverHair::getSolverHairDopDescription()
00133 {
00134 static PRM_Template theTemplates[] = {
00135 PRM_Template()
00136 };
00137
00138 static SIM_DopDescription theDopDescription(true,
00139 "hdk_hairsolver",
00140 "Hair Solver",
00141 SIM_SOLVER_DATANAME,
00142 classname(),
00143 theTemplates);
00144
00145 return &theDopDescription;
00146 }
00147
00148 void
00149 SIM_SolverHair::solveHair(SIM_GeometryCopy &hairgeo,
00150 const SIM_ObjectArray &srcobjs,
00151 const SIM_Object &object,
00152 const SIM_Time ×tep) const
00153 {
00154 GU_DetailHandleAutoWriteLock gdl(hairgeo.lockGeometry());
00155 GU_Detail &gdp = *gdl.getGdp();
00156 UT_DMatrix4 xform;
00157 UT_Vector4 startpos, midline;
00158 UT_Vector3 dp, dv;
00159 const UT_Vector3 zero(0.0, 0.0, 0.0);
00160 const float one = 1.0;
00161 GEO_Primitive *hairpoly;
00162 GEO_Point *hairpt0, *hairpt1, *hairpt2;
00163 GB_AttributeRef massoffset, veloffset;
00164 int primnum, ptnum, geonum, numhairprims;
00165
00166 hairgeo.getTransform(xform);
00167 primnum = 0;
00168 numhairprims = gdp.primitives().entries();
00169 for( geonum = 0; geonum < srcobjs.entries(); geonum++ )
00170 {
00171 const SIM_Object *sourceobj = srcobjs(geonum);
00172 const SIM_Geometry *sourcegeo = sourceobj->getGeometry();
00173 if(!sourcegeo || sourcegeo->getGeometry().isNull())
00174 continue;
00175
00176 GU_DetailHandleAutoReadLock sourcegdl(sourcegeo->getGeometry());
00177 const GU_Detail *sourcegdp = sourcegdl.getGdp();
00178 const GEO_Point *sourcept;
00179 UT_DMatrix4 sourcexform;
00180
00181 SIMgetGeometryTransform(sourcexform, *sourceobj);
00182 massoffset = gdp.addPointAttrib(
00183 gdp.getStdAttributeName(GEO_ATTRIBUTE_MASS),
00184 sizeof(float), GB_ATTRIB_FLOAT, &one);
00185 veloffset = gdp.addPointAttrib(
00186 gdp.getStdAttributeName(GEO_ATTRIBUTE_VELOCITY),
00187 sizeof(UT_Vector3), GB_ATTRIB_VECTOR, &zero);
00188
00189
00190 SIM_HairForceCallback callback(gdp, object, xform, timestep,
00191 massoffset, veloffset);
00192 object.forEachConstSubData(callback,
00193 SIM_DataFilterByType("SIM_Force"),
00194 SIM_FORCES_DATANAME,
00195 SIM_DataFilterNone());
00196
00197
00198 FOR_ALL_GPOINTS((&gdp), hairpt0)
00199 {
00200 dp = hairpt0->getValue<UT_Vector3>(veloffset);
00201 dp *= timestep;
00202
00203 hairpt0->getPos() = hairpt0->getPos() + dp;
00204 }
00205
00206
00207
00208 FOR_ALL_GPOINTS(sourcegdp, sourcept)
00209 {
00210 if( primnum >= numhairprims )
00211 break;
00212
00213 startpos = sourcept->getPos();
00214 startpos *= sourcexform;
00215 hairpoly = gdp.primitives()(primnum);
00216 if( hairpoly->getPrimitiveId() == GEOPRIMPOLY &&
00217 hairpoly->getVertexCount() == 10 )
00218 {
00219 UT_Vector3 vel;
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 vel = hairpt0->getValue<UT_Vector3>(veloffset);
00229 vel += dv;
00230
00231 vel *= 0.8;
00232 hairpt0->setValue<UT_Vector3>(veloffset, vel);
00233 hairpt0->getPos() = hairpt0->getPos() + dp;
00234 for( ptnum = 1; ptnum < 10; ptnum++ )
00235 {
00236 if( ptnum < 9 )
00237 hairpt2 = hairpoly->getVertex(ptnum + 1).getPt();
00238 midline = hairpt2->getPos() - hairpt0->getPos();
00239
00240
00241
00242
00243 dp = midline * (0.1 / midline.length()) +
00244 hairpt0->getPos() - hairpt1->getPos();
00245 dv = dp / timestep;
00246 vel = hairpt1->getValue<UT_Vector3>(veloffset);
00247 vel += dv;
00248
00249 vel *= 0.8;
00250 hairpt1->setValue<UT_Vector3>(veloffset, vel);
00251 hairpt1->getPos() = hairpt1->getPos() + dp;
00252 hairpt0 = hairpt1;
00253 hairpt1 = hairpt2;
00254 }
00255 }
00256 primnum++;
00257 }
00258 }
00259
00260 hairgeo.releaseGeometry();
00261 }
00262
00263 void
00264 SIM_SolverHair::createHairFromSource(SIM_GeometryCopy &hairgeo,
00265 const SIM_ObjectArray &srcobjs) const
00266 {
00267 GU_DetailHandleAutoWriteLock gdl(hairgeo.lockGeometry());
00268 GU_Detail &gdp = *gdl.getGdp();
00269 UT_Vector4 startpos;
00270 GEO_Point *newpt;
00271 GEO_Face *newpoly;
00272 int i, geonum;
00273
00274 for( geonum = 0; geonum < srcobjs.entries(); geonum++ )
00275 {
00276 const SIM_Object *sourceobj = srcobjs(geonum);
00277 const SIM_Geometry *sourcegeo = sourceobj->getGeometry();
00278 if(!sourcegeo || sourcegeo->getGeometry().isNull())
00279 continue;
00280
00281 GU_DetailHandleAutoReadLock sourcegdl(sourcegeo->getGeometry());
00282 const GU_Detail *sourcegdp = sourcegdl.getGdp();
00283 const GEO_Point *sourcept;
00284 UT_DMatrix4 sourcexform;
00285
00286 SIMgetGeometryTransform(sourcexform, *sourceobj);
00287 FOR_ALL_GPOINTS(sourcegdp, sourcept)
00288 {
00289 startpos = sourcept->getPos();
00290 startpos *= sourcexform;
00291 newpoly = GU_PrimPoly::build(&gdp, 0, GU_POLY_OPEN, 0);
00292 for( i = 0; i < 10; i++ )
00293 {
00294 newpt = gdp.appendPoint();
00295 newpt->getPos().assign(startpos.x(),
00296 startpos.y() + (fpreal)i * 0.1,
00297 startpos.z(),
00298 1.0);
00299 newpoly->appendVertex(newpt);
00300 }
00301 }
00302 }
00303
00304 hairgeo.releaseGeometry();
00305 }
00306
00307 SIM_Solver::SIM_Result
00308 SIM_SolverHair::solveSingleObjectSubclass(SIM_Engine & ,
00309 SIM_Object &object,
00310 SIM_ObjectArray &,
00311 const SIM_Time ×tep,
00312 bool newobject)
00313 {
00314 SIM_GeometryCopy *hairgeo = 0;
00315 SIM_ObjectArray sourceobjects;
00316
00317 if( newobject )
00318 {
00319 if( !SIM_DATA_GET(object, SIM_GEOMETRY_DATANAME, SIM_GeometryCopy) )
00320 {
00321 hairgeo = SIM_DATA_CREATE(object, SIM_GEOMETRY_DATANAME,
00322 SIM_GeometryCopy, 0);
00323 object.getAffectors(sourceobjects, "SIM_RelationshipSource");
00324 if( hairgeo && sourceobjects.entries() > 0 )
00325 createHairFromSource(*hairgeo, sourceobjects);
00326 }
00327 }
00328 else
00329 {
00330 hairgeo = SIM_DATA_GET(object, SIM_GEOMETRY_DATANAME, SIM_GeometryCopy);
00331 if( hairgeo )
00332 {
00333 object.getAffectors(sourceobjects, "SIM_RelationshipSource");
00334 if( hairgeo && sourceobjects.entries() > 0 )
00335 solveHair(*hairgeo, sourceobjects, object, timestep);
00336 }
00337 }
00338
00339 return hairgeo ? SIM_SOLVER_SUCCESS : SIM_SOLVER_FAIL;
00340 }
00341