void Geo2Emp::transferParticlePointAttribs(int numAttribs, GEO_AttributeHandleList& attribList, std::map<int, AttributeInfo>& attrLut, Nb::ParticleShape& shape, const GEO_Point* ppt)
{
	GEO_AttributeHandle* pAttr;
	AttributeInfo* pAttrInfo;

	for (int i = 0; i < numAttribs; i++)
	{
		pAttr = attribList[i];
		pAttrInfo = &( attrLut[i] );

		if (!pAttrInfo->supported)
			//Skip unsupported attributes
			continue;

		pAttr->setElement( ppt );
		if (! pAttr->isAttributeValid() )
		{
			LogDebug() << "Invalid attribute handle on supported attribute!! [" << pAttr->getName() << "]" << std::endl;
		}

		LogDebug() << "Transferring attribute: " << pAttr->getName() << std::endl;

		switch ( pAttrInfo->type )
		{
			case GB_ATTRIB_FLOAT:
				//LogDebug() << "Transfer Float" << pAttrInfo->entries << "[" << pAttr->getName() << "]" << std::endl;
				switch ( pAttrInfo->entries )
				{
					case 1:
						{
							//LogDebug() << "Float1: " << pAttr->getV3() << std::endl;
							//Get the channel from the point shape
							em::block3_array1f& vecData = shape.mutableBlocks1f( pAttrInfo->empIndex );
							//Write the data into the buffer
							vecData(0).push_back( pAttr->getF() );
						}
						break;
					case 3:
						{
							LogDebug() << "Float3: " << pAttr->getV3() << std::endl;
							//Get the channel from the particle shape
							em::block3_array3f& vecData = shape.mutableBlocks3f( pAttrInfo->empIndex );
							//Write the data into the buffer
							vecData(0).push_back( em::vec3f( pAttr->getF(0), pAttr->getF(1), pAttr->getF(2) ) );
						}
						break;
				}
				break;
			case GB_ATTRIB_INT:
				LogDebug() << "Int " << pAttrInfo->entries << std::endl;
				switch ( pAttrInfo->entries )
				{
					case 1:
						{
							//LogDebug() << "Float1: " << pAttr->getV3() << std::endl;
							//Get the channel from the point shape
							em::block3_array1i& vecData = shape.mutableBlocks1i( pAttrInfo->empIndex );
							//Write the data into the buffer
							vecData(0).push_back( pAttr->getI() );
						}
						break;
					case 3:
						{
							LogDebug() << "Int3: " << std::endl;
							//Get the channel from the particle shape
							em::block3_array3i& vecData = shape.mutableBlocks3i( pAttrInfo->empIndex );
							//Write the data into the buffer
							vecData(0).push_back( em::vec3i( pAttr->getI(0), pAttr->getI(1), pAttr->getI(2) ) );
						}
						break;
				}
				break;
			case GB_ATTRIB_VECTOR:
				{
					//LogDebug() << "Transfer Vector3 [" << pAttr->getName() << "] " <<  pAttr->getF(0) << "," << pAttr->getF(1) << "," << pAttr->getF(2)<< std::endl;
					//If we have a vector, we need to invert it (reverse winding).
					em::block3_array3f& vecData = shape.mutableBlocks3f( pAttrInfo->empIndex );
					//Write the data into the buffer
					vecData(0).push_back( em::vec3f( pAttr->getF(0), pAttr->getF(1), pAttr->getF(2) ) );
					break;
				}
			case GB_ATTRIB_MIXED:
			case GB_ATTRIB_INDEX:
			default:
				//Unsupported attribute, so give it a skip.
				LogDebug() << " !!!!! SHOULDNT GET THIS !!!! Unsupported attribute type for blind copy [" << pAttrInfo->type << "]" << std::endl;
				continue;
				break;
		}

	}

}
示例#2
0
OP_ERROR
SOP_IntersectRay::cookMySop(OP_Context &context)
{
    double t;
    float  edgelength, primarea, generatepoints;
    int    verbose;

    // We optionally add points in self-penetration places:
    GB_PointGroup          *hitPointsGroup;
    UT_RefArray<UT_Vector3> hitPoints;

    if (lockInputs(context) >= UT_ERROR_ABORT)
	    return error();

    t = context.getTime();
    duplicatePointSource(0, context);

    edgelength     = EDGELENGTH(t);
    primarea       = PRIMAREA(t);
    verbose        = VERBOSE(t);
    generatepoints = GENERATEPOINTS(t);

    // Normals:
    GEO_AttributeHandle  nH;
    GEO_AttributeHandle  cdH;
    nH   = gdp->getAttribute(GEO_POINT_DICT, "N");
    cdH  = gdp->getAttribute(GEO_POINT_DICT, "Cd");
   

    // RayInfo parms:
    //float max = 1E18f; // Max specified by edge length...
    float min = 0.0f;
    float tol = 1e-1F;

    // Rayhit objects:
    GU_RayFindType  itype     = GU_FIND_ALL;   
    GU_RayIntersect intersect = GU_RayIntersect(gdp);

    // Profile:
    //Timer timer = Timer();
    //float rayhit_time = 0;
    //float vertex_time = 0;

    // Here we determine which groups we have to work on. 
    if (error() < UT_ERROR_ABORT && cookInputGroups(context) < UT_ERROR_ABORT)
    {
        UT_AutoInterrupt progress("Checking for self-intersections...");
        const GEO_Primitive   *ppr;
        FOR_ALL_GROUP_PRIMITIVES(gdp, myGroup, ppr)
	    {
             // Check if user requested abort
             if (progress.wasInterrupted())
                break;

            // Get rid of primitives smaller than primarea:
            if ( ppr->calcArea() < primarea )
                continue;

            for (int j = 0; j < ppr->getVertexCount() - 1; j++)
            {
                // Get data;
                // TODO: This is extremally inefficent.
                // TODO: Why do we crash with uv vetrex attributes!? 
                const GEO_Vertex ppv1 = ppr->getVertex(j);
                const GEO_Vertex ppv2 = ppr->getVertex(j+1);
                const GEO_Point *ppt1 = ppv1.getPt();
                const GEO_Point *ppt2 = ppv2.getPt();
               
                // Vertices positions:
                UT_Vector3 p1 = ppt1->getPos();
                UT_Vector3 p2 = ppt2->getPos();

                // Ray direction:
                p2   = p2 - p1;
                // Get rid of edges shorter than edgelength:
                if (p2.length() < edgelength)
                    continue;
                // hit info with max distance equal edge length:
                GU_RayInfo  hitinfo = GU_RayInfo(p2.length(), min, itype, tol); 
                p2.normalize();

                // Send ray:
                if (intersect.sendRay(p1, p2, hitinfo))
                {  
                    UT_RefArray<GU_RayInfoHit> hits = *(hitinfo.myHitList);
                    for(int j = 0; j < hits.entries(); j++)
                    {
                        const GEO_Primitive *prim = hits[j].prim;
                        const GEO_PrimPoly  *poly = (const GEO_PrimPoly *) prim; //TODO: Prims only?
                        // We are interested only ff points are not part of prims...:
                        if (poly->find(*ppt1) == -1 && poly->find(*ppt2)== -1)
                        {
                            if (verbose)
                                printf("Edge: %i-%i intersects with prim:%d \n",ppt1->getNum(), ppt2->getNum(), prim->getNum());

                            // Save hit position as points:
                            if (generatepoints)
                            {
                                UT_Vector4 pos;
                                float u = hits[j].u; 
                                float v = hits[j].v;
                                if (!prim->evaluateInteriorPoint(pos, u, v))
                                    hitPoints.append(pos);
                            }

                            // TODO: Should I indicate penetration with red color on both ends of edge?:
                            cdH.setElement(ppt1);
                            cdH.setV3(UT_Vector3(1.0, 0.0, 0.0));
                            cdH.setElement(ppt2);
                            cdH.setV3(UT_Vector3(1.0, 0.0, 0.0));
                        }
                        
                    }
                }
            }
	    } 
     
   
    if (generatepoints)
    {
        hitPointsGroup = gdp->newPointGroup("__self_penetrate", false);
        for (int i = 0; i < hitPoints.entries(); i++)
        {
            GEO_Point *point;
            point = gdp->appendPoint();
            hitPointsGroup->add(point);
            point->setPos(hitPoints(i));
        }
    }
    
    }
OP_ERROR SOP_FluidSolver2D::cookMySop(OP_Context &context) {

	oldf = f;

	double t = context.getTime();
	int f =	context.getFrame();
	UT_Interrupt	*boss;
	GU_PrimVolume	*volume;

	OP_Node::flags().timeDep = 1;
	fluidSolver->fps = OPgetDirector()->getChannelManager()->getSamplesPerSec();


	int newResX = RESX(t);
	int newResY = RESY(t);

	if ( newResX != fluidSolver->res.x || newResY != fluidSolver->res.y) {
		fluidSolver->changeFluidRes(newResX,newResY);

	}

	UT_Vector3 fluidPos(POSX(t), POSY(t), POSZ(t));
	UT_Vector3 fluidRot(ROTX(t), ROTY(t), ROTZ(t));
	fluidRot.degToRad();

	fluidSolver->fluidSize.x = FLUIDSIZEX(t);
	fluidSolver->fluidSize.y = FLUIDSIZEY(t);

	fluidSolver->borderNegX = BORDERNEGX(t);
	fluidSolver->borderPosX = BORDERPOSX(t);
	fluidSolver->borderNegY = BORDERNEGY(t);
	fluidSolver->borderPosY = BORDERPOSY(t);

	fluidSolver->preview = PREVIEW(t);
	fluidSolver->previewType = PREVIEWTYPE(t);
	fluidSolver->bounds = BOUNDS(t);

	fluidSolver->substeps = SUBSTEPS(t);
	fluidSolver->jacIter = JACITER(t);

	fluidSolver->densDis = DENSDIS(t);
	fluidSolver->densBuoyStrength = DENSBUOYSTRENGTH(t);
	float ddirX = DENSBUOYDIRX(t);
	float ddirY = DENSBUOYDIRY(t);
	fluidSolver->densBuoyDir = cu::make_float2(ddirX,ddirY);

	fluidSolver->velDamp = VELDAMP(t);
	fluidSolver->vortConf = VORTCONF(t);

	fluidSolver->noiseStr = NOISESTR(t);
	fluidSolver->noiseFreq = NOISEFREQ(t);
	fluidSolver->noiseOct = NOISEOCT(t);
	fluidSolver->noiseLacun = NOISELACUN(t);
	fluidSolver->noiseSpeed = NOISESPEED(t);
	fluidSolver->noiseAmp = NOISEAMP(t);

    if (error() < UT_ERROR_ABORT) {
			boss = UTgetInterrupt();

		gdp->clearAndDestroy();		

		// Start the interrupt server
		if (boss->opStart("Building Volume")){

			static float		 zero = 0.0;

#ifdef HOUDINI_11
			GB_AttributeRef fluidAtt = gdp->addAttrib("cudaFluidPreview", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(fluidAtt, fluidSolver->preview);

			GB_AttributeRef solverIdAtt = gdp->addAttrib("solverId", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(solverIdAtt, fluidSolver->id);
#else
			GA_WOAttributeRef fluidAtt = gdp->addIntTuple(GA_ATTRIB_DETAIL, "cudaFluidPreview", 1);
			gdp->element().setValue<int>(fluidAtt, fluidSolver->preview);

			GA_WOAttributeRef solverIdAtt = gdp->addIntTuple(GA_ATTRIB_DETAIL, "solverId", 1);
			gdp->element().setValue<int>(solverIdAtt, fluidSolver->id);
#endif


			UT_Matrix3              xform;
			const UT_XformOrder volXFormOrder;
			
			volume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);

#ifdef HOUDINI_11
			volume->getVertex().getPt()->getPos() = fluidPos;
#else
			volume->getVertexElement(0).getPt()->setPos(fluidPos);
#endif

			xform.identity();
			xform.scale(fluidSolver->fluidSize.x*0.5, fluidSolver->fluidSize.y*0.5, 0.25);
			xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder);

			volume->setTransform(xform);
			

			xform.identity();
			xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder);
			xform.invert();

			if(lockInputs(context) >= UT_ERROR_ABORT)
				return error();

			if(getInput(0)){
				GU_Detail* emittersInput = (GU_Detail*)inputGeo(0, context);
				GEO_PointList emittersList = emittersInput->points();
				int numEmitters = emittersList.entries();

				if (numEmitters != fluidSolver->nEmit) {
					delete fluidSolver->emitters;
					fluidSolver->nEmit = numEmitters;
					fluidSolver->emitters = new FluidEmitter[numEmitters];
				}

				GEO_AttributeHandle radAh, amountAh;
				radAh = emittersInput->getPointAttribute("radius");
				amountAh = emittersInput->getPointAttribute("amount");

				for (int i = 0; i < numEmitters; i++) {

					UT_Vector4 emitPos = emittersList[i]->getPos();
					UT_Vector3 emitPos3(emitPos);

					emitPos3 -= fluidPos;
					emitPos3 = emitPos3*xform;

					fluidSolver->emitters[i].posX = emitPos3.x();
					fluidSolver->emitters[i].posY = emitPos3.y();

					radAh.setElement(emittersList[i]);
					amountAh.setElement(emittersList[i]);

					fluidSolver->emitters[i].radius = radAh.getF(0);
					fluidSolver->emitters[i].amount = amountAh.getF(0);
				}
			} else {

				fluidSolver->nEmit = 0;

			}
		

			if(getInput(1)) {
				GU_Detail* collidersInput = (GU_Detail*)inputGeo(1, context);
		
				GEO_PointList collidersList = collidersInput->points();
				int numColliders = collidersList.entries();

				if (numColliders != fluidSolver->nColliders) {
					delete fluidSolver->colliders;
					fluidSolver->nColliders = numColliders;
					fluidSolver->colliders = new Collider[numColliders];
				}

				GEO_AttributeHandle colRadAh;
				colRadAh = collidersInput->getPointAttribute("radius");

				for (int i = 0; i < numColliders; i++) {

					UT_Vector4 colPos = collidersList[i]->getPos();
					UT_Vector3 colPos3(colPos);

					colPos3 -= fluidPos;
					colPos3 = colPos3*xform;

					if (f > STARTFRAME(t)) {
						fluidSolver->colliders[i].oldPosX = fluidSolver->colliders[i].posX;
						fluidSolver->colliders[i].oldPosY = fluidSolver->colliders[i].posY;
					} else {
						fluidSolver->colliders[i].oldPosX = colPos3.x();
						fluidSolver->colliders[i].oldPosY = colPos3.y();
					}

					fluidSolver->colliders[i].posX = colPos3.x();
					fluidSolver->colliders[i].posY = colPos3.y();

					colRadAh.setElement(collidersList[i]);

					fluidSolver->colliders[i].radius = colRadAh.getF(0);
				}

			} else {
				fluidSolver->nColliders = 0;
			}

			unlockInputs();

			if (f <= STARTFRAME(t)) {

				fluidSolver->resetFluid();

				if (fluidSolver->preview != 1) {
					{
						UT_VoxelArrayWriteHandleF	handle = volume->getVoxelWriteHandle();
						handle->constant(0);
					}
				}


			} else {

				if (f!=oldf) {

					fluidSolver->solveFluid();

				}

				if (fluidSolver->preview != 1) {
					
						cu::cudaMemcpy( fluidSolver->host_dens, fluidSolver->dev_dens,
						fluidSolver->res.x*fluidSolver->res.y*sizeof(float), cu::cudaMemcpyDeviceToHost );
				
					{
						UT_VoxelArrayWriteHandleF	handle = volume->getVoxelWriteHandle();

						handle->size(fluidSolver->res.x, fluidSolver->res.y, 1);

						for (int i = 0; i < fluidSolver->res.x; i++) {
							for (int j = 0; j < fluidSolver->res.y; j++) {
								handle->setValue(i, j, 0, fluidSolver->host_dens[(j*fluidSolver->res.x + i)]);
							}
						}
									

					}

				}
			}


		select(GU_SPrimitive);
		}

		// Tell the interrupt server that we've completed. Must do this
		// regardless of what opStart() returns.
		boss->opEnd();
    }

    gdp->notifyCache(GU_CACHE_ALL);
 
    return error();
}
示例#4
-1
OP_ERROR SOP_FluidSolver3D::cookMySop(OP_Context &context) {

	oldf = f;
	f =	context.getFrame();

	double t = context.getTime();

	fluidSolver->fps = OPgetDirector()->getChannelManager()->getSamplesPerSec();

	UT_Interrupt	*boss;
	GU_PrimVolume	*volume;
	GU_PrimVolume	*velXVolume;
	GU_PrimVolume	*velYVolume;
	GU_PrimVolume	*velZVolume;

	OP_Node::flags().timeDep = 1;

	int newResX = RESX(t);
	int newResY = RESY(t);
	int newResZ = RESZ(t);

	if ( newResX != fluidSolver->res.width || newResY != fluidSolver->res.height || newResZ != fluidSolver->res.depth) {
		fluidSolver->changeFluidRes(newResX,newResY,newResZ);

	}

	UT_Vector3 fluidPos(POSX(t), POSY(t), POSZ(t));
	UT_Vector3 fluidRot(ROTX(t), ROTY(t), ROTZ(t));
	fluidRot.degToRad();

	fluidSolver->fluidSize.x = FLUIDSIZEX(t);
	fluidSolver->fluidSize.y = FLUIDSIZEY(t);
	fluidSolver->fluidSize.z = FLUIDSIZEZ(t);

	fluidSolver->borderNegX = BORDERNEGX(t);
	fluidSolver->borderPosX = BORDERPOSX(t);
	fluidSolver->borderNegY = BORDERNEGY(t);
	fluidSolver->borderPosY = BORDERPOSY(t);
	fluidSolver->borderNegZ = BORDERNEGZ(t);
	fluidSolver->borderPosZ = BORDERPOSZ(t);

	fluidSolver->substeps = SUBSTEPS(t);
	fluidSolver->jacIter = JACITER(t);

	fluidSolver->densDis = DENSDIS(t);
	fluidSolver->densBuoyStrength = DENSBUOYSTRENGTH(t);
	float ddirX = DENSBUOYDIRX(t);
	float ddirY = DENSBUOYDIRY(t);
	float ddirZ = DENSBUOYDIRZ(t);
	fluidSolver->densBuoyDir = cu::make_float3(ddirX,ddirY,ddirZ);

	fluidSolver->velDamp = VELDAMP(t);
	fluidSolver->vortConf = VORTCONF(t);

	fluidSolver->noiseStr = NOISESTR(t);
	fluidSolver->noiseFreq = NOISEFREQ(t);
	fluidSolver->noiseOct = NOISEOCT(t);
	fluidSolver->noiseLacun = NOISELACUN(t);
	fluidSolver->noiseSpeed = NOISESPEED(t);
	fluidSolver->noiseAmp = NOISEAMP(t);

	fluidSolver->preview = PREVIEW(t);
	fluidSolver->drawCube = DRAWCUBE(t);
	fluidSolver->opaScale = OPASCALE(t);
	fluidSolver->stepMul = STEPMUL(t);
	fluidSolver->displayRes = DISPLAYRES(t);


	fluidSolver->doShadows = DOSHADOWS(t);
	float lightPosX = LIGHTPOSX(t);
	float lightPosY = LIGHTPOSY(t);
	float lightPosZ = LIGHTPOSZ(t);
	fluidSolver->lightPos = cu::make_float3(lightPosX,lightPosY,lightPosZ);
	fluidSolver->shadowDens = SHADOWDENS(t);
	fluidSolver->shadowStepMul = SHADOWSTEPMUL(t);
	fluidSolver->shadowThres = SHADOWTHRES(t);

	fluidSolver->displaySlice = DISPLAYSLICE(t);
	fluidSolver->sliceType = SLICETYPE(t);
	fluidSolver->sliceAxis = SLICEAXIS(t);
	fluidSolver->slicePos = SLICEPOS(t);
	fluidSolver->sliceBounds = SLICEBOUNDS(t);


    if (error() < UT_ERROR_ABORT) {
		boss = UTgetInterrupt();

	gdp->clearAndDestroy();		

		// Start the interrupt server
		if (boss->opStart("Building Volume")){

			static float		 zero = 0.0;
			GB_AttributeRef fluidAtt = gdp->addAttrib("cudaFluid3DPreview", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(fluidAtt, fluidSolver->preview);

			GB_AttributeRef fluidSliceAtt = gdp->addAttrib("sliceDisplay", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(fluidSliceAtt, fluidSolver->displaySlice);

			GB_AttributeRef solverIdAtt = gdp->addAttrib("solverId", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(solverIdAtt, fluidSolver->id);

			GEO_AttributeHandle         name_gah;
			int	def = -1;

			gdp->addPrimAttrib("name", sizeof(int), GB_ATTRIB_INDEX, &def);
			name_gah = gdp->getPrimAttribute("name");


			UT_Matrix3              xform;
			const UT_XformOrder volXFormOrder;

			volume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);

			volume->getVertex().getPt()->getPos() = fluidPos;

			xform.identity();
			xform.scale(fluidSolver->fluidSize.x*0.5, fluidSolver->fluidSize.y*0.5, fluidSolver->fluidSize.z*0.5);
			xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder);

			volume->setTransform(xform);

			name_gah.setElement(volume);
			name_gah.setString("density");

			velXVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);
			velXVolume->getVertex().getPt()->getPos() = fluidPos;
			velXVolume->setTransform(xform);

			name_gah.setElement(velXVolume);
			name_gah.setString("vel.x");

			velYVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);
			velYVolume->getVertex().getPt()->getPos() = fluidPos;
			velYVolume->setTransform(xform);

			name_gah.setElement(velYVolume);
			name_gah.setString("vel.y");

			velZVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);
			velZVolume->getVertex().getPt()->getPos() = fluidPos;
			velZVolume->setTransform(xform);

			name_gah.setElement(velZVolume);
			name_gah.setString("vel.z");


			xform.identity();
			xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder);
			xform.invert();

			if(lockInputs(context) >= UT_ERROR_ABORT)
				return error();

			if(getInput(0)){
				GU_Detail* emittersInput = (GU_Detail*)inputGeo(0, context);
				GEO_PointList emittersList = emittersInput->points();
				int numEmitters = emittersList.entries();

				if (numEmitters != fluidSolver->nEmit) {
					delete fluidSolver->emitters;
					fluidSolver->nEmit = numEmitters;
					fluidSolver->emitters = new VHFluidEmitter[numEmitters];
				}

				GEO_AttributeHandle radAh, amountAh;
				radAh = emittersInput->getPointAttribute("radius");
				amountAh = emittersInput->getPointAttribute("amount");

				for (int i = 0; i < numEmitters; i++) {

					UT_Vector4 emitPos = emittersList[i]->getPos();
					UT_Vector3 emitPos3(emitPos);

					emitPos3 -= fluidPos;
					emitPos3 = emitPos3*xform;

					fluidSolver->emitters[i].posX = emitPos3.x();
					fluidSolver->emitters[i].posY = emitPos3.y();
					fluidSolver->emitters[i].posZ = emitPos3.z();

					radAh.setElement(emittersList[i]);
					amountAh.setElement(emittersList[i]);

					fluidSolver->emitters[i].radius = radAh.getF(0);
					fluidSolver->emitters[i].amount = amountAh.getF(0);
				}
			} else {

				fluidSolver->nEmit = 0;

			}
		

			if(getInput(1)) {
				GU_Detail* collidersInput = (GU_Detail*)inputGeo(1, context);
		
				GEO_PointList collidersList = collidersInput->points();
				int numColliders = collidersList.entries();

				if (numColliders != fluidSolver->nColliders) {
					delete fluidSolver->colliders;
					fluidSolver->nColliders = numColliders;
					fluidSolver->colliders = new VHFluidCollider[numColliders];
				}

				GEO_AttributeHandle colRadAh;
				colRadAh = collidersInput->getPointAttribute("radius");

				for (int i = 0; i < numColliders; i++) {

					UT_Vector4 colPos = collidersList[i]->getPos();
					UT_Vector3 colPos3(colPos);

					colPos3 -= fluidPos;
					colPos3 = colPos3*xform;

					if (f > STARTFRAME(t)) {
						fluidSolver->colliders[i].oldPosX = fluidSolver->colliders[i].posX;
						fluidSolver->colliders[i].oldPosY = fluidSolver->colliders[i].posY;
						fluidSolver->colliders[i].oldPosZ = fluidSolver->colliders[i].posZ;
					} else {
						fluidSolver->colliders[i].oldPosX = colPos3.x();
						fluidSolver->colliders[i].oldPosY = colPos3.y();
						fluidSolver->colliders[i].oldPosZ = colPos3.z();
					}

					fluidSolver->colliders[i].posX = colPos3.x();
					fluidSolver->colliders[i].posY = colPos3.y();
					fluidSolver->colliders[i].posZ = colPos3.z();

					colRadAh.setElement(collidersList[i]);

					fluidSolver->colliders[i].radius = colRadAh.getF(0);
				}

			} else {
				fluidSolver->nColliders = 0;
			}

			unlockInputs();

			if (f <= STARTFRAME(t)) {

				fluidSolver->resetFluid();

				if (COPYDENS(t)) {

					{
						UT_VoxelArrayWriteHandleF	handle = volume->getVoxelWriteHandle();
						handle->constant(0);

						UT_VoxelArrayWriteHandleF	velXHandle = velXVolume->getVoxelWriteHandle();
						velXHandle->constant(0);
						UT_VoxelArrayWriteHandleF	velYHandle = velYVolume->getVoxelWriteHandle();
						velYHandle->constant(0);
						UT_VoxelArrayWriteHandleF	velZHandle = velZVolume->getVoxelWriteHandle();
						velZHandle->constant(0);
					}

				}


			} else {

				if (f!=oldf) {

					fluidSolver->solveFluid();

				}

				if (COPYDENS(t)) {

					cu::cudaMemcpy( fluidSolver->host_dens, fluidSolver->dev_dens,
					fluidSolver->res.width*fluidSolver->res.height*fluidSolver->res.depth*sizeof(float), cu::cudaMemcpyDeviceToHost );

					{
						UT_VoxelArrayWriteHandleF	handle = volume->getVoxelWriteHandle();

						handle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth);

						for (int i = 0; i < fluidSolver->res.width; i++) {
							for (int j = 0; j < fluidSolver->res.height; j++) {
								for (int k = 0; k < fluidSolver->res.depth; k++) {
									handle->setValue(i, j, k, fluidSolver->host_dens[k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i]);
								}
							}
						}
									

					}

					if (COPYVEL(t)) {

					cu::cudaMemcpy( fluidSolver->host_vel, fluidSolver->dev_vel,
						fluidSolver->res.width*fluidSolver->res.height*fluidSolver->res.depth*sizeof(cu::float4), cu::cudaMemcpyDeviceToHost );

					{
						UT_VoxelArrayWriteHandleF	velXHandle = velXVolume->getVoxelWriteHandle();
						velXHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth);
						UT_VoxelArrayWriteHandleF	velYHandle = velYVolume->getVoxelWriteHandle();
						velYHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth);
						UT_VoxelArrayWriteHandleF	velZHandle = velZVolume->getVoxelWriteHandle();
						velZHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth);

						
						for (int i = 0; i < fluidSolver->res.width; i++) {
							for (int j = 0; j < fluidSolver->res.height; j++) {
								for (int k = 0; k < fluidSolver->res.depth; k++) {
									velXHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)]);
									velYHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)+1]);
									velZHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)+2]);
								}
							}
						}
									

					}


					}

				}
			}


		select(GU_SPrimitive);
		}

		// Tell the interrupt server that we've completed. Must do this
		// regardless of what opStart() returns.
		boss->opEnd();
    }

    gdp->notifyCache(GU_CACHE_ALL);

 
    return error();
}