OP_ERROR SOP_Ocean::cookMySop(OP_Context &context) { float now = context.getTime(); //std::cout << "cook ocean, t = " << now << std::endl; // lock inputs if (lockInputs(context) >= UT_ERROR_ABORT ) { return error(); } GEO_Point *ppt; UT_Interrupt *boss; // Check to see that there hasn't been a critical error in cooking the SOP. if (error() < UT_ERROR_ABORT) { boss = UTgetInterrupt(); // Start the interrupt server boss->opStart("Updating Ocean"); duplicatePointSource(0,context); int gridres = 1 << int(GRID_RES(now)); float stepsize = GRID_SIZE(now) / (float)gridres; bool do_chop = CHOP(now); bool do_jacobian = JACOBIAN(now); bool do_normals = NORMALS(now) && !do_chop; if (!_ocean || _ocean_needs_rebuild) { if (_ocean) { delete _ocean; } if (_ocean_context) { delete _ocean_context; } _ocean = new drw::Ocean(gridres,gridres,stepsize,stepsize, V(0),L(0),1.0,W(0),1-DAMP(0),ALIGN(0), DEPTH(0),SEED(0)); _ocean_scale = _ocean->get_height_normalize_factor(); _ocean_context = _ocean->new_context(true,do_chop,do_normals,do_jacobian); _ocean_needs_rebuild = false; // std::cout << "######### SOP, rebuilt ocean, norm_factor = " << _ocean_scale // << " chop = " << do_chop // << " norm = " << do_normals // << " jacobian = " << do_jacobian // << std::endl; } float chop_amount = CHOPAMOUNT(now); // sum up the waves at this timestep _ocean->update(TIME(now),*_ocean_context,true,do_chop,do_normals,do_jacobian, _ocean_scale * SCALE(now),chop_amount); bool linterp = ! INTERP(now); // get our attribute indices GA_RWAttributeRef normal_index; GA_RWAttributeRef jminus_index; GA_RWAttributeRef eminus_index; if (do_normals) { normal_index = gdp->addNormalAttribute(GEO_POINT_DICT); } if (do_jacobian) { // jminus_index = gdp->addPointAttrib("mineigval",sizeof(float),GB_ATTRIB_FLOAT,0); // eminus_index = gdp->addPointAttrib("mineigvec",sizeof(UT_Vector3),GB_ATTRIB_VECTOR,0); jminus_index = gdp->addTuple(GA_STORE_REAL32,GA_ATTRIB_POINT,"mineigval",1,GA_Defaults(0)); eminus_index = gdp->addFloatTuple(GA_ATTRIB_POINT,"mineigvec",1,GA_Defaults(0)); } // this is not that fast, can it be done quicker ??? GA_FOR_ALL_GPOINTS(gdp, ppt) { UT_Vector4 p = ppt->getPos(); if (linterp) { _ocean_context->eval_xz(p(0),p(2)); } else { _ocean_context->eval2_xz(p(0),p(2)); } if (do_chop) { p.assign( p(0) + _ocean_context->disp[0], p(1) + _ocean_context->disp[1], p(2) + _ocean_context->disp[2] ); } else { // ppt->getPos()(1) += _ocean_context->disp[1]; UT_Vector4 tmp_p = ppt->getPos(); tmp_p(1) += _ocean_context->disp[1]; ppt->setPos(tmp_p); } if (do_normals) { /* UT_Vector3* normal = (UT_Vector3*) ppt->castAttribData<UT_Vector3>(normal_index); normal->assign(_ocean_context->normal[0], _ocean_context->normal[1], _ocean_context->normal[2]); normal->normalize(); */ ppt->getValue<UT_Vector3>(normal_index).assign(_ocean_context->normal[0], _ocean_context->normal[1], _ocean_context->normal[2]); ppt->getValue<UT_Vector3>(normal_index).normalize(); } if (do_jacobian) {/* float *js = (float*)ppt->castAttribData<float>(jminus_index); *js = _ocean_context->Jminus; UT_Vector3* eminus = (UT_Vector3*)ppt->castAttribData<UT_Vector3>(eminus_index); eminus->assign(_ocean_context->Eminus[0],0,_ocean_context->Eminus[1]); */ ppt->setValue<float>(jminus_index,_ocean_context->Jminus); ppt->getValue<UT_Vector3>(eminus_index).assign(_ocean_context->Eminus[0],0,_ocean_context->Eminus[1]); } ppt->setPos(p); }
OP_ERROR aaOceanSOP::cookMySop(OP_Context &context) { if (lockInputs(context) >= UT_ERROR_ABORT) return error(); duplicateSource(0, context); setVariableOrder(3, 2, 0, 1); setCurGdh(0, myGdpHandle); setupLocalVars(); // variable declarations float now = context.getTime(); // Flag the SOP as being time dependent (i.e. cook on time changes) flags().timeDep = 1; // start pulling in SOP inputs and send to aaOcean enableEigens = (ENABLEEIGENS() != 0); if(pOcean->isChoppy() && enableEigens) enableEigens = TRUE; now = now + TIMEOFFSET(now); pOcean->input( RESOLUTION(), SEED(), OCEANSCALE(now), OCEANDEPTH(now), SURFACETENSION(now), VELOCITY(now), CUTOFF(now), WINDDIR(now), WINDALIGN(), DAMP(now), WAVESPEED(now), WAVEHEIGHT(now), CHOP(now), now, LOOPTIME(now), enableEigens, FALSE); // get the user-specified attribute that holds uv-data getUVAttributeName(UvAttribute); if(UvAttribute.length() == 0) UvAttribute = "uv"; const char* UVAttribName = (const char *)UvAttribute; uvRef = gdp->findFloatTuple(GA_ATTRIB_POINT, UVAttribName, 3); if(uvRef.isValid() == TRUE) { uvAttribute = uvRef.getAttribute(); uvTuple = uvRef.getAIFTuple(); } else { // uv attribute not found char msg[256]; sprintf(msg, "[aaOcean] Specified UV attribute \'%s\' not found on geometry.\ \nUV's are required for aaOcean to cook", UVAttribName); std::cout<<msg; std::cout.flush(); addError(SOP_MESSAGE, msg); unlockInputs(); return error(); } // setup local variables to output Eigens if(enableEigens) { eVecPlusRef = gdp->addFloatTuple(GA_ATTRIB_POINT, eVecPlusName, 3); eVecMinusRef = gdp->addFloatTuple(GA_ATTRIB_POINT, eVecMinusName, 3); eValuesRef = gdp->addFloatTuple(GA_ATTRIB_POINT, eValuesName, 1); eVecPlusHandle = GA_RWHandleV3(eVecPlusRef.getAttribute()); eVecMinusHandle = GA_RWHandleV3(eVecMinusRef.getAttribute()); eValuesHandle = GA_RWHandleF(eValuesRef.getAttribute()); } // inputs validated. Begin writing ocean data to output handles int npts = gdp->getNumPoints(); #pragma omp parallel for for (int pt_offset = 0; pt_offset < npts; ++pt_offset) { UT_Vector3F pos = gdp->getPos3(pt_offset); UT_Vector3F UV; uvTuple->get(uvAttribute, pt_offset, UV.data(), 3); // Houdini V coord runs in opposite direction compared to Softimage/Maya // Conforming with other apps to make ocean shape consistent across apps float u = UV.x(); float v = 1.0f - (fmod(UV.y(), 1.0f)); pos.y() += pOcean->getOceanData(u, v, aaOcean::eHEIGHTFIELD); if(pOcean->isChoppy()) { pos.x() += pOcean->getOceanData(u, v, aaOcean::eCHOPX); pos.z() += pOcean->getOceanData(u, v, aaOcean::eCHOPZ); } gdp->setPos3(pt_offset, pos); if(enableEigens) { UT_Vector3F eigenVectorPlusValue; UT_Vector3F eigenVectorMinusValue; float eigenValue; eigenVectorPlusValue.x() = pOcean->getOceanData(u, v, aaOcean::eEIGENPLUSX); eigenVectorPlusValue.y() = 0.0f; eigenVectorPlusValue.z() = pOcean->getOceanData(u, v, aaOcean::eEIGENPLUSZ); eigenVectorMinusValue.x() = pOcean->getOceanData(u, v, aaOcean::eEIGENMINUSX); eigenVectorMinusValue.y() = 0.0f; eigenVectorMinusValue.z() = pOcean->getOceanData(u, v, aaOcean::eEIGENMINUSZ); eigenValue = pOcean->getOceanData(u, v, aaOcean::eFOAM); eVecPlusHandle.set(pt_offset,eigenVectorPlusValue); eVecMinusHandle.set(pt_offset,eigenVectorMinusValue); eValuesHandle.set(pt_offset,eigenValue); } } unlockInputs(); return error(); }