Example #1
0
void BlobMesh::BuildMesh(TimeValue t)
{

	//TODO: Implement the code to build the mesh representation of the object
	//    using its parameter settings at the time passed. The plug-in should 
	//    use the data member mesh to store the built mesh.
	int numberOfNodes = pblock2->Count(pb_nodelist);

	float size, tension, renderCoarseness, viewCoarseness,coarseness;

	// Interval valid;
	pblock2->GetValue(pb_size,t,size,ivalid);
	pblock2->GetValue(pb_tension,t,tension,ivalid);
	if (tension < 0.011f) tension = 0.011f;
	if (tension > 1.0f) tension = 1.0f;

	pblock2->GetValue(pb_render,t,renderCoarseness,ivalid);
	pblock2->GetValue(pb_viewport,t,viewCoarseness,ivalid);

	BOOL autoCoarseness;
	pblock2->GetValue(pb_relativecoarseness,t,autoCoarseness,ivalid);

	BOOL largeDataSetOpt;
	pblock2->GetValue(pb_oldmetaballmethod,t,largeDataSetOpt,ivalid);


	BOOL useSoftSel;
	float minSize;
	pblock2->GetValue(pb_usesoftsel,t,useSoftSel,ivalid);
	pblock2->GetValue(pb_minsize,t,minSize,ivalid);

	if (inRender)
		coarseness = renderCoarseness;
	else coarseness = viewCoarseness;

	if (autoCoarseness)
		coarseness = size/coarseness;

	Tab<INode *> pfList;

	BOOL useAllPFEvents;
	pblock2->GetValue(pb_useallpf,0,useAllPFEvents,FOREVER);



	int pfCt = pblock2->Count(pb_pfeventlist);

	BOOL offInView;
	pblock2->GetValue(pb_offinview,0,offInView,FOREVER);



	for (int i = 0; i < pfCt; i++)
	{
		INode* node = NULL;
		pblock2->GetValue(pb_pfeventlist,0,node,FOREVER,i);
		if (node)
			pfList.Append(1,&node);
	}

	float thres = 0.6f;

	//need to get our tm
	if (selfNode == NULL)
	{
		MyEnumProc dep(true);
		DoEnumDependents(&dep);
		if (dep.Nodes.Count() > 0)
			selfNode = dep.Nodes[0];
	}

	Matrix3 baseTM(1);

	if (selfNode != NULL)
		baseTM = Inverse(selfNode->GetObjectTM(t));
	//loop throght the nodes

	if (!inRender)
	{
		if (offInView)
			numberOfNodes = 0;

	}

	std::vector<SphereData> data;
	data.reserve(500);

	for (int i = 0; i < numberOfNodes; i++)
	{
		INode* node = NULL;
		pblock2->GetValue(pb_nodelist,t,node,ivalid,i);

		if (node)
		{
			//get the nodes tm
			Matrix3 objectTM = node->GetObjectTM(t);
			Matrix3 toLocalSpace = objectTM*baseTM;

			ObjectState tos =  node->EvalWorldState(t,TRUE);

			if (tos.obj->IsParticleSystem())
			{
				SimpleParticle* pobj      = NULL;
				IParticleObjectExt* epobj = NULL;
				pobj = static_cast<SimpleParticle*>( tos.obj->GetInterface(I_SIMPLEPARTICLEOBJ) );
				if (pobj)
				{
					pobj->UpdateParticles(t, node);

					int count = pobj->parts.Count();
					data.reserve(data.size() + count);
					float closest = 999999999.9f;
					SphereData d;
					for (int pid = 0; pid < count; pid++)
					{
						TimeValue age  = pobj->ParticleAge(t,pid);
						TimeValue life = pobj->ParticleLife(t,pid);
						if (age != -1)
						{
							float psize = pobj->ParticleSize(t,pid);
							Point3 curval = pobj->parts.points[pid];
							d.center = curval * baseTM;
							d.radius = psize;
							d.oradius = psize;
							d.rsquare = psize * psize;
							d.tover4 = tension * d.rsquare *d.rsquare ;
							data.push_back(d);
						}
					}
				}
				else
				{
					epobj = (IParticleObjectExt*) tos.obj->GetInterface(PARTICLEOBJECTEXT_INTERFACE);
					if (epobj) 
					{
						
						epobj->UpdateParticles(node, t);

						int count = epobj->NumParticles();
						data.reserve(data.size() + count);
						for (int pid = 0; pid < count; pid++)
						{
							TimeValue age  = epobj->GetParticleAgeByIndex(pid);
							if (age!=-1)
							{
								INode *node = epobj->GetParticleGroup(pid);

								Point3 *curval = epobj->GetParticlePositionByIndex(pid);

								BOOL useParticle = TRUE;

								if (!useAllPFEvents)
								{
									useParticle = FALSE;
									for (int k = 0; k < pfList.Count(); k++)
									{
										if (node == pfList[k])
										{
											useParticle = TRUE;
											k = pfList.Count();
										}
									}
								}

								if ((curval) && (useParticle))
								{
									float scale = epobj->GetParticleScaleByIndex(pid) ;
									float psize = scale;

									SphereData d;
									d.center = *curval*baseTM;
									d.radius = psize;
									d.oradius = psize;
									d.rsquare = psize * psize;
									d.tover4 = tension * d.rsquare *d.rsquare ;
									data.push_back(d);
								}
							}
						}
					}

				}
			}
			else if (tos.obj->IsShapeObject()) 
			{
				PolyShape shape;

				ShapeObject *pathOb = (ShapeObject*)tos.obj;
				pathOb->MakePolyShape(t, shape);
				
				// first find out how many points there are:
				size_t num_points = 0;
				for (int i = 0; i < shape.numLines; i++)
				{
					PolyLine& line = shape.lines[i];
					num_points += line.numPts;
				}
				data.reserve(data.size() + num_points);

				for (int i = 0; i < shape.numLines; i++)
				{
					PolyLine line = shape.lines[i];
					for (int j = 0; j < line.numPts; j++)
					{
						SphereData d;
						float tsize = size;
						d.center = line.pts[j].p*toLocalSpace;
						d.radius = tsize;
						d.oradius = tsize;
						d.rsquare = tsize * tsize;
						d.tover4 = tension * d.rsquare *d.rsquare ;
						data.push_back(d);
					}
				}
			}
			else if (tos.obj->SuperClassID()==GEOMOBJECT_CLASS_ID)
			{
				SphereData d;
				BOOL converted = FALSE;

				TriObject *triObj = NULL;


				if(tos.obj->IsSubClassOf(triObjectClassID)) 
				{
					triObj = (TriObject *)tos.obj;
				}

				// If it can convert to a TriObject, do it
				else if(tos.obj->CanConvertToType(triObjectClassID)) 
				{
					triObj = (TriObject *)tos.obj->ConvertToType(t, triObjectClassID);
					converted = TRUE;
				}

				if (triObj != NULL)
				{
					Mesh* mesh = &triObj->GetMesh();
					if (mesh)
					{
						int vcount = mesh->getNumVerts();
						float *vsw = mesh->getVSelectionWeights ();
						BitArray vsel =  mesh->VertSel();
						data.reserve(data.size() + vcount);
						for (int j = 0; j < vcount; j++)
						{
							float tsize = size;
							if (useSoftSel)
							{
								tsize = 0.0f;
								if (vsw)
								{
									float v = 0.0f;
									if (vsel[j]) 
										v = 1.0f;
									else 
									{
										if (vsw)
											v = vsw[j];
									}
									if (v == 0.0f)
										tsize = 0.0f;
									else
									{
										tsize = minSize + (size -minSize)*v;
									}

								}
								else
								{
									float v = 0.0f;
									if (vsel[j]) 
										v = 1.0f;
									tsize = minSize + (size -minSize)*v;
								}
							}
							if (tsize != 0.0f)
							{
								d.center = mesh->getVert(j)*toLocalSpace;
								d.radius = tsize;
								d.oradius = tsize;
								d.rsquare = tsize * tsize;
								d.tover4 = tension * d.rsquare *d.rsquare ;
								data.push_back(d);
							}
						}
					}

					if (converted) triObj->DeleteThis();
				}
			}
			else
			{
				SphereData d;
				d.center = Point3(0.0f,0.0f,0.0f)*toLocalSpace;
				d.radius = size;
				d.oradius = size;
				d.rsquare = size * size;
				d.tover4 = tension * d.rsquare *d.rsquare ;
				data.push_back(d);
			}
		}
	}


	if ((data.size() == 0) && (numberOfNodes==0))
	{
		data.resize(1);
		data[0].center = Point3(0.0f,0.0f,0.0f);
		data[0].radius = size;
		data[0].oradius = size;
		data[0].rsquare = size * size;
		data[0].tover4 = tension * data[0].rsquare *data[0].rsquare ;

	}

	if (data.size() > 0)
	{
		int iRes = 1;
		if (!largeDataSetOpt)
		{
			MetaParticle oldBlob;
			iRes = oldBlob.CreatePodMetas(&data[0],(int)data.size(),&mesh,thres,coarseness);
		}
		else
		{
			MetaParticleFast blob;
			iRes = blob.CreatePodMetas(&data[0],(int)data.size(),&mesh,thres,coarseness);
		}

		// An out of memory error is the only reason iRes would be zero in either case
		if( (iRes == 0) && GetCOREInterface() )
			GetCOREInterface()->DisplayTempPrompt(GetString(IDS_NOT_ENOUGH_MEM), 5000 );
	}
	else
	{
		mesh.setNumFaces(0);
		mesh.setNumVerts(0);
	}

	mesh.InvalidateTopologyCache();

	ivalid.Set(t,t);
}