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
00029
00030 #include <UT/UT_DSOVersion.h>
00031 #include <GU/GU_Detail.h>
00032 #include <GU/GU_PrimPoly.h>
00033 #include <PRM/PRM_Include.h>
00034 #include <PRM/PRM_ChoiceList.h>
00035 #include <OP/OP_Operator.h>
00036 #include <OP/OP_OperatorTable.h>
00037
00038 #include <SOP/SOP_Guide.h>
00039 #include "SOP_BrushHairLen.h"
00040
00041 using namespace HDK_Sample;
00042
00043 #define PRM_MENU_CHOICES (PRM_ChoiceListType)(PRM_CHOICELIST_EXCLUSIVE |\
00044 PRM_CHOICELIST_REPLACE)
00045
00046
00047 void
00048 newSopOperator(OP_OperatorTable *table)
00049 {
00050 table->addOperator(new OP_Operator("proto_brushhairlen",
00051 "Brush Hair Length",
00052 SOP_BrushHairLen::myConstructor,
00053 SOP_BrushHairLen::myTemplateList,
00054 1,
00055 1));
00056 }
00057
00058 static PRM_Name sop_names[] = {
00059 PRM_Name("group", "Group"),
00060 PRM_Name("op", "Operation"),
00061 PRM_Name("flen", "FL"),
00062 PRM_Name("blen", "BL"),
00063 PRM_Name("radius", "Radius"),
00064 PRM_Name("uvradius", "UV Radius"),
00065 PRM_Name(0)
00066 };
00067
00068 static PRM_Name sopOpMenuNames[] = {
00069 PRM_Name("paint", "Paint"),
00070 PRM_Name("eyedrop", "Eye Dropper"),
00071 PRM_Name("smoothattrib", "Smooth"),
00072 PRM_Name("callback", "Callback"),
00073 PRM_Name("erase", "Erase Changes"),
00074 PRM_Name(0)
00075 };
00076 static PRM_ChoiceList sopOpMenu(PRM_MENU_CHOICES, sopOpMenuNames);
00077
00078 PRM_Template
00079 SOP_BrushHairLen::myTemplateList[]=
00080 {
00081
00082 PRM_Template(PRM_STRING, 1, &sop_names[0], 0, &SOP_Node::primGroupMenu),
00083
00084
00085 PRM_Template((PRM_Type) PRM_ORD,
00086 PRM_Template::PRM_EXPORT_MAX,
00087 1, &sop_names[1], 0, &sopOpMenu),
00088
00089 PRM_Template(PRM_FLT_J, PRM_Template::PRM_EXPORT_TBX,
00090 1, &sop_names[2], PRMoneDefaults),
00091
00092 PRM_Template(PRM_FLT_J, PRM_Template::PRM_EXPORT_TBX,
00093 1, &sop_names[3], PRMzeroDefaults),
00094
00095 PRM_Template(PRM_FLT_J, PRM_Template::PRM_EXPORT_TBX,
00096 1, &sop_names[4], PRMpointOneDefaults),
00097
00098 PRM_Template(PRM_FLT_J, PRM_Template::PRM_EXPORT_TBX,
00099 1, &sop_names[5], PRMpointOneDefaults),
00100 PRM_Template()
00101 };
00102
00103 OP_Node *
00104 SOP_BrushHairLen::myConstructor(OP_Network *net,const char *name,OP_Operator *entry)
00105 {
00106 return new SOP_BrushHairLen(net, name, entry);
00107 }
00108
00109
00110 SOP_BrushHairLen::SOP_BrushHairLen(OP_Network *net, const char *name, OP_Operator *entry)
00111 : SOP_BrushBase(net, name, entry)
00112 {
00113
00114
00115
00116 myRayOrient = 0.0f;
00117 myRayHit = 0.0f;
00118 myRayHitU = myRayHitV = 0.0f;
00119 myRayHitPressure = 1.0f;
00120 myPrimHit = -1;
00121 myEvent = SOP_BRUSHSTROKE_NOP;
00122 myUseFore = true;
00123 myStrokeChanged = false;
00124 }
00125
00126 SOP_BrushHairLen::~SOP_BrushHairLen()
00127 {
00128 }
00129
00130
00131 unsigned
00132 SOP_BrushHairLen::disableParms()
00133 {
00134 int changed = 0;
00135
00136 return changed;
00137 }
00138
00139 SOP_BrushOp
00140 SOP_BrushHairLen::OP()
00141 {
00142 switch (evalInt("op", 0, 0))
00143 {
00144 case 0: return SOP_BRUSHOP_PAINT;
00145 case 1: return SOP_BRUSHOP_EYEDROP;
00146 case 2: return SOP_BRUSHOP_SMOOTHATTRIB;
00147 case 3: return SOP_BRUSHOP_CALLBACK;
00148 case 4: default: return SOP_BRUSHOP_ERASE;
00149 }
00150 }
00151
00152 void
00153 SOP_BrushHairLen::setBrushOp(SOP_BrushOp op)
00154 {
00155 int iop;
00156 switch (op)
00157 {
00158 case SOP_BRUSHOP_EYEDROP: iop = 1; break;
00159 case SOP_BRUSHOP_SMOOTHATTRIB: iop = 2; break;
00160 case SOP_BRUSHOP_CALLBACK: iop = 3; break;
00161 case SOP_BRUSHOP_ERASE: iop = 4; break;
00162 case SOP_BRUSHOP_PAINT:
00163 default: iop = 0; break;
00164 }
00165 setInt("op", 0, 0, iop);
00166 }
00167
00168 void
00169 SOP_BrushHairLen::doErase()
00170 {
00171
00172 myBrush.eraseAttributes(myPermanentDelta, myCurrentDelta);
00173 if (myBrush.doVisualize())
00174 myBrush.applyVisualizeStencil(gdp);
00175 }
00176
00177 bool
00178 SOP_BrushHairLen::hasStyleChanged(float t)
00179 {
00180
00181 return isParmDirty(1, t) ||
00182 isParmDirty(2, t);
00183 }
00184
00185 const GU_Detail *
00186 SOP_BrushHairLen::getIsectGdp()
00187 {
00188 SOP_Node *sop;
00189 OP_Context context(0.0f);
00190
00191
00192
00193 sop = CAST_SOPNODE(getInput(0));
00194
00195 return sop->getCookedGeo(context);
00196 }
00197
00198 OP_ERROR
00199 SOP_BrushHairLen::cookMySop(OP_Context &context)
00200 {
00201 float t = context.myTime;
00202 int aoff, i;
00203 GB_Attribute *attrib;
00204 static float zero = 0.0;
00205
00206 if (lockInputs(context) >= UT_ERROR_ABORT) return error();
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 #define BUILD_HAIR
00217 #ifdef BUILD_HAIR
00218
00219
00220 duplicateSource(0, context);
00221
00222
00223 attrib = gdp->pointAttribs().find("hairlen", GB_ATTRIB_FLOAT);
00224
00225
00226 if (!attrib)
00227 {
00228
00229 gdp->addPointAttrib("hairlen", sizeof(float), GB_ATTRIB_FLOAT, &zero);
00230 attrib = gdp->pointAttribs().find("hairlen", GB_ATTRIB_FLOAT);
00231 }
00232
00233
00234
00235 gdp->addVariableName("hairlen", "HAIRLEN");
00236
00237
00238 myHairlenIdx = -2;
00239 myTime = t;
00240
00241
00242
00243
00244
00245 processBrushOp(context, true, true);
00246
00247
00248 myStrokeChanged = false;
00249
00250 aoff = gdp->pointAttribs().getOffset("hairlen", GB_ATTRIB_FLOAT);
00251 if (aoff < 0)
00252 {
00253
00254 UT_ASSERT(!"Newly created hairlen disappeared!");
00255 unlockInputs();
00256 return error();
00257 }
00258
00259
00260 int n;
00261
00262 n = gdp->points().entries();
00263 for (i = 0; i < n; i++)
00264 {
00265 GEO_Point *pt, *lpt;
00266 GU_PrimPoly *poly;
00267
00268 pt = gdp->points()(i);
00269 lpt = gdp->appendPoint();
00270 lpt->getPos() = pt->getPos();
00271
00272 lpt->getPos().y() += *(pt->castAttribData<float>(aoff));
00273
00274
00275 poly = GU_PrimPoly::build(gdp, 2, GU_POLY_OPEN, 0);
00276 poly->setVertex(0, pt);
00277 poly->setVertex(1, lpt);
00278 }
00279 #else
00280 bool changed_input = false;
00281 bool changed_group = false;
00282
00283 changed_input = checkChangedSource(0, context);
00284 changed_group = isParmDirty(SOP_GDT_GRP_IDX, context.myTime);
00285
00286 if (changed_input)
00287 duplicateChangedSource(0, context, 0, true);
00288
00289
00290 attrib = gdp->pointAttribs().find("hairlen", GB_ATTRIB_FLOAT);
00291
00292
00293 if (!attrib)
00294 {
00295
00296 gdp->addPointAttrib("hairlen", sizeof(float), GB_ATTRIB_FLOAT, &zero);
00297 attrib = gdp->pointAttribs().find("hairlen", GB_ATTRIB_FLOAT);
00298 }
00299
00300
00301
00302 gdp->addVariableName("hairlen", "HAIRLEN");
00303
00304 processBrushOp(context, changed_input, changed_group);
00305 #endif
00306
00307 unlockInputs();
00308 return error();
00309 }
00310
00311 void
00312 SOP_BrushHairLen::brushOpCallback(
00313 GEO_Point *pt,
00314 const UT_PtrArray<const GEO_Point *> * ,
00315 GEO_Vertex * ,
00316 const UT_PtrArray<const GEO_Vertex *> * ,
00317 GEO_Primitive * ,
00318 int ,
00319 float alpha,
00320 GEO_Delta *delta)
00321 {
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 if (myHairlenIdx == -2)
00332 myHairlenIdx = gdp->findPointAttrib("hairlen", sizeof(float), GB_ATTRIB_FLOAT);
00333
00334
00335 if (myHairlenIdx < 0)
00336 return;
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 float newhair = (myUseFore ? FGR(myTime) : BGR(myTime));
00348 float oldhair, *hair;
00349
00350 if (pt)
00351 {
00352 if (delta) delta->beginPointAttributeChange(*pt);
00353
00354
00355 hair = pt->castAttribData<float>(myHairlenIdx);
00356 oldhair = *hair;
00357
00358
00359 *hair = (1.0f - alpha) * oldhair + alpha * newhair;
00360
00361 if (delta) delta->endChange();
00362 }
00363 }