Пример #1
0
BOOL plDistributor::IConformCheck(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const
{
    Matrix3 OTM = IOTM(iRepNode);
    Mesh* mesh = cache[iRepNode].fMesh;

    Point3 dir = l2w.VectorTransform(Point3(0.f, 0.f, 1.f));
    dir = FNormalize(dir);

    const float kOneOverSqrt2 = 0.707107f;
    Point3 scalePt(kOneOverSqrt2, kOneOverSqrt2, 0.f);
    scalePt = l2w.VectorTransform(scalePt);
    float maxScaledDist = fMaxConform * scalePt.Length();

    Box3 bnd = mesh->getBoundingBox() * OTM;
    bnd = Box3(Point3(bnd.Min().x, bnd.Min().y, -bnd.Max().z), bnd.Max());
    bnd = bnd * l2w;
    Tab<int32_t> faces;
    IFindFaceSet(bnd, faces);

    int i;
    for( i = 0; i < mesh->getNumVerts(); i++ )
    {
        Point3 pt = mesh->getVert(i) * OTM;
        pt.z = 0;

        pt = pt * l2w;

        Point3 projPt;
        if( !IProjectVertex(pt, dir, maxScaledDist, faces, projPt) )
            return false;
    }
    return true;
}
Пример #2
0
void bhkProxyObject::BuildColBox()
{
	Box3 box; box.Init();
	for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) {
		INode *tnode = NULL;
		pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);	
		if (tnode)
		{
			ObjectState os = tnode->EvalWorldState(0);
			Matrix3 wm = tnode->GetNodeTM(0);
			TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));
			if (tri)
			{
				Box3 box2; box2.Init();
				Mesh& mesh = tri->GetMesh();
				CalcAxisAlignedBox(mesh, box2, &wm);
				box += box2;
			}
		}
	}
	BuildBox(proxyMesh, box.Max().y-box.Min().y, box.Max().x-box.Min().x, box.Max().z-box.Min().z);

	MNMesh mn(proxyMesh);
	Matrix3 tm(true);
	tm.SetTranslate(box.Center());
	mn.Transform(tm);
	mn.OutToTri(proxyMesh);

	//proxyPos = box.Center();
	proxyPos = Point3::Origin;
	forceRedraw = true;
}
Пример #3
0
BOOL plDistributor::IConformAll(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const
{
    Matrix3 OTM = IOTM(iRepNode);
    Mesh* mesh = cache[iRepNode].fMesh;

    Point3 dir = l2w.VectorTransform(Point3(0.f, 0.f, 1.f));
    dir = FNormalize(dir);

    const float kOneOverSqrt2 = 0.707107f;
    Point3 scalePt(kOneOverSqrt2, kOneOverSqrt2, 0.f);
    scalePt = l2w.VectorTransform(scalePt);
    float maxScaledDist = fMaxConform * scalePt.Length();

    Box3 bnd = mesh->getBoundingBox() * OTM;
    bnd = Box3(Point3(bnd.Min().x, bnd.Min().y, -bnd.Max().z), bnd.Max());
    bnd = bnd * l2w;
    Tab<int32_t> faces;
    IFindFaceSet(bnd, faces);

    // l2w, iRepNode, cache, &iCache, maxScaledDist, dir
    iCache = cache.Count();
    cache.SetCount(iCache + 1);
    cache[iCache] = cache[iRepNode];
    cache[iCache].fMesh = new Mesh(*mesh);

    mesh = cache[iCache].fMesh;

    Matrix3 v2w = OTM * l2w;
    Matrix3 w2v = Inverse(v2w);

    BOOL retVal = true;
    int i;
    for( i = 0; i < mesh->getNumVerts(); i++ )
    {
        Point3 pt = mesh->getVert(i) * OTM;
        pt.z = 0;

        pt = pt * l2w;

        Point3 projPt;
        if( !IProjectVertex(pt, dir, maxScaledDist, faces, projPt) )
        {
            retVal = false;
            break;
        }

        Point3 del = w2v.VectorTransform(projPt - pt);
        mesh->getVert(i) += del;
    }
    if( !retVal )
    {
//      delete cache[iCache].fMesh;
        delete mesh;
        cache.SetCount(iCache);
        iCache = iRepNode;
    }
    return retVal;
}
Пример #4
0
/// positive in, negative out
static inline bool isPointInBoxBias(const Box3& box, const double3& point)
{
    if (point.x > box.Max().x) return false;
    if (point.y > box.Max().y) return false;
    if (point.z > box.Max().z) return false;

    if (point.x <= box.Min().x) return false;
    if (point.y <= box.Min().y) return false;
    if (point.z <= box.Min().z) return false;

    return true;
}
void bhkRigidBodyModifier::BuildColBox(Mesh& mesh)
{
	Box3 box; box.Init();
	CalcAxisAlignedBox(mesh, box, NULL);
	BuildBox(mesh, box.Max().y-box.Min().y, box.Max().x-box.Min().x, box.Max().z-box.Min().z);

	MNMesh mn(mesh);
	Matrix3 tm(true);
	tm.Translate(box.Center());
	mn.Transform(tm);
	mn.OutToTri(mesh);
}
Пример #6
0
static void MakeDummyMesh(plMaxNode* node, plMaxMeshExtractor::NeutralMesh& mesh)
{
    hsPoint3 minV, maxV;

    Object* thisObj = node->GetObjectRef();
    DummyObject* thisDummy = (DummyObject*)thisObj;
    Box3 thisBoundSurface = thisDummy->GetBox();
    minV.fX = thisBoundSurface.Min().x;
    minV.fY = thisBoundSurface.Min().y;
    minV.fZ = thisBoundSurface.Min().z;
    maxV.fX = thisBoundSurface.Max().x;
    maxV.fY = thisBoundSurface.Max().y;
    maxV.fZ = thisBoundSurface.Max().z;

    MakeBoxMesh(node, mesh, minV, maxV);
}
Пример #7
0
plLayerInterface* plLayerConverter::IConvertAngleAttenLayer(plPlasmaMAXLayer *layer, 
                                                                plMaxNode *maxNode, uint32_t blendFlags, 
                                                                bool preserveUVOffset, bool upperLayer)
{
    hsGuardBegin( "plPlasmaMAXLayer::IConvertAngleAttenLayer" );
    if( !upperLayer )
    {
        fErrorMsg->Set(true, maxNode->GetName(), "Angle Attenuation layers can only be used as a top layer").Show();
        fErrorMsg->Set();
        return nil;
    }
    plAngleAttenLayer* aaLay = (plAngleAttenLayer*)layer;
    Box3 fade = aaLay->GetFade();
    float tr0 = cosf(DegToRad(180.f - fade.Min().x));
    float op0 = cosf(DegToRad(180.f - fade.Min().y));
    float tr1 = cosf(DegToRad(180.f - fade.Max().x));
    float op1 = cosf(DegToRad(180.f - fade.Max().y));

    int loClamp = aaLay->GetLoClamp();
    int hiClamp = aaLay->GetHiClamp();

    int uvwSrc = aaLay->Reflect() ? plLayerInterface::kUVWReflect : plLayerInterface::kUVWNormal;

    plLayer* lut = ICreateAttenuationLayer(plString::FromUtf8(layer->GetName()), maxNode, uvwSrc, tr0, op0, tr1, op1, loClamp, hiClamp);

    return lut;

    hsGuardEnd;
}
Пример #8
0
static inline void normalizeBox3(const Box3& target, const Box3& env, Box3& output)
{
    auto scale = env.Diagonal();
    auto center = env.Center();
    
    output.Set((target.Min()-center)/scale*2.0, 
        (target.Max()-center)/scale*2.0);
}
Пример #9
0
static inline void staticFilter(Box3& box, double factor)
{
    double3 minimum(box.Min());
    double3 maximum(box.Max());

    minimum.x = staticFilter(minimum.x, factor);
    minimum.y = staticFilter(minimum.y, factor);
    minimum.z = staticFilter(minimum.z, factor);

    maximum.x = staticFilter(maximum.x, factor);
    maximum.y = staticFilter(maximum.y, factor);
    maximum.z = staticFilter(maximum.z, factor);
}
Пример #10
0
BOOL plDistributor::ISetupSkinWeights(plMaxNode* node, Mesh* mesh, const Point3& flex) const
{
    const char* dbgNodeName = node->GetName();

    Matrix3 otm = node->GetOTM();

    Box3 bnd = mesh->getBoundingBox() * otm;

    float meshHeight = bnd.Max().z;
    float maxHeight = kMaxHeight;
    if( meshHeight > maxHeight )
        maxHeight = meshHeight;
    float maxNorm = meshHeight / maxHeight;

    float flexibility = flex[0];

    UVVert *wgtMap = mesh->mapVerts(kWgtMapChan);   
    int numWgtVerts = mesh->getNumMapVerts(kWgtMapChan);
    if( !mesh->mapSupport(kWgtMapChan) || !mesh->mapVerts(kWgtMapChan) || !mesh->mapFaces(kWgtMapChan) )
    {
        mesh->setMapSupport(kWgtMapChan);

        mesh->setNumMapVerts(kWgtMapChan, mesh->getNumVerts());
        mesh->setNumMapFaces(kWgtMapChan, mesh->getNumFaces());
    }

    int i;
    for( i = 0; i < mesh->getNumVerts(); i++ )
    {
        Point3 pos = mesh->getVert(i) * otm;
        float wgt = pos.z / meshHeight;
        wgt *= wgt > 0 ? wgt : 0;
        wgt *= maxNorm;
        wgt *= flexibility;

        pos.x = wgt;
        pos.y = wgt;
        pos.z = wgt;

        mesh->setMapVert(kWgtMapChan, i, pos);
    }

    TVFace* mapFaces = mesh->mapFaces(kWgtMapChan);
    Face* faces = mesh->faces;
    for( i = 0; i < mesh->getNumFaces(); i++ )
    {
        mapFaces[i].setTVerts(faces[i].getVert(0), faces[i].getVert(1), faces[i].getVert(2));
    }

    return true;
}
Пример #11
0
void Exporter::CalcBoundingBox(INode *node, Box3& box, int all)
{
	if (nullptr == node)
		return;

	Matrix3 tm = node->GetObjTMAfterWSM(0);
	if (node->IsBoneShowing()) {
		box.IncludePoints(const_cast<Point3*>(&tm.GetTrans()), 1, nullptr);
	}
	else {
		if (Object *o = node->GetObjectRef()) {
			if (o->SuperClassID() == GEOMOBJECT_CLASS_ID) {
				if (o->ClassID() == BONE_OBJ_CLASSID
					|| o->ClassID() == Class_ID(BONE_CLASS_ID, 0)
					|| o->ClassID() == Class_ID(0x00009125, 0) /* Biped Twist Helpers */
					)
				{
					box.IncludePoints(const_cast<Point3*>(&tm.GetTrans()), 1, nullptr);
				}
				else
				{
					Box3 local;
#if VERSION_3DSMAX < (15000<<16) // Version 15 (2013)
					o->GetLocalBoundBox(0, node, mI->GetActiveViewport(), local);
#else
					o->GetLocalBoundBox(0, node, &mI->GetActiveViewExp(), local);
#endif
					box.IncludePoints(&local.Min(), 1, nullptr);
					box.IncludePoints(&local.Max(), 1, nullptr);
				}
			}
			else if (mExportCameras && o->SuperClassID() == CAMERA_CLASS_ID)
			{
				box.IncludePoints(const_cast<Point3*>(&tm.GetTrans()), 1, nullptr);
			}
		}
	}
	if (all < 0)
		return;

	all = (all>0 ? all : -1);
	for (int i = 0; i < node->NumberOfChildren(); i++) {
		CalcBoundingBox(node->GetChildNode(i), box, all);
	}
}
Пример #12
0
void BSPOctree::SplitSpaceByXYZ(const Box3& bbox,  Box3 childBoxes[])
{
    vec3<float> minOffset, maxOffset;
    const double factor = pow(2.0, 11);
    double3 step = double3(
        staticFilter(bbox.Diagonal().x* 0.5, factor)
        , staticFilter(bbox.Diagonal().y*0.5, factor)
        ,  staticFilter(bbox.Diagonal().z*0.5, factor));

    for (int i = 0; i < 8 ; i++)
    {
        maxOffset.z = i & 1 ?  0 : -step.z; 
        maxOffset.y = i & 2 ?  0 : -step.y;
        maxOffset.x = i & 4 ?  0 : -step.x;
        minOffset.z = i & 1 ?  step.z : 0; 
        minOffset.y = i & 2 ?  step.y : 0;
        minOffset.x = i & 4 ?  step.x : 0;
        childBoxes[i].Set(bbox.Min() + minOffset, bbox.Max()+ maxOffset);
    }
}
BOOL plDistribComponent_old::IValidateFade(Box3& fade)
{
    BOOL retVal = true;
    fade = GetFade();

    if( fCompPB->GetInt(kFadeInActive) )
    {
        if( fade.Max()[0] < fade.Max()[1] )
        {
            if( fade.Min()[0] > fade.Max()[0] )
            {
                fade.pmin[0] = fade.Max()[0];
                retVal = false;
            }

            if( fade.Min()[1] > fade.Min()[0] )
            {
                fade.pmin[1] = fade.Min()[0];
                retVal = false;
            }
        }
        else if( fade.Max()[0] > fade.Max()[1] )
        {
            if( fade.Min()[1] > fade.Max()[1] )
            {
                fade.pmin[1] = fade.Max()[1];
                retVal = false;
            }

            if( fade.Min()[0] > fade.Min()[1] )
            {
                fade.pmin[0] = fade.Min()[1];
                retVal = false;
            }
        }
    }
    return retVal;
}
Пример #14
0
int Blockporter::DoExport(const TCHAR* name, ExpInterface* ei, Interface* i, BOOL supressPrompts, DWORD options)
{
	INode* root;
	//caption and message for MessagesBoxes
	TCHAR msg[MB_BUFFER_LENGTH];
	TCHAR cap[MB_BUFFER_LENGTH];

	//Get the root node
	root = i->GetRootNode();

	//the node of our object should be a groupnode, which contains every object
	//we want to export
	i->PushPrompt(_T("Searching for Group..."));
	bool found = false;
	for(int idx = 0; idx < root->NumberOfChildren(); idx++)
	{
		if(root->GetChildNode(idx)->IsGroupHead())
		{
			//we found our group
			//next step is to make the group node our new root, because every object
			//we want is part of this group

			found = true;
			root = root->GetChildNode(idx);
			break;
		}
	}

	if(!found)
	{
		MessageBox(nullptr, GetString(IDS_ERROR_NO_GROUP, msg), GetString(IDS_GENERAL_ERROR, cap), MB_OK | MB_ICONERROR);
		return 0;
	}

	//Now that we have the groupnode let's compare the fileversions
	if(!IsNewModelVersion(name, root->GetName()))
	{
		if(MessageBox(nullptr, GetString(IDS_VER_TO_LOW_MSG, msg), GetString(IDS_VER_TO_LOW_CAP, cap), MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
			return 1;
	}

	i->PushPrompt(_T("Opening File"));
	Interface14* iface = GetCOREInterface14();
	UINT code = iface->DefaultTextSaveCodePage(true);
	MaxSDK::Util::Path storageNamePath(name);
	storageNamePath.SaveBaseFile();
	switch (code & MaxSDK::Util::MaxStringDataEncoding::MSDE_CP_MASK)
	{
	case CP_UTF8:
		mStream = _tfopen(name, _T("wt, ccs=UFT-8"));
		break;
	case MaxSDK::Util::MaxStringDataEncoding::MSDE_CP_UTF16:
		mStream = _tfopen(name, _T("wt, ccs=UTF-16BE"));
		break;
	default:
		mStream = _tfopen(name, _T("wt"));
	}
	if(!mStream)
		return 0;

	//now we have our file stream, so let's write the header
	i->PushPrompt(_T("Writing Header"));
	WriteHeader(root->GetName(), root->NumberOfChildren());

	//now that we have the header written, let's iterate through the objects in the
	//group and export the meshes and lights

	INode* child;
    Point3 pMin(0,0,0), pMax(0,0,0);

	for(int idx = 0; idx < root->NumberOfChildren(); idx++)
	{
		child = root->GetChildNode(idx);
		i->PushPrompt(_T("Processing Object %s", child->GetName()));
		if(child->IsGroupHead())
		{
			MessageBox(nullptr, GetString(IDS_ERROR_TO_MANY_GROUPS, msg), GetString(IDS_GENERAL_ERROR, cap), MB_OK | MB_ICONERROR);
			continue;
		}

		ObjectState os = child->EvalWorldState(0);

		//let's take a look at the SuperClassID of the object
		//so we find out if it's a mesh or a light
		if(!os.obj)
			continue; //somehow this node doesn't have an object

        Box3 boundBox;

		switch(os.obj->SuperClassID())
		{
		case GEOMOBJECT_CLASS_ID:
			_ftprintf(mStream, _T("<ObjectID=%i>\n"), idx);
			i->PushPrompt(_T("Writing MeshData for Object %s", child->GetName()));
			boundBox = WriteMeshData(child, idx);
            pMin.x = (boundBox.Min().x < pMin.x) ? boundBox.Min().x : pMin.x;
            pMin.y = (boundBox.Min().y < pMin.y) ? boundBox.Min().y : pMin.y;
            pMax.x = (boundBox.Max().x > pMax.x) ? boundBox.Max().x : pMax.x;
            pMax.y = (boundBox.Max().y > pMax.y) ? boundBox.Max().y : pMax.y;
			i->PushPrompt(_T("Writing MaterialData for Object %s", child->GetName()));
			WriteMaterialData(child);
			_ftprintf(mStream, _T("</Object>\n"));
			break;
		//case LIGHT_CLASS_ID:
		//	WriteLightData(child, idx);
		//	break;
		}
	}

    //Write the Bounding Box
    _ftprintf(mStream, _T("<BoundingBox>\n"));
    _ftprintf(mStream, _T("\t<Min=%f,%f>\n"), pMin.x, pMin.y);
    _ftprintf(mStream, _T("\t<Max=%f,%f>\n"), pMax.x, pMax.y);
    _ftprintf(mStream, _T("</BoundingBox>\n"));
	//we are done exporting, so close the stream
	i->PushPrompt(_T("Closing file..."));
	fclose(mStream);

	MessageBox(nullptr, GetString(IDS_FINISH_MSG, msg), GetString(IDS_FINISH_CAP, cap), MB_OK | MB_ICONINFORMATION);

	return 1;
}
Пример #15
0
void LuminaireObject::BuildMesh()
{
	mesh.setNumVerts(120);
	mesh.setNumFaces(106);

	// aszabo|Feb.10.03|Compute scale of mesh. DummyObject::box has been scaled,
	// while our mDefBoxSize wasn't, but it was used to initialize the box.
	float s = box.Max().x/mDefBoxSize.Max().x;

	mesh.setVert(0, s*Point3(2.812824,-4.221277,0.000000));
	mesh.setVert(1, s*Point3(-2.731174,-4.221277,0.000000));
	mesh.setVert(2, s*Point3(-2.731174,-4.972452,0.000000));
	mesh.setVert(3, s*Point3(2.812824,-4.972452,0.000000));
	mesh.setVert(4, s*Point3(0.430951,-0.504076,0.000000));
	mesh.setVert(5, s*Point3(0.373688,-0.540217,0.000000));
	mesh.setVert(6, s*Point3(0.312884,-0.570737,0.000000));
	mesh.setVert(7, s*Point3(0.248868,-0.595212,0.000000));
	mesh.setVert(8, s*Point3(0.181967,-0.613220,0.000000));
	mesh.setVert(9, s*Point3(0.112510,-0.624335,0.000000));
	mesh.setVert(10, s*Point3(0.040825,-0.628134,0.000000));
	mesh.setVert(11, s*Point3(-0.030860,-0.624335,0.000000));
	mesh.setVert(12, s*Point3(-0.100318,-0.613220,0.000000));
	mesh.setVert(13, s*Point3(-0.167219,-0.595213,0.000000));
	mesh.setVert(14, s*Point3(-0.231235,-0.570737,0.000000));
	mesh.setVert(15, s*Point3(-0.292039,-0.540217,0.000000));
	mesh.setVert(16, s*Point3(-0.349302,-0.504076,0.000000));
	mesh.setVert(17, s*Point3(-0.402695,-0.462737,0.000000));
	mesh.setVert(18, s*Point3(-0.402695,-4.025318,0.000000));
	mesh.setVert(19, s*Point3(0.484345,-4.025318,0.000000));
	mesh.setVert(20, s*Point3(0.484345,-0.462738,0.000000));
	mesh.setVert(21, s*Point3(0.373465,-4.025318,0.000000));
	mesh.setVert(22, s*Point3(-0.291815,-4.025318,0.000000));
	mesh.setVert(23, s*Point3(-0.291815,-4.221277,0.000000));
	mesh.setVert(24, s*Point3(0.373465,-4.221277,0.000000));
	mesh.setVert(25, s*Point3(4.419012,5.754055,0.000000));
	mesh.setVert(26, s*Point3(2.964259,4.637785,0.000000));
	mesh.setVert(27, s*Point3(3.340581,4.051188,0.000000));
	mesh.setVert(28, s*Point3(3.598334,3.467271,0.000000));
	mesh.setVert(29, s*Point3(3.784944,2.884963,0.000000));
	mesh.setVert(30, s*Point3(3.947842,2.303191,0.000000));
	mesh.setVert(31, s*Point3(4.134453,1.720884,0.000000));
	mesh.setVert(32, s*Point3(4.392206,1.136967,0.000000));
	mesh.setVert(33, s*Point3(4.768528,0.550370,0.000000));
	mesh.setVert(34, s*Point3(7.900172,2.953366,0.000000));
	mesh.setVert(35, s*Point3(7.430962,3.468688,0.000000));
	mesh.setVert(36, s*Point3(6.933653,3.868786,0.000000));
	mesh.setVert(37, s*Point3(6.419484,4.199750,0.000000));
	mesh.setVert(38, s*Point3(5.899698,4.507671,0.000000));
	mesh.setVert(39, s*Point3(5.385530,4.838635,0.000000));
	mesh.setVert(40, s*Point3(4.888222,5.238734,0.000000));
	mesh.setVert(41, s*Point3(2.805657,2.557596,0.000000));
	mesh.setVert(42, s*Point3(2.664196,2.574949,0.000000));
	mesh.setVert(43, s*Point3(2.533501,2.619650,0.000000));
	mesh.setVert(44, s*Point3(2.416477,2.688673,0.000000));
	mesh.setVert(45, s*Point3(2.316031,2.778996,0.000000));
	mesh.setVert(46, s*Point3(2.235066,2.887594,0.000000));
	mesh.setVert(47, s*Point3(2.176486,3.011443,0.000000));
	mesh.setVert(48, s*Point3(2.143197,3.147520,0.000000));
	mesh.setVert(49, s*Point3(-0.028124,0.736024,0.000000));
	mesh.setVert(50, s*Point3(-0.018348,0.737188,0.000000));
	mesh.setVert(51, s*Point3(-0.008572,0.738606,0.000000));
	mesh.setVert(52, s*Point3(0.001220,0.740119,0.000000));
	mesh.setVert(53, s*Point3(0.011041,0.741571,0.000000));
	mesh.setVert(54, s*Point3(0.020906,0.742804,0.000000));
	mesh.setVert(55, s*Point3(0.030829,0.743659,0.000000));
	mesh.setVert(56, s*Point3(0.040825,0.743979,0.000000));
	mesh.setVert(57, s*Point3(0.174745,0.730856,0.000000));
	mesh.setVert(58, s*Point3(0.299803,0.693174,0.000000));
	mesh.setVert(59, s*Point3(0.413514,0.633459,0.000000));
	mesh.setVert(60, s*Point3(0.513398,0.554243,0.000000));
	mesh.setVert(61, s*Point3(0.596971,0.458053,0.000000));
	mesh.setVert(62, s*Point3(0.661752,0.347418,0.000000));
	mesh.setVert(63, s*Point3(0.705257,0.224866,0.000000));
	mesh.setVert(64, s*Point3(0.726882,0.057922,0.000000));
	mesh.setVert(65, s*Point3(0.708744,0.215121,0.000000));
	mesh.setVert(66, s*Point3(0.657090,0.359483,0.000000));
	mesh.setVert(67, s*Point3(0.576055,0.486872,0.000000));
	mesh.setVert(68, s*Point3(0.469775,0.593152,0.000000));
	mesh.setVert(69, s*Point3(0.342386,0.674188,0.000000));
	mesh.setVert(70, s*Point3(0.198024,0.725842,0.000000));
	mesh.setVert(71, s*Point3(0.040825,0.743979,0.000000));
	mesh.setVert(72, s*Point3(-0.116374,0.725842,0.000000));
	mesh.setVert(73, s*Point3(-0.260736,0.674188,0.000000));
	mesh.setVert(74, s*Point3(-0.388125,0.593152,0.000000));
	mesh.setVert(75, s*Point3(-0.494405,0.486872,0.000000));
	mesh.setVert(76, s*Point3(-0.575440,0.359483,0.000000));
	mesh.setVert(77, s*Point3(-0.627095,0.215121,0.000000));
	mesh.setVert(78, s*Point3(-0.645232,0.057922,0.000000));
	mesh.setVert(79, s*Point3(-0.627095,-0.099276,0.000000));
	mesh.setVert(80, s*Point3(-0.575440,-0.243638,0.000000));
	mesh.setVert(81, s*Point3(-0.494405,-0.371027,0.000000));
	mesh.setVert(82, s*Point3(-0.388125,-0.477308,0.000000));
	mesh.setVert(83, s*Point3(-0.260736,-0.558343,0.000000));
	mesh.setVert(84, s*Point3(-0.116374,-0.609997,0.000000));
	mesh.setVert(85, s*Point3(0.040825,-0.628134,0.000000));
	mesh.setVert(86, s*Point3(0.198024,-0.609997,0.000000));
	mesh.setVert(87, s*Point3(0.342386,-0.558343,0.000000));
	mesh.setVert(88, s*Point3(0.469775,-0.477308,0.000000));
	mesh.setVert(89, s*Point3(0.576055,-0.371027,0.000000));
	mesh.setVert(90, s*Point3(0.657090,-0.243638,0.000000));
	mesh.setVert(91, s*Point3(0.708744,-0.099276,0.000000));
	mesh.setVert(92, s*Point3(3.504380,3.242251,0.000000));
	mesh.setVert(93, s*Point3(3.486243,3.399450,0.000000));
	mesh.setVert(94, s*Point3(3.434589,3.543813,0.000000));
	mesh.setVert(95, s*Point3(3.353553,3.671200,0.000000));
	mesh.setVert(96, s*Point3(3.247273,3.777481,0.000000));
	mesh.setVert(97, s*Point3(3.119884,3.858516,0.000000));
	mesh.setVert(98, s*Point3(2.975523,3.910170,0.000000));
	mesh.setVert(99, s*Point3(2.818324,3.928308,0.000000));
	mesh.setVert(100, s*Point3(2.661125,3.910171,0.000000));
	mesh.setVert(101, s*Point3(2.516763,3.858516,0.000000));
	mesh.setVert(102, s*Point3(2.389374,3.777481,0.000000));
	mesh.setVert(103, s*Point3(2.283094,3.671201,0.000000));
	mesh.setVert(104, s*Point3(2.202058,3.543812,0.000000));
	mesh.setVert(105, s*Point3(2.150404,3.399450,0.000000));
	mesh.setVert(106, s*Point3(2.132267,3.242251,0.000000));
	mesh.setVert(107, s*Point3(2.150404,3.085053,0.000000));
	mesh.setVert(108, s*Point3(2.202059,2.940691,0.000000));
	mesh.setVert(109, s*Point3(2.283093,2.813301,0.000000));
	mesh.setVert(110, s*Point3(2.389374,2.707022,0.000000));
	mesh.setVert(111, s*Point3(2.516763,2.625986,0.000000));
	mesh.setVert(112, s*Point3(2.661125,2.574332,0.000000));
	mesh.setVert(113, s*Point3(2.818324,2.556195,0.000000));
	mesh.setVert(114, s*Point3(2.975523,2.574332,0.000000));
	mesh.setVert(115, s*Point3(3.119885,2.625987,0.000000));
	mesh.setVert(116, s*Point3(3.247273,2.707021,0.000000));
	mesh.setVert(117, s*Point3(3.353554,2.813302,0.000000));
	mesh.setVert(118, s*Point3(3.434589,2.940691,0.000000));
	mesh.setVert(119, s*Point3(3.486243,3.085052,0.000000));
	Face f;

	f.v[0] = 2;  f.v[1] = 3;  f.v[2] = 0;  	f.smGroup = 1;  f.flags = 67; mesh.faces[0] = f; 
	f.v[0] = 2;  f.v[1] = 0;  f.v[2] = 1;  	f.smGroup = 1;  f.flags = 70; mesh.faces[1] = f;
	f.v[0] = 16;  f.v[1] = 17;  f.v[2] = 18;  	f.smGroup = 1;  f.flags = 67; mesh.faces[2] = f;
	f.v[0] = 19;  f.v[1] = 20;  f.v[2] = 4;  	f.smGroup = 1;  f.flags = 67; mesh.faces[3] = f;
	f.v[0] = 15;  f.v[1] = 16;  f.v[2] = 18;  	f.smGroup = 1;  f.flags = 65; mesh.faces[4] = f;
	f.v[0] = 19;  f.v[1] = 4;  f.v[2] = 5;  	f.smGroup = 1;  f.flags = 66; mesh.faces[5] = f;
	f.v[0] = 19;  f.v[1] = 5;  f.v[2] = 6;  	f.smGroup = 1;  f.flags = 66; mesh.faces[6] = f;
	f.v[0] = 14;  f.v[1] = 15;  f.v[2] = 18;  	f.smGroup = 1;  f.flags = 65; mesh.faces[7] = f;
	f.v[0] = 13;  f.v[1] = 14;  f.v[2] = 18;  	f.smGroup = 1;  f.flags = 65; mesh.faces[8] = f;
	f.v[0] = 19;  f.v[1] = 6;  f.v[2] = 7;  	f.smGroup = 1;  f.flags = 66; mesh.faces[9] = f;
	f.v[0] = 19;  f.v[1] = 7;  f.v[2] = 8;  	f.smGroup = 1;  f.flags = 66; mesh.faces[10] = f;
	f.v[0] = 12;  f.v[1] = 13;  f.v[2] = 18;  	f.smGroup = 1;  f.flags = 65; mesh.faces[11] = f;
	f.v[0] = 18;  f.v[1] = 19;  f.v[2] = 8;  	f.smGroup = 1;  f.flags = 65; mesh.faces[12] = f;
	f.v[0] = 18;  f.v[1] = 8;  f.v[2] = 9;  	f.smGroup = 1;  f.flags = 66; mesh.faces[13] = f;
	f.v[0] = 18;  f.v[1] = 9;  f.v[2] = 10;  	f.smGroup = 1;  f.flags = 66; mesh.faces[14] = f;
	f.v[0] = 18;  f.v[1] = 10;  f.v[2] = 11;  	f.smGroup = 1;  f.flags = 66; mesh.faces[15] = f;
	f.v[0] = 12;  f.v[1] = 18;  f.v[2] = 11;  	f.smGroup = 1;  f.flags = 68; mesh.faces[16] = f;
	f.v[0] = 23;  f.v[1] = 24;  f.v[2] = 21;  	f.smGroup = 1;  f.flags = 67; mesh.faces[17] = f;
	f.v[0] = 23;  f.v[1] = 21;  f.v[2] = 22;  	f.smGroup = 1;  f.flags = 70; mesh.faces[18] = f;
	f.v[0] = 32;  f.v[1] = 33;  f.v[2] = 34;  	f.smGroup = 1;  f.flags = 67; mesh.faces[19] = f;
	f.v[0] = 32;  f.v[1] = 34;  f.v[2] = 35;  	f.smGroup = 1;  f.flags = 66; mesh.faces[20] = f;
	f.v[0] = 32;  f.v[1] = 35;  f.v[2] = 36;  	f.smGroup = 1;  f.flags = 66; mesh.faces[21] = f;
	f.v[0] = 31;  f.v[1] = 32;  f.v[2] = 36;  	f.smGroup = 1;  f.flags = 65; mesh.faces[22] = f;
	f.v[0] = 31;  f.v[1] = 36;  f.v[2] = 37;  	f.smGroup = 1;  f.flags = 66; mesh.faces[23] = f;
	f.v[0] = 30;  f.v[1] = 31;  f.v[2] = 37;  	f.smGroup = 1;  f.flags = 65; mesh.faces[24] = f;
	f.v[0] = 29;  f.v[1] = 30;  f.v[2] = 37;  	f.smGroup = 1;  f.flags = 65; mesh.faces[25] = f;
	f.v[0] = 29;  f.v[1] = 37;  f.v[2] = 38;  	f.smGroup = 1;  f.flags = 66; mesh.faces[26] = f;
	f.v[0] = 28;  f.v[1] = 29;  f.v[2] = 38;  	f.smGroup = 1;  f.flags = 65; mesh.faces[27] = f;
	f.v[0] = 28;  f.v[1] = 38;  f.v[2] = 39;  	f.smGroup = 1;  f.flags = 66; mesh.faces[28] = f;
	f.v[0] = 27;  f.v[1] = 28;  f.v[2] = 39;  	f.smGroup = 1;  f.flags = 65; mesh.faces[29] = f;
	f.v[0] = 27;  f.v[1] = 39;  f.v[2] = 40;  	f.smGroup = 1;  f.flags = 66; mesh.faces[30] = f;
	f.v[0] = 27;  f.v[1] = 40;  f.v[2] = 25;  	f.smGroup = 1;  f.flags = 66; mesh.faces[31] = f;
	f.v[0] = 27;  f.v[1] = 25;  f.v[2] = 26;  	f.smGroup = 1;  f.flags = 70; mesh.faces[32] = f;
	f.v[0] = 48;  f.v[1] = 49;  f.v[2] = 50;  	f.smGroup = 1;  f.flags = 67; mesh.faces[33] = f;
	f.v[0] = 48;  f.v[1] = 50;  f.v[2] = 51;  	f.smGroup = 1;  f.flags = 66; mesh.faces[34] = f;
	f.v[0] = 48;  f.v[1] = 51;  f.v[2] = 52;  	f.smGroup = 1;  f.flags = 66; mesh.faces[35] = f;
	f.v[0] = 48;  f.v[1] = 52;  f.v[2] = 53;  	f.smGroup = 1;  f.flags = 66; mesh.faces[36] = f;
	f.v[0] = 48;  f.v[1] = 53;  f.v[2] = 54;  	f.smGroup = 1;  f.flags = 66; mesh.faces[37] = f;
	f.v[0] = 48;  f.v[1] = 54;  f.v[2] = 55;  	f.smGroup = 1;  f.flags = 66; mesh.faces[38] = f;
	f.v[0] = 48;  f.v[1] = 55;  f.v[2] = 56;  	f.smGroup = 1;  f.flags = 66; mesh.faces[39] = f;
	f.v[0] = 48;  f.v[1] = 56;  f.v[2] = 57;  	f.smGroup = 1;  f.flags = 66; mesh.faces[40] = f;
	f.v[0] = 47;  f.v[1] = 48;  f.v[2] = 57;  	f.smGroup = 1;  f.flags = 65; mesh.faces[41] = f;
	f.v[0] = 63;  f.v[1] = 41;  f.v[2] = 42;  	f.smGroup = 1;  f.flags = 67; mesh.faces[42] = f;
	f.v[0] = 62;  f.v[1] = 63;  f.v[2] = 42;  	f.smGroup = 1;  f.flags = 65; mesh.faces[43] = f;
	f.v[0] = 47;  f.v[1] = 57;  f.v[2] = 58;  	f.smGroup = 1;  f.flags = 66; mesh.faces[44] = f;
	f.v[0] = 46;  f.v[1] = 47;  f.v[2] = 58;  	f.smGroup = 1;  f.flags = 65; mesh.faces[45] = f;
	f.v[0] = 62;  f.v[1] = 42;  f.v[2] = 43;  	f.smGroup = 1;  f.flags = 66; mesh.faces[46] = f;
	f.v[0] = 61;  f.v[1] = 62;  f.v[2] = 43;  	f.smGroup = 1;  f.flags = 65; mesh.faces[47] = f;
	f.v[0] = 46;  f.v[1] = 58;  f.v[2] = 59;  	f.smGroup = 1;  f.flags = 66; mesh.faces[48] = f;
	f.v[0] = 45;  f.v[1] = 46;  f.v[2] = 59;  	f.smGroup = 1;  f.flags = 65; mesh.faces[49] = f;
	f.v[0] = 61;  f.v[1] = 43;  f.v[2] = 44;  	f.smGroup = 1;  f.flags = 66; mesh.faces[50] = f;
	f.v[0] = 60;  f.v[1] = 61;  f.v[2] = 44;  	f.smGroup = 1;  f.flags = 65; mesh.faces[51] = f;
	f.v[0] = 45;  f.v[1] = 59;  f.v[2] = 60;  	f.smGroup = 1;  f.flags = 66; mesh.faces[52] = f;
	f.v[0] = 45;  f.v[1] = 60;  f.v[2] = 44;  	f.smGroup = 1;  f.flags = 68; mesh.faces[53] = f;
	f.v[0] = 91;  f.v[1] = 64;  f.v[2] = 65;  	f.smGroup = 1;  f.flags = 67; mesh.faces[54] = f;
	f.v[0] = 91;  f.v[1] = 65;  f.v[2] = 66;  	f.smGroup = 1;  f.flags = 66; mesh.faces[55] = f;
	f.v[0] = 90;  f.v[1] = 91;  f.v[2] = 66;  	f.smGroup = 1;  f.flags = 65; mesh.faces[56] = f;
	f.v[0] = 90;  f.v[1] = 66;  f.v[2] = 67;  	f.smGroup = 1;  f.flags = 66; mesh.faces[57] = f;
	f.v[0] = 89;  f.v[1] = 90;  f.v[2] = 67;  	f.smGroup = 1;  f.flags = 65; mesh.faces[58] = f;
	f.v[0] = 88;  f.v[1] = 89;  f.v[2] = 67;  	f.smGroup = 1;  f.flags = 65; mesh.faces[59] = f;
	f.v[0] = 88;  f.v[1] = 67;  f.v[2] = 68;  	f.smGroup = 1;  f.flags = 66; mesh.faces[60] = f;
	f.v[0] = 88;  f.v[1] = 68;  f.v[2] = 69;  	f.smGroup = 1;  f.flags = 66; mesh.faces[61] = f;
	f.v[0] = 88;  f.v[1] = 69;  f.v[2] = 70;  	f.smGroup = 1;  f.flags = 66; mesh.faces[62] = f;
	f.v[0] = 88;  f.v[1] = 70;  f.v[2] = 71;  	f.smGroup = 1;  f.flags = 66; mesh.faces[63] = f;
	f.v[0] = 88;  f.v[1] = 71;  f.v[2] = 72;  	f.smGroup = 1;  f.flags = 66; mesh.faces[64] = f;
	f.v[0] = 88;  f.v[1] = 72;  f.v[2] = 73;  	f.smGroup = 1;  f.flags = 66; mesh.faces[65] = f;
	f.v[0] = 88;  f.v[1] = 73;  f.v[2] = 74;  	f.smGroup = 1;  f.flags = 66; mesh.faces[66] = f;
	f.v[0] = 88;  f.v[1] = 74;  f.v[2] = 75;  	f.smGroup = 1;  f.flags = 66; mesh.faces[67] = f;
	f.v[0] = 88;  f.v[1] = 75;  f.v[2] = 76;  	f.smGroup = 1;  f.flags = 66; mesh.faces[68] = f;
	f.v[0] = 88;  f.v[1] = 76;  f.v[2] = 77;  	f.smGroup = 1;  f.flags = 66; mesh.faces[69] = f;
	f.v[0] = 88;  f.v[1] = 77;  f.v[2] = 78;  	f.smGroup = 1;  f.flags = 66; mesh.faces[70] = f;
	f.v[0] = 88;  f.v[1] = 78;  f.v[2] = 79;  	f.smGroup = 1;  f.flags = 66; mesh.faces[71] = f;
	f.v[0] = 88;  f.v[1] = 79;  f.v[2] = 80;  	f.smGroup = 1;  f.flags = 66; mesh.faces[72] = f;
	f.v[0] = 88;  f.v[1] = 80;  f.v[2] = 81;  	f.smGroup = 1;  f.flags = 66; mesh.faces[73] = f;
	f.v[0] = 88;  f.v[1] = 81;  f.v[2] = 82;  	f.smGroup = 1;  f.flags = 66; mesh.faces[74] = f;
	f.v[0] = 88;  f.v[1] = 82;  f.v[2] = 83;  	f.smGroup = 1;  f.flags = 66; mesh.faces[75] = f;
	f.v[0] = 88;  f.v[1] = 83;  f.v[2] = 84;  	f.smGroup = 1;  f.flags = 66; mesh.faces[76] = f;
	f.v[0] = 88;  f.v[1] = 84;  f.v[2] = 85;  	f.smGroup = 1;  f.flags = 66; mesh.faces[77] = f;
	f.v[0] = 88;  f.v[1] = 85;  f.v[2] = 86;  	f.smGroup = 1;  f.flags = 66; mesh.faces[78] = f;
	f.v[0] = 88;  f.v[1] = 86;  f.v[2] = 87;  	f.smGroup = 1;  f.flags = 70; mesh.faces[79] = f;
	f.v[0] = 105;  f.v[1] = 106;  f.v[2] = 107;  	f.smGroup = 1;  f.flags = 67; mesh.faces[80] = f;
	f.v[0] = 105;  f.v[1] = 107;  f.v[2] = 108;  	f.smGroup = 1;  f.flags = 66; mesh.faces[81] = f;
	f.v[0] = 104;  f.v[1] = 105;  f.v[2] = 108;  	f.smGroup = 1;  f.flags = 65; mesh.faces[82] = f;
	f.v[0] = 103;  f.v[1] = 104;  f.v[2] = 108;  	f.smGroup = 1;  f.flags = 65; mesh.faces[83] = f;
	f.v[0] = 103;  f.v[1] = 108;  f.v[2] = 109;  	f.smGroup = 1;  f.flags = 66; mesh.faces[84] = f;
	f.v[0] = 103;  f.v[1] = 109;  f.v[2] = 110;  	f.smGroup = 1;  f.flags = 66; mesh.faces[85] = f;
	f.v[0] = 102;  f.v[1] = 103;  f.v[2] = 110;  	f.smGroup = 1;  f.flags = 65; mesh.faces[86] = f;
	f.v[0] = 102;  f.v[1] = 110;  f.v[2] = 111;  	f.smGroup = 1;  f.flags = 66; mesh.faces[87] = f;
	f.v[0] = 102;  f.v[1] = 111;  f.v[2] = 112;  	f.smGroup = 1;  f.flags = 66; mesh.faces[88] = f;
	f.v[0] = 102;  f.v[1] = 112;  f.v[2] = 113;  	f.smGroup = 1;  f.flags = 66; mesh.faces[89] = f;
	f.v[0] = 102;  f.v[1] = 113;  f.v[2] = 114;  	f.smGroup = 1;  f.flags = 66; mesh.faces[90] = f;
	f.v[0] = 102;  f.v[1] = 114;  f.v[2] = 115;  	f.smGroup = 1;  f.flags = 66; mesh.faces[91] = f;
	f.v[0] = 102;  f.v[1] = 115;  f.v[2] = 116;  	f.smGroup = 1;  f.flags = 66; mesh.faces[92] = f;
	f.v[0] = 102;  f.v[1] = 116;  f.v[2] = 117;  	f.smGroup = 1;  f.flags = 66; mesh.faces[93] = f;
	f.v[0] = 102;  f.v[1] = 117;  f.v[2] = 118;  	f.smGroup = 1;  f.flags = 66; mesh.faces[94] = f;
	f.v[0] = 102;  f.v[1] = 118;  f.v[2] = 119;  	f.smGroup = 1;  f.flags = 66; mesh.faces[95] = f;
	f.v[0] = 102;  f.v[1] = 119;  f.v[2] = 92;  	f.smGroup = 1;  f.flags = 66; mesh.faces[96] = f;
	f.v[0] = 102;  f.v[1] = 92;  f.v[2] = 93;  	f.smGroup = 1;  f.flags = 66; mesh.faces[97] = f;
	f.v[0] = 102;  f.v[1] = 93;  f.v[2] = 94;  	f.smGroup = 1;  f.flags = 66; mesh.faces[98] = f;
	f.v[0] = 102;  f.v[1] = 94;  f.v[2] = 95;  	f.smGroup = 1;  f.flags = 66; mesh.faces[99] = f;
	f.v[0] = 102;  f.v[1] = 95;  f.v[2] = 96;  	f.smGroup = 1;  f.flags = 66; mesh.faces[100] = f;
	f.v[0] = 102;  f.v[1] = 96;  f.v[2] = 97;  	f.smGroup = 1;  f.flags = 66; mesh.faces[101] = f;
	f.v[0] = 102;  f.v[1] = 97;  f.v[2] = 98;  	f.smGroup = 1;  f.flags = 66; mesh.faces[102] = f;
	f.v[0] = 102;  f.v[1] = 98;  f.v[2] = 99;  	f.smGroup = 1;  f.flags = 66; mesh.faces[103] = f;
	f.v[0] = 102;  f.v[1] = 99;  f.v[2] = 100;  	f.smGroup = 1;  f.flags = 66; mesh.faces[104] = f;
	f.v[0] = 102;  f.v[1] = 100;  f.v[2] = 101;  	f.smGroup = 1;  f.flags = 70; mesh.faces[105] = f;
	// This makes the mesh "float" on top of other objects
	mesh.InvalidateGeomCache();
	mesh.EnableEdgeList(1);
}
    BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        HWND cbox = NULL;
        switch (msg)
        {

        case WM_INITDIALOG:
            cbox = GetDlgItem(hWnd, IDC_COMP_DISTRIB_PROBCOLORCHAN);
            int i;
            for( i = 0; i < kNumColorChanOptions; i++ )
            {
                SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)kProbColorChanStrings[i].fString);
            }
            SendMessage(cbox, CB_SETCURSEL, map->GetParamBlock()->GetInt(plDistribComponent_old::kProbColorChan), 0);

            ISetupScaleLock(map, true);

            return TRUE;
        case WM_COMMAND:
            if( (HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDC_DISTRIB_CLEAR) )
            {
                plDistribComponent_old* dc = (plDistribComponent_old*)map->GetParamBlock()->GetOwner();
                dc->Clear();

                return TRUE;
            }
            switch( LOWORD(wParam) )
            {
                case IDC_COMP_DISTRIB_PROBCOLORCHAN:
                {
                    map->GetParamBlock()->SetValue(plDistribComponent_old::kProbColorChan, t, SendMessage(GetDlgItem(hWnd, LOWORD(wParam)), CB_GETCURSEL, 0, 0));
                    return TRUE;
                }
                break;

                case IDC_COMP_DISTRIB_FADEINACTIVE:
                case IDC_COMP_DISTRIB_FADEINTRAN:
                case IDC_COMP_DISTRIB_FADEINOPAQ:
                case IDC_COMP_DISTRIB_FADEOUTTRAN:
                case IDC_COMP_DISTRIB_FADEOUTOPAQ:
                case IDC_COMP_DISTRIB_FADEINTRAN_SPIN:
                case IDC_COMP_DISTRIB_FADEINOPAQ_SPIN:
                case IDC_COMP_DISTRIB_FADEOUTTRAN_SPIN:
                case IDC_COMP_DISTRIB_FADEOUTOPAQ_SPIN:
                {
                    plDistribComponent_old* dc = (plDistribComponent_old*)map->GetParamBlock()->GetOwner();
                    Box3 fade;
                    if( !dc->IValidateFade(fade) )
                    {
                        map->GetParamBlock()->SetValue(plDistribComponent_old::kFadeInTran, t, fade.Min()[0]);
                        map->GetParamBlock()->SetValue(plDistribComponent_old::kFadeInOpaq, t, fade.Min()[1]);
                        map->GetParamBlock()->SetValue(plDistribComponent_old::kFadeOutTran, t, fade.Max()[0]);
                        map->GetParamBlock()->SetValue(plDistribComponent_old::kFadeOutOpaq, t, fade.Max()[1]);

                        map->Invalidate(plDistribComponent_old::kFadeInTran);
                        map->Invalidate(plDistribComponent_old::kFadeInOpaq);
                        map->Invalidate(plDistribComponent_old::kFadeOutTran);
                        map->Invalidate(plDistribComponent_old::kFadeOutOpaq);
                        ShowWindow(hWnd, SW_HIDE);
                        ShowWindow(hWnd, SW_SHOW);
                    }
                    return TRUE;
                }
                break;
#if 0 // Obsolete, now kRndPosRadius is percentage of kSpacing
                case IDC_COMP_DISTRIB_RNDPOSRADIUS:
                case IDC_COMP_DISTRIB_RNDPOSRADIUS_SPIN:
                {
                    IParamBlock2 *pb = map->GetParamBlock();

                    float maxRndPosRad = pb->GetFloat(plDistribComponent_old::kSpacing) * 0.5f;
                    if( pb->GetFloat(plDistribComponent_old::kRndPosRadius) > maxRndPosRad )
                    {
                        pb->SetValue(plDistribComponent_old::kRndPosRadius, t, maxRndPosRad);
                        map->Invalidate(plDistribComponent_old::kRndPosRadius);
                        ShowWindow(hWnd, SW_HIDE);
                        ShowWindow(hWnd, SW_SHOW);
                    }
                    
                    return TRUE;
                }
#endif // Obsolete, now kRndPosRadius is percentage of kSpacing
                case IDC_COMP_DISTRIB_LOCKSCALEXY:
                case IDC_COMP_DISTRIB_LOCKSCALEXYZ:
                    ISetupScaleLock(map, false);
                    return TRUE;

            }
            break;
        }

        return false;
    }
Пример #17
0
void BSPOctree::PerformBoolean(PolygonPtrList& mesh1, PolygonPtrList& mesh2, const Box3& bbox, OctTreeNode** node)
{
    FixedPlane bounds[] = {FixedPlane(double3(1,0,0),-bbox.Min().x)
                            , FixedPlane(double3(-1,0,0),bbox.Max().x)
                            , FixedPlane(double3(0,1,0),-bbox.Min().y)
                            , FixedPlane(double3(0,-1,0),bbox.Max().y)
                            , FixedPlane(double3(0,0,1),-bbox.Min().z)
                            , FixedPlane(double3(0,0,-1),bbox.Max().z)};

    FixedPlaneMesh myMesh1, myMesh2;
    FixedPlanePolygon poly;
    std::list<FixedPlanePolygon*> polyPool;

    // for containment test, jxd
    OctLeafNode* pLeaf = new OctLeafNode;
    pLeaf->bbox = bbox;
    // end

    for (auto index: mesh1)
    {
        MeshData *data = &(mMesh1[index]);
        /// convert simple mesh into plane based mesh
        if (!data->bSplitted)
        {
            data->bSplitted = true;
            data->OrigPolygon = FixedPlanePolygon(data->Position[0],
                data->Position[1], data->Position[2]);
            FixedPlanePolygon *root = new FixedPlanePolygon(data->OrigPolygon);
            data->Fragments.push_back(root);
        }

        // get the inside polygons: myMesh1
        poly = data->OrigPolygon;
        bool bNeedInsert = true;
        for (int i = 0; i < 6; i++)
        {
            poly.ClipByPlaneNoFront(bounds[i]);
            if (poly.Size() == 0)
            {
                bNeedInsert = false;
                break;
            }
        }
        if (bNeedInsert) myMesh1.AddPolygon(poly);
        poly.Clear();
    }
    if (myMesh1.PrimitiveCount() == 0)
    {
        pLeaf->type = eCritical;
        FillOctreeLeafNode(mesh1, mesh2, pLeaf);
        *node = pLeaf;
        return;
    }

    for (auto index: mesh2)
    {
        /// convert simple mesh into plane based mesh
        MeshData *data = &(mMesh2[index]);
        if (!data->bSplitted)
        {
            data->bSplitted = true;
            data->OrigPolygon = FixedPlanePolygon(data->Position[0],
                data->Position[1], data->Position[2]);
            FixedPlanePolygon *root = new FixedPlanePolygon(data->OrigPolygon);
            data->Fragments.push_back(root);
        }

        // get the inside polygons: myMesh2
        poly = data->OrigPolygon;
        bool bNeedInsert = true;
        for (int i = 0; i < 6; i++)
        {
            poly.ClipByPlaneNoFront(bounds[i]);
            if (poly.Size() == 0)
            {
                bNeedInsert = false;
                break;
            }
        }
        if (bNeedInsert) myMesh2.AddPolygon(poly);
        poly.Clear();
    }
    if (myMesh2.PrimitiveCount() == 0)
    {
        pLeaf->type = eCritical;
        FillOctreeLeafNode(mesh1, mesh2, pLeaf);
        *node = pLeaf;
        return;
    }
    FixedBSPTree *tree1, *tree2;
    tree1 = myMesh1.ToBSPTree();
    tree1->FormSubHyperPlane(bbox);
    tree2 = myMesh2.ToBSPTree();
    tree2->FormSubHyperPlane(bbox);

    auto op = mOperation;
    if (mOperation == FixedBSPTree::OP_DIFFERENCE)
    {
        op = FixedBSPTree::OP_INTERSECT;
    }

    FixedBSPTree *mergeTree = tree1->Merge(tree2, op);
    delete tree1;
    delete tree2;

    mergeTree->GetPolygons(mPlanePolygon);
    delete mergeTree;

    pLeaf->type = eIntered;
    FillOctreeLeafNode(mesh1, mesh2, pLeaf);
    *node = pLeaf;
}
Пример #18
0
	// Load blend shape poses
	bool BlendShape::loadPoses(ParamList &params, std::vector<vertex> &vertices,long numVertices,long offset,long targetIndex)
	{
		if (params.useSharedGeom)
		{
			assert(targetIndex == 0);
			m_target = T_MESH;
		}
		else
		{
			assert(offset == 0);
			poseGroup new_pg;
			m_target = T_SUBMESH;
			new_pg.targetIndex = targetIndex;
			m_poseGroups.insert(std::pair<int,poseGroup>(targetIndex,new_pg));
		}
		poseGroup& pg = m_poseGroups.find(targetIndex)->second;

		if(m_pGameNode && m_pMorphR3)
		{
            // Disable all skin Modifiers.
            std::vector<Modifier*> disabledSkinModifiers;
            IGameObject* pGameObject = m_pGameNode->GetIGameObject();
            if( pGameObject )
            {
                int numModifiers = pGameObject->GetNumModifiers();
                for( int i = 0; i < numModifiers; ++i )
                {
                    IGameModifier* pGameModifier = pGameObject->GetIGameModifier(i);
                    if( pGameModifier )
                    {
                        if( pGameModifier->IsSkin() )
                        {
                            Modifier* pModifier = pGameModifier->GetMaxModifier();
                            if( pModifier )
                            {
                                if( pModifier->IsEnabled() )
                                {
                                    disabledSkinModifiers.push_back(pModifier);
                                    pModifier->DisableMod();
                                }
                            }
                        }
                    }
                }
            }

			// Get the original mesh from the IGameNode.  Not using IGame here
			// since MorphR3 doesn't allow for it.  Also we don't know if our vertices
			// are in object or world space, so we'll just calculate diffs directly from 
			// the Max meshes and modify the coordinate system manually.  
			// Obtained method of getting mesh from 3D Studio Max SDK Training session by
			// David Lanier.
 			bool DeleteObjectWhenDone;
			const ObjectState& objectState = m_pGameNode->GetMaxNode()->EvalWorldState(GetCOREInterface()->GetTime());
			Object *origMeshObj = objectState.obj;
			if (!origMeshObj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))
			{
				FxOgreMaxExporterLog( "Could not access original mesh for morph target comparison.");
				return false;
			}

			// Calculate the DiffTM matrix.  This is the difference between the INode's world transform
			// which is used to calculate the morph verticies, and the IGameNode's world transform, which is used
			// to calculate the Ogre mesh's verticies.
			Matrix3 DiffTM = m_pGameNode->GetObjectTM(GetCOREInterface()->GetTime()).ExtractMatrix3();

			// The below code is not well tested as FaceFX needs content in the native coordinates.
			// I've seen the direction of the morph movement flipped on some content when in Y-up mode 
			// which sets the coordinate system to IGAME_OGL.
			// I can't get this to work on all the morph examples I have however.
			IGameConversionManager* pConversionManager = GetConversionManager();
			if(IGameConversionManager::IGAME_OGL == pConversionManager->GetCoordSystem())
			{			
				Matrix3 conv = Matrix3(Point3(1,0,0), Point3(0,0,1), Point3(0,-1,0), Point3(0,0,0));
				DiffTM = DiffTM * conv;
			}

			TriObject *origMeshTriObj = (TriObject *) origMeshObj->ConvertToType(GetCOREInterface()->GetTime(), Class_ID(TRIOBJ_CLASS_ID, 0));
			if (origMeshObj != origMeshTriObj) DeleteObjectWhenDone = true;
			Mesh& origMesh = origMeshTriObj->GetMesh();
			const int NumVerts = origMesh.getNumVerts();
 

			for( int i = 0; i < m_pMorphR3->chanBank.size() && i < MR3_NUM_CHANNELS; ++i )
			{
				if( m_pMorphR3->chanBank[i].mActive )
				{
					morphChannel* pMorphChannel = &m_pMorphR3->chanBank[i];	
					if( pMorphChannel )
					{
						pMorphChannel->rebuildChannel();

						std::string posename = string_tools::string_cast<ogre_string_type>(pMorphChannel->mName.data());
						int numMorphVertices = pMorphChannel->mNumPoints;
						
						if( numMorphVertices != origMesh.getNumVerts() )
						{
							MessageBox(GetCOREInterface()->GetMAXHWnd(), _T("Morph targets have failed to export becuase the morph vertex count did not match the base mesh.  Collapse the modifier stack prior to export, as smoothing is not supported with morph target export."), _T("Morph Target Export Failed."), MB_OK);
							return false;
						}
						else
						{
							FxOgreMaxExporterLog( "Exporting Morph target: %s with %d vertices.\n", posename.c_str(), numMorphVertices);
							FxOgreMaxExporterLog( "Mesh has %d vertices.\n", numVertices);
							FxOgreMaxExporterLog( "%d total vertices.\n", vertices.size());
							assert(offset+numVertices <= vertices.size());
							// create a new pose
							pose p;
							p.poseTarget = m_target;
							p.index = targetIndex;
							p.blendShapeIndex = i;
							p.name = posename;
							p.pMChannel = pMorphChannel;

							size_t numPoints = pMorphChannel->mPoints.size();
							std::vector<Point3> vmPoints;
							vmPoints.reserve(numPoints);
							for( size_t k = 0; k < numPoints; ++k )
							{
								vmPoints.push_back(pMorphChannel->mPoints[k]);
							}

							Box3 morphBoundingBox;
							// calculate vertex offsets
							for (int k=0; k<numVertices; k++)
							{
								vertexOffset vo;
								assert ((offset+k)<vertices.size());

								vertex v = vertices[offset+k];
								assert(v.index < numMorphVertices);
								assert(v.index < origMesh.getNumVerts());

								Point3 meshVert = origMesh.getVert(v.index);
								Point3 morphVert = vmPoints[v.index];

								Point3 diff = morphVert - meshVert;

								// Transform our morph vertex movements by whatever
								// scaling/rotation is being done by IGame..
								Point3 ogreSpacediff = DiffTM.VectorTransform(diff);


								// Add this point to the bounding box
								morphBoundingBox += morphVert;

								vo.x = ogreSpacediff.x * params.lum;
								vo.y = ogreSpacediff.y * params.lum;
								vo.z = ogreSpacediff.z * params.lum;	

								vo.index = offset+k;
								if (fabs(vo.x) < PRECISION)
									vo.x = 0;
								if (fabs(vo.y) < PRECISION)
									vo.y = 0;
								if (fabs(vo.z) < PRECISION)
									vo.z = 0;
								if ((vo.x!=0) || (vo.y!=0) || (vo.z!=0))
									p.offsets.push_back(vo);
							}
							// add pose to pose list
							if (p.offsets.size() > 0)
							{
								pg.poses.push_back(p);
							}
							if (params.bsBB)
							{
								// update bounding boxes of loaded submeshes
								for (int j=0; j<params.loadedSubmeshes.size(); j++)
								{
									Point3 min = morphBoundingBox.Min() * params.lum;
									Point3 max = morphBoundingBox.Max() * params.lum;
									// Update coordinate system here.
									Point3 newMin, newMax;
									newMin.x = min.x;
									newMin.y = min.z;
									newMin.z = min.y;
									Box3 newBox(newMin, newMax);
									if (params.exportWorldCoords)
										newBox = newBox * m_pGameNode->GetWorldTM(GetCOREInterface()->GetTime()).ExtractMatrix3();
									params.loadedSubmeshes[j]->m_boundingBox += newBox;
								}
							}
						}

					}
				}
			}
            // Re-enable skin modifiers.
            for( int i = 0; i < disabledSkinModifiers.size(); ++i )
            {
                disabledSkinModifiers[i]->EnableMod();
            }
			// According to David Lanier, this should be deleted, but I get crashes when exporting blendShapes
			// without shared geometry when I use the object for the second time.  Perhaps it
			// can only be used/deleted once.  Even without shared geometry, I'll get a strange crash
			// a few seconds after successful export with this here.
//			if (DeleteObjectWhenDone)
//				origMeshTriObj->DeleteMe();
		}
		return true;
	}
Пример #19
0
void plDistributor::IDistributeOverFace(int iFace, plDistribInstTab& reps, plMeshCacheTab& cache) const
{
    Point3 p0 = fSurfMesh->getVert(fSurfMesh->faces[iFace].getVert(0));
    Point3 p1 = fSurfMesh->getVert(fSurfMesh->faces[iFace].getVert(1));
    Point3 p2 = fSurfMesh->getVert(fSurfMesh->faces[iFace].getVert(2));

    Box3 grid = ISetupGrid(p0, p1, p2);

    float delta = fSpacing;

    float x, y, z;
    for( x = grid.Min().x; x < grid.Max().x; x += delta )
    {
        for( y = grid.Min().y; y < grid.Max().y; y += delta )
        {
            for( z = grid.Min().z; z < grid.Max().z; z += delta )
            {
                Point3 pt(x, y, z);

                pt = IPerturbPoint(pt);

                Point3 plnPt = pt;
                Point3 bary;

                // Get Barycentric coord of projection of grid pt onto face
                plTriUtils triUtil;
                plTriUtils::Bary baryVal = triUtil.ComputeBarycentricProjection(hsP3(p0), hsP3(p1), hsP3(p2), hsP3(plnPt), hsP3(bary));
                if( !(baryVal & (plTriUtils::kOutsideTri | plTriUtils::kDegenerateTri)) )
                {
                    int iRepNode = ISelectRepNode();

                    Matrix3 l2w = IGenerateTransform(iRepNode, iFace, plnPt, bary);

                    // l2w as ident means this position turned out to be not so good afterall.
                    if( l2w.IsIdentity() )
                    {
                        continue;
                    }

                    Box3 clearBox;
                    if( !ISpaceClear(iRepNode, l2w, clearBox, cache) )
                    {
                        continue;
                    }

                    int iCacheNode = iRepNode;
                    if( !IConform(l2w, iRepNode, cache, iCacheNode) )
                    {
                        continue;
                    }

                    // If |projGridPt - GridPt| < gridCubeRadius
                    // and probBitmap->GetPixel(src->UVW(bary)) < RandomZeroToOne()
                    // Also a generic random factor.
                    if( IProbablyDoIt(iFace, pt - plnPt, bary) )
                    {
                        IReplicate(l2w, iRepNode, reps, cache[iCacheNode]);

                        IReserveSpace(clearBox);
                    }
                }
            }
        }
    }
}