public void PreContainerUpdate(uFlex.FlexSolver solver, uFlex.FlexContainer cntr, uFlex.FlexParameters parameters) { //=== Bake rim skinned mesh and update position of softbody particle pins === _oSMR.BakeMesh(_oMeshSkinBaked); //###OPT!!! Check how expensive this is. Is there a way for us to move verts & normals straight from skinned mesh from Flex? (Have not found a way so far) Vector3[] aVerts = _oMeshSkinBaked.vertices; for (int nVert = 0; nVert < _nVerts; nVert++) //###OPT!! Expensive loop per frame that is unfortunately required because different memory footprints... :-( m_particles[nVert].pos = aVerts[nVert]; }
//void Start () {} //void Update () {} public static void CreateFlexObject(GameObject go, Mesh oMeshAppearance, Mesh oMeshFlexCollider, uFlex.FlexBodyType bodyType, uFlex.FlexInteractionType interactionType, float nMass, Color color) { CGame oGame = CGame.INSTANCE; float particleSpacing = oGame.particleSpacing; //###WEAK ###MOVE? float volumeSampling = oGame.volumeSampling; float surfaceSampling = oGame.surfaceSampling; float clusterSpacing = particleSpacing * oGame.clusterSpacingMult; float clusterRadius = particleSpacing * oGame.clusterRadiusMult; float clusterStiffness = oGame.clusterStiffness; float linkRadius = particleSpacing * oGame.linkRadiusMult; float linkStiffness = oGame.linkStiffness; float skinFalloff = oGame.skinFalloff; float skinMaxDist = particleSpacing * oGame.skinMaxDistMult; float stretchStiffness = oGame.stretchStiffness; float bendStiffness = oGame.bendStiffness; float tetherStiffness = oGame.tetherStiffness; float tetherGive = oGame.tetherGive; int group = -1; bool softMesh = (bodyType == uFlex.FlexBodyType.Soft) || (bodyType == uFlex.FlexBodyType.Cloth); Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue); Vector3[] vertices = oMeshFlexCollider.vertices; int vertexCount = oMeshFlexCollider.vertexCount; int[] triangles = oMeshFlexCollider.triangles; int triIndicesCount = triangles.Length; int trianglesCount = triIndicesCount / 3; IntPtr flexAssetPtr = IntPtr.Zero; int[] uniqueVerticesIds = new int[vertexCount]; int[] origToUniqueVertMapping = new int[vertexCount]; int uniqueVerticesCount = uFlex.FlexExt.flexExtCreateWeldedMeshIndices(vertices, vertexCount, uniqueVerticesIds, origToUniqueVertMapping, 0.00001f); Debug.Log("Welding Mesh: " + uniqueVerticesCount + "/" + vertexCount); Vector3[] uniqueVertices = new Vector3[uniqueVerticesCount]; Vector4[] verticesWithInvMass = new Vector4[uniqueVerticesCount]; //###MOD Vector4[] uniqueVerticesWithInvMass = new Vector4[uniqueVerticesCount]; for (int i = 0; i < uniqueVerticesCount; i++) { uniqueVertices[i] = vertices[uniqueVerticesIds[i]]; verticesWithInvMass[i] = vertices[i]; //###MOD verticesWithInvMass[i].w = 1.0f / nMass; uniqueVerticesWithInvMass[i] = vertices[uniqueVerticesIds[i]]; uniqueVerticesWithInvMass[i].w = 1.0f / nMass; min = uFlex.FlexUtils.Min(min, uniqueVertices[i]); max = uFlex.FlexUtils.Max(max, uniqueVertices[i]); } int[] uniqueTriangles = new int[trianglesCount * 3]; for (int i = 0; i < trianglesCount * 3; i++) { uniqueTriangles[i] = origToUniqueVertMapping[triangles[i]]; } if (bodyType == uFlex.FlexBodyType.Rigid) //###CLEANUP { //flexAssetPtr = FlexExt.flexExtCreateRigidFromMesh(vertices, vertexCount, triangles, triIndicesCount, rigidRadius, rigidExpand); ///flexAssetPtr = uFlex.FlexExt.flexExtCreateRigidFromMesh(uniqueVertices, uniqueVerticesCount, uniqueTriangles, triIndicesCount, rigidRadius, rigidExpand); } if (bodyType == uFlex.FlexBodyType.Soft) { //###F: Do away with vert glueing? flexAssetPtr = uFlex.FlexExt.flexExtCreateSoftFromMesh(vertices, vertexCount, triangles, triIndicesCount, particleSpacing, volumeSampling, surfaceSampling, clusterSpacing, clusterRadius, clusterStiffness, linkRadius, linkStiffness); //flexAssetPtr = uFlex.FlexExt.flexExtCreateSoftFromMesh(uniqueVertices, uniqueVerticesCount, uniqueTriangles, triIndicesCount, particleSpacing, volumeSampling, surfaceSampling, clusterSpacing, clusterRadius, clusterStiffness, linkRadius, linkStiffness); } if (bodyType == uFlex.FlexBodyType.Cloth) { flexAssetPtr = uFlex.FlexExt.flexExtCreateClothFromMesh(verticesWithInvMass, vertexCount, triangles, trianglesCount, stretchStiffness, bendStiffness, tetherStiffness, tetherGive, 0); //flexAssetPtr = uFlex.FlexExt.flexExtCreateClothFromMesh(uniqueVerticesWithInvMass, uniqueVerticesCount, uniqueTriangles, trianglesCount, stretchStiffness, bendStiffness, tetherStiffness, tetherGive, 0); } if (bodyType == uFlex.FlexBodyType.Inflatable) { ///flexAssetPtr = uFlex.FlexExt.flexExtCreateClothFromMesh(verticesWithInvMass, vertexCount, triangles, trianglesCount, stretchStiffness, bendStiffness, tetherStiffness, tetherGive, pressure); ///flexAssetPtr = uFlex.FlexExt.flexExtCreateClothFromMesh(uniqueVerticesWithInvMass, uniqueVerticesCount, uniqueTriangles, trianglesCount, stretchStiffness, bendStiffness, tetherStiffness, tetherGive, pressure); } //if (bodyType == uFlex.FlexBodyType.Cloth) //{ // // flexAssetPtr = FlexExt.flexExtCreateClothFromMesh(verticesWithInvMass, vertexCount, triangles, trianglesCount, stretchStiffness, bendStiffness, tetherStiffness, tetherGive, 0); // ///flexAssetPtr = uFlex.FlexExt.flexExtCreateClothFromMesh(uniqueVerticesWithInvMass, uniqueVerticesCount, uniqueTriangles, trianglesCount, stretchStiffness, bendStiffness, tetherStiffness, tetherGive, 0); //} if (flexAssetPtr != IntPtr.Zero) { //Flex Asset Marshalling uFlex.FlexExt.FlexExtAsset flexAsset = (uFlex.FlexExt.FlexExtAsset)Marshal.PtrToStructure(flexAssetPtr, typeof(uFlex.FlexExt.FlexExtAsset)); Vector4[] particles = uFlex.FlexUtils.MarshallArrayOfStructures<Vector4>(flexAsset.mParticles, flexAsset.mNumParticles); int[] springIndices = uFlex.FlexUtils.MarshallArrayOfStructures<int>(flexAsset.mSpringIndices, flexAsset.mNumSprings * 2); float[] springRestLengths = uFlex.FlexUtils.MarshallArrayOfStructures<float>(flexAsset.mSpringRestLengths, flexAsset.mNumSprings); float[] springCoefficients = uFlex.FlexUtils.MarshallArrayOfStructures<float>(flexAsset.mSpringCoefficients, flexAsset.mNumSprings); int[] shapeIndices = uFlex.FlexUtils.MarshallArrayOfStructures<int>(flexAsset.mShapeIndices, flexAsset.mNumShapeIndices); int[] shapeOffsets = uFlex.FlexUtils.MarshallArrayOfStructures<int>(flexAsset.mShapeOffsets, flexAsset.mNumShapes); Vector3[] shapeCenters = uFlex.FlexUtils.MarshallArrayOfStructures<Vector3>(flexAsset.mShapeCenters, flexAsset.mNumShapes); float[] shapeCoefficients = uFlex.FlexUtils.MarshallArrayOfStructures<float>(flexAsset.mShapeCoefficients, flexAsset.mNumShapes); Debug.LogFormat("[FlexSB] '{0}' has {1} Particules {2} Shapes {3} Springs {4} Tris.", go.name, flexAsset.mNumParticles, flexAsset.mNumShapes, flexAsset.mNumSprings, flexAsset.mNumTriangles); if (flexAsset.mNumParticles > 0) { uFlex.FlexParticles part = go.AddComponent<uFlex.FlexParticles>(); part.m_particlesCount = flexAsset.mNumParticles; part.m_particles = new uFlex.Particle[flexAsset.mNumParticles]; part.m_colours = new Color[flexAsset.mNumParticles]; part.m_velocities = new Vector3[flexAsset.mNumParticles]; part.m_densities = new float[flexAsset.mNumParticles]; part.m_particlesActivity = new bool[flexAsset.mNumParticles]; part.m_colour = color; part.m_interactionType = interactionType; part.m_collisionGroup = group; part.m_bounds.SetMinMax(min, max); for (int i = 0; i < flexAsset.mNumParticles; i++) { part.m_particles[i].pos = particles[i]; part.m_particles[i].invMass = particles[i].w; part.m_colours[i] = color; part.m_particlesActivity[i] = true; } } if (flexAsset.mNumSprings > 0) { uFlex.FlexSprings springs = go.AddComponent<uFlex.FlexSprings>(); springs.m_springsCount = flexAsset.mNumSprings; springs.m_springIndices = springIndices; springs.m_springRestLengths = springRestLengths; springs.m_springCoefficients = springCoefficients; } if (flexAsset.mNumTriangles > 0) { uFlex.FlexTriangles tris = go.AddComponent<uFlex.FlexTriangles>(); tris.m_trianglesCount = trianglesCount; tris.m_triangleIndices = uniqueTriangles; } uFlex.FlexShapeMatching shapes = null; if (flexAsset.mNumShapes > 0) { shapes = go.AddComponent<uFlex.FlexShapeMatching>(); shapes.m_shapesCount = flexAsset.mNumShapes; shapes.m_shapeIndicesCount = flexAsset.mNumShapeIndices; shapes.m_shapeIndices = shapeIndices; shapes.m_shapeOffsets = shapeOffsets; shapes.m_shapeCenters = shapeCenters; shapes.m_shapeCoefficients = shapeCoefficients; shapes.m_shapeTranslations = new Vector3[flexAsset.mNumShapes]; shapes.m_shapeRotations = new Quaternion[flexAsset.mNumShapes]; shapes.m_shapeRestPositions = new Vector3[flexAsset.mNumShapeIndices]; int shapeStart = 0; int shapeIndex = 0; int shapeIndexOffset = 0; for (int s = 0; s < shapes.m_shapesCount; s++) { shapes.m_shapeTranslations[s] = new Vector3(); shapes.m_shapeRotations[s] = Quaternion.identity; shapeIndex++; int shapeEnd = shapes.m_shapeOffsets[s]; for (int i = shapeStart; i < shapeEnd; ++i) { int p = shapes.m_shapeIndices[i]; // remap indices and create local space positions for each shape Vector3 pos = particles[p]; shapes.m_shapeRestPositions[shapeIndexOffset] = pos - shapes.m_shapeCenters[s]; // m_shapeIndices[shapeIndexOffset] = shapes.m_shapeIndices[i] + particles.m_particlesIndex; shapeIndexOffset++; } shapeStart = shapeEnd; } } if (flexAsset.mInflatable) { uFlex.FlexInflatable infla = go.AddComponent<uFlex.FlexInflatable>(); infla.m_pressure = flexAsset.mInflatablePressure; infla.m_stiffness = flexAsset.mInflatableStiffness; infla.m_restVolume = flexAsset.mInflatableVolume; } if (softMesh) { Renderer rend = null; if (bodyType == uFlex.FlexBodyType.Soft) { float[] skinWeights = new float[oMeshAppearance.vertexCount * 4]; int[] skinIndices = new int[oMeshAppearance.vertexCount * 4]; uFlex.FlexExt.flexExtCreateSoftMeshSkinning(oMeshAppearance.vertices, oMeshAppearance.vertexCount, shapes.m_shapeCenters, shapes.m_shapesCount, skinFalloff, skinMaxDist, skinWeights, skinIndices); Mesh mesh = new Mesh(); mesh.name = oMeshAppearance.name + "FlexMesh"; mesh.vertices = oMeshAppearance.vertices; mesh.triangles = oMeshAppearance.triangles; mesh.normals = oMeshAppearance.normals; mesh.uv = oMeshAppearance.uv; Transform[] bones = new Transform[shapes.m_shapesCount]; BoneWeight[] boneWeights = new BoneWeight[oMeshAppearance.vertexCount]; Matrix4x4[] bindPoses = new Matrix4x4[shapes.m_shapesCount]; Vector3[] rigidRestPoses = new Vector3[shapes.m_shapesCount]; //GameObject oTemplateGO = Resources.Load("Prefabs/CVisualizeShape", typeof(GameObject)) as GameObject; for (int i = 0; i < shapes.m_shapesCount; i++) { rigidRestPoses[i] = shapes.m_shapeCenters[i]; bones[i] = new GameObject("FlexShape_" + i).transform; //bones[i] = Instantiate(oTemplateGO).transform; bones[i].name = "Shape" + i.ToString(); bones[i].parent = go.transform; bones[i].localPosition = shapes.m_shapeCenters[i]; bones[i].localRotation = Quaternion.identity; bindPoses[i] = bones[i].worldToLocalMatrix * go.transform.localToWorldMatrix; } for (int i = 0; i < oMeshAppearance.vertexCount; i++) { boneWeights[i].boneIndex0 = skinIndices[i * 4 + 0]; boneWeights[i].boneIndex1 = skinIndices[i * 4 + 1]; boneWeights[i].boneIndex2 = skinIndices[i * 4 + 2]; boneWeights[i].boneIndex3 = skinIndices[i * 4 + 3]; boneWeights[i].weight0 = skinWeights[i * 4 + 0]; boneWeights[i].weight1 = skinWeights[i * 4 + 1]; boneWeights[i].weight2 = skinWeights[i * 4 + 2]; boneWeights[i].weight3 = skinWeights[i * 4 + 3]; } mesh.bindposes = bindPoses; mesh.boneWeights = boneWeights; mesh.RecalculateNormals(); mesh.RecalculateBounds(); ///AssetDatabase.CreateAsset(mesh, "Assets/uFlex/Meshes/" + inputMesh.name + "FlexMesh.asset"); //###CHECK! ///AssetDatabase.SaveAssets(); //uFlex.FlexSkinnedMesh skin = go.AddComponent<uFlex.FlexSkinnedMesh>(); uFlex.FlexSkinnedMesh skin = CUtility.FindOrCreateComponent(go, typeof(uFlex.FlexSkinnedMesh)) as uFlex.FlexSkinnedMesh; skin.m_bones = bones; skin.m_boneWeights = boneWeights; skin.m_bindPoses = bindPoses; //rend = go.AddComponent<SkinnedMeshRenderer>(); rend = CUtility.FindOrCreateComponent(go, typeof(SkinnedMeshRenderer)) as SkinnedMeshRenderer; ((SkinnedMeshRenderer)rend).sharedMesh = mesh; ((SkinnedMeshRenderer)rend).updateWhenOffscreen = true; ((SkinnedMeshRenderer)rend).quality = SkinQuality.Bone4; ((SkinnedMeshRenderer)rend).bones = bones; rend.enabled = false; //###MOD: We don't actually draw the skinned mesh... we bake its verts into a regular mesh, adjust rim pos and normals and draw that one! } if (bodyType == uFlex.FlexBodyType.Rigid) { go.AddComponent<uFlex.FlexRigidTransform>(); //MeshFilter meshFilter = go.AddComponent<MeshFilter>(); MeshFilter meshFilter = CUtility.FindOrCreateComponent(go, typeof(MeshFilter)) as MeshFilter; meshFilter.sharedMesh = oMeshFlexCollider; rend = CUtility.FindOrCreateComponent(go, typeof(MeshRenderer)) as MeshRenderer; } if (bodyType == uFlex.FlexBodyType.Cloth || bodyType == uFlex.FlexBodyType.Inflatable) { go.AddComponent<uFlex.FlexClothMesh>(); //MeshFilter meshFilter = go.AddComponent<MeshFilter>(); MeshFilter meshFilter = CUtility.FindOrCreateComponent(go, typeof(MeshFilter)) as MeshFilter; meshFilter.sharedMesh = oMeshFlexCollider; //rend = go.AddComponent<MeshRenderer>(); rend = CUtility.FindOrCreateComponent(go, typeof(MeshRenderer)) as MeshRenderer; } //Material mat = new Material(Shader.Find("Diffuse")); //mat.name = newName + "Mat"; //mat.color = color; } } //=== Add particle renderer === uFlex.FlexParticlesRenderer partRend = CUtility.FindOrCreateComponent(go, typeof(uFlex.FlexParticlesRenderer)) as uFlex.FlexParticlesRenderer; partRend.m_size = particleSpacing; partRend.m_radius = partRend.m_size / 2.0f; partRend.enabled = false; // Hidden by default }
//--------------------------------------------------------------------------- Flex public void PreContainerUpdate(uFlex.FlexSolver solver, uFlex.FlexContainer cntr, uFlex.FlexParameters parameters) { //=== Bake the baked part of our cloth. We need its periphery verts to pin our simulated part of the cloth! === _oPinnedParticles._oMeshSoftBodyPinnedParticles.Baking_UpdateBakedMesh(); // Bake the skinned portion of the mesh. We need its verts to pin the 'pinned particles' which in turn move the 'moving particles' toward them via a spring we created in init === _oPinnedParticles.UpdatePositionsOfPinnedParticles(); if (Input.GetKeyDown(KeyCode.F10)) { //####TEMP ####OBS ####CLEAN for (int nVert = 0; nVert < _oBMeshClothAtStartup._memVerts.L.Length; nVert++) { // Copy each vert from the 'backup' mesh to this simulated cloth... _oFlexParticles.m_particles[nVert].pos = _oBMeshClothAtStartup.transform.localToWorldMatrix.MultiplyPoint(_oBMeshClothAtStartup._memVerts.L[nVert]); //... making sure to convert each vert from the backup mesh's local coordinates to the global coordinates used in PhysX _oFlexParticles.m_velocities[nVert] = Vector3.zero; } } }
public static uFlex.FlexParticles CreateFlexObjects(GameObject oGO, IFlexProcessor iFlexProcessor, int nParticleCount, uFlex.FlexInteractionType nFlexInterationType, Color oColor) { uFlex.FlexParticles oFlexParticles = CUtility.FindOrCreateComponent(oGO, typeof(uFlex.FlexParticles)) as uFlex.FlexParticles; oFlexParticles.m_particlesCount = nParticleCount; // The non-edge particle are the ones that require driving between skinned and visible mesh. oFlexParticles.m_type = uFlex.FlexBodyType.Other; oFlexParticles.m_particles = new uFlex.Particle[nParticleCount]; oFlexParticles.m_colours = new Color[nParticleCount]; oFlexParticles.m_velocities = new Vector3[nParticleCount]; oFlexParticles.m_densities = new float[nParticleCount]; oFlexParticles.m_particlesActivity = new bool[nParticleCount]; oFlexParticles.m_colour = oColor; oFlexParticles.m_interactionType = nFlexInterationType; // The simulated particles collide with everything (other than ourselves) oFlexParticles.m_collisionGroup = -1; // Flex runtime will allocate to its own 'phase' of type m_interactionType oFlexParticles.m_bounds.SetMinMax(new Vector3(-1,-1,-1), new Vector3(1,1,1)); //###CHECK: Better with some reasonable values than zero? //=== Add particle renderer component for debug visualization === uFlex.FlexParticlesRenderer oFlexPartRend = CUtility.FindOrCreateComponent(oGO, typeof(uFlex.FlexParticlesRenderer)) as uFlex.FlexParticlesRenderer; oFlexPartRend.m_size = CGame.INSTANCE.particleSpacing; oFlexPartRend.m_radius = oFlexPartRend.m_size / 2.0f; oFlexPartRend.enabled = false; // Hidden by default //=== Create Flex Processor so we can update particles === if (iFlexProcessor != null) { uFlex.FlexProcessor oFlexProc = CUtility.FindOrCreateComponent(oGO, typeof(uFlex.FlexProcessor)) as uFlex.FlexProcessor; oFlexProc._oFlexProcessor = iFlexProcessor; } return oFlexParticles; }
public void PreContainerUpdate(uFlex.FlexSolver solver, uFlex.FlexContainer cntr, uFlex.FlexParameters parameters) { //=== Update the position of our flex particles so bodysuit can be repelled by the updated morph vert positions === if (_bParticlePositionsUpdated) { float nDistFlexColliderShrink = CGame.INSTANCE.particleSpacing * CGame.INSTANCE.nDistFlexColliderShrinkMult; for (int nParticle = 0; nParticle < _oFlexParticles.m_particlesCount; nParticle++) { int nVertWholeMesh = _aVertsFlexCollider[nParticle]; // Lookup the vert index in the full mesh from the Blender-supplied array that isolates which verts participate in the Flex collider Vector3 vecVert = _oMeshMorphResult._memVerts.L[nVertWholeMesh]; vecVert -= _oMeshMorphResult._memNormals.L[nVertWholeMesh] * nDistFlexColliderShrink; // 'Shrink' each particle a fraction of the way inverse to its normal so it 'shrinks' inside the body to account for particle-to-particle distance and make it appear that cloth can be right over body skin. _oFlexParticles.m_particles[nParticle].pos = vecVert; } _bParticlePositionsUpdated = false; } }
//-------------------------------------------------------------------------- UPDATE public virtual void PreContainerUpdate(uFlex.FlexSolver solver, uFlex.FlexContainer cntr, uFlex.FlexParameters parameters) { if (_bSoftBodyInReset_HACK) //###OPT? Reset_SoftBody_DoReset(); }
//-------------------------------------------------------------------------- UPDATE public override void PreContainerUpdate(uFlex.FlexSolver solver, uFlex.FlexContainer cntr, uFlex.FlexParameters parameters) { base.PreContainerUpdate(solver, cntr, parameters); _oPinnedParticles.UpdatePositionsOfPinnedParticles(); // Update the position of our pinned particles so this softbody follows the surface of its body //=== Bake the skinned softbody into a regular mesh (so we can update edge-of-softbody position and normals to pertinent rim verts === _oFlexGeneratedSMR.BakeMesh(_oFlexGeneratedSMR_BakedMesh); //###OPT!!! Check how expensive this is. Is there a way for us to move verts & normals straight from skinned mesh from Flex? (Have not found a way so far) Vector3[] aVertsFlexGenerated = _oFlexGeneratedSMR_BakedMesh.vertices; Vector3[] aNormalsFlexGenerated = _oFlexGeneratedSMR_BakedMesh.normals; UpdateVisibleSoftBodySurfaceMesh(ref aVertsFlexGenerated, ref aNormalsFlexGenerated); // Call base class to update the visible mesh (and manually adjust sb rim verts for seamless connection to main skinned body) }
List<int> aShapeVerts = new List<int>(); // Array of which vert / particle is also a shape #endregion Fields #region Methods ////=== Obtain the collections for the edge and non-edge verts that Blender calculated for us === //CUtility.BlenderSerialize_GetSerializableCollection_INT("'CBody'", _sBlenderInstancePath_CSoftBody_FullyQualfied + ".SerializeCollection_aShapeVerts()", out aShapeVerts); //CUtility.BlenderSerialize_GetSerializableCollection_INT("'CBody'", _sBlenderInstancePath_CSoftBody_FullyQualfied + ".SerializeCollection_aShapeParticleIndices()", out aShapeParticleIndices); //CUtility.BlenderSerialize_GetSerializableCollection_INT("'CBody'", _sBlenderInstancePath_CSoftBody_FullyQualfied + ".SerializeCollection_aShapeParticleCutoffs()", out aShapeParticleCutoffs); ////=== Define Flex particles from Blender mesh made for Flex === //int nParticles = GetNumVerts(); //_oFlexParticles = CUtility.FindOrCreateComponent(gameObject, typeof(uFlex.FlexParticles)) as uFlex.FlexParticles; //_oFlexParticles.m_particlesCount = nParticles; //_oFlexParticles.m_particles = new uFlex.Particle[nParticles]; //_oFlexParticles.m_colours = new Color[nParticles]; //_oFlexParticles.m_velocities = new Vector3[nParticles]; //_oFlexParticles.m_densities = new float[nParticles]; //_oFlexParticles.m_particlesActivity = new bool[nParticles]; //_oFlexParticles.m_colour = Color.green; //###TODO: Colors! //_oFlexParticles.m_interactionType = uFlex.FlexInteractionType.SelfCollideFiltered; //_oFlexParticles.m_collisionGroup = -1; ////part.m_bounds.SetMinMax(min, max); //###IMPROVE Bounds? //for (int nParticle = 0; nParticle < nParticles; nParticle++) { // _oFlexParticles.m_particles[nParticle].pos = _memVerts.L[nParticle]; // //_oFlexParticles.m_particles[nParticle].invMass = 1; //###TODO: Mass // //_oFlexParticles.m_particles[nParticle].invMass = 0; //###TODO: Mass // _oFlexParticles.m_colours[nParticle] = _oFlexParticles.m_colour; // _oFlexParticles.m_particlesActivity[nParticle] = true; //} ////=== Define Flex shapes from the Blender particles that have been set as shapes too === //int nShapes = aShapeVerts.Count; //_oFlexShapeMatching = CUtility.FindOrCreateComponent(gameObject, typeof(uFlex.FlexShapeMatching)) as uFlex.FlexShapeMatching; //_oFlexShapeMatching.m_shapesCount = nShapes; //_oFlexShapeMatching.m_shapeIndicesCount = aShapeParticleIndices.Count; //_oFlexShapeMatching.m_shapeIndices = aShapeParticleIndices.ToArray(); //###LEARN: How to convert a list to a straight .Net array. //_oFlexShapeMatching.m_shapeOffsets = aShapeParticleCutoffs.ToArray(); //_oFlexShapeMatching.m_shapeCenters = new Vector3[nShapes]; //_oFlexShapeMatching.m_shapeCoefficients = new float[nShapes]; //_oFlexShapeMatching.m_shapeTranslations = new Vector3[nShapes]; //_oFlexShapeMatching.m_shapeRotations = new Quaternion[nShapes]; //_oFlexShapeMatching.m_shapeRestPositions = new Vector3[_oFlexShapeMatching.m_shapeIndicesCount]; ////=== Calculate shape centers from attached particles === ////int nShape = 0; ////foreach (int nShapeParticle in aShapeVerts) { //// _oFlexShapeMatching.m_shapeCoefficients[nShape] = 0.05f; //###NOW### //// _oFlexShapeMatching.m_shapeCenters[nShape] = _oFlexParticles.m_particles[nShapeParticle].pos; //// nShape++; ////} //int nShapeStart = 0; //for (int nShape = 0; nShape < _oFlexShapeMatching.m_shapesCount; nShape++) { // _oFlexShapeMatching.m_shapeCoefficients[nShape] = 0.05f; //###NOW### Calculate shape center here or just accept particle pos? // int nShapeEnd = _oFlexShapeMatching.m_shapeOffsets[nShape]; // Vector3 vecCenter = Vector3.zero; // for (int nShapeIndex = nShapeStart; nShapeIndex < nShapeEnd; ++nShapeIndex) { // int nParticle = _oFlexShapeMatching.m_shapeIndices[nShapeIndex]; // Vector3 vecParticlePos = _oFlexParticles.m_particles[nParticle].pos; // remap indices and create local space positions for each shape // vecCenter += vecParticlePos; // } // vecCenter /= (nShapeEnd - nShapeStart); // _oFlexShapeMatching.m_shapeCenters[nShape] = vecCenter; // nShapeStart = nShapeEnd; //} ////=== Set the shape rest positions === //nShapeStart = 0; //int nShapeIndexOffset = 0; //for (int nShape = 0; nShape < _oFlexShapeMatching.m_shapesCount; nShape++) { // int nShapeEnd = _oFlexShapeMatching.m_shapeOffsets[nShape]; // for (int nShapeIndex = nShapeStart; nShapeIndex < nShapeEnd; ++nShapeIndex) { // int nParticle = _oFlexShapeMatching.m_shapeIndices[nShapeIndex]; // Vector3 vecParticle = _oFlexParticles.m_particles[nParticle].pos; // remap indices and create local space positions for each shape // _oFlexShapeMatching.m_shapeRestPositions[nShapeIndexOffset] = vecParticle - _oFlexShapeMatching.m_shapeCenters[nShape]; // nShapeIndexOffset++; // } // nShapeStart = nShapeEnd; //} //foreach (int nShapeParticle in aShapeVerts) { // _oFlexParticles.m_particles[nShapeParticle].invMass = 1; //###NOW### //} ////=== Add particle renderer === //_oFlexParticlesRenderer = CUtility.FindOrCreateComponent(gameObject, typeof(uFlex.FlexParticlesRenderer)) as uFlex.FlexParticlesRenderer; //_oFlexParticlesRenderer.m_size = CGame.INSTANCE.particleSpacing; //_oFlexParticlesRenderer.m_radius = _oFlexParticlesRenderer.m_size / 2.0f; //_oFlexParticlesRenderer.enabled = false; // Hidden by default public override void PreContainerUpdate(uFlex.FlexSolver solver, uFlex.FlexContainer cntr, uFlex.FlexParameters parameters) { base.PreContainerUpdate(solver, cntr, parameters); //////=== Iterate through all softbody edge verts to update their position and normals. This is critical for a 'seamless connection' between the softbody presentation mesh and the main skinned body === ////Vector3[] aVertsRimBaked = _oMeshSoftBodyRim._oMeshBaked.vertices; // Obtain the verts and normals from baked rim mesh so we can manually set rim verts & normals for seamless connection to main body mesh. ////Vector3[] aNormalsRimBaked = _oMeshSoftBodyRim._oMeshBaked.normals; ////for (int nIndex = 0; nIndex < _aMapRimVerts.Count;) { // Iterate through the twin vert flattened map... //// ushort nVertMesh = _aMapRimVerts[nIndex++]; // The simple list has been flattened into <nVertMesh0, nVertRim0>, <nVertMesh1, nVertRim1>, etc //// ushort nVertRim = _aMapRimVerts[nIndex++]; //// _oFlexParticles.m_particles[nVertMesh].pos = aVertsRimBaked[nVertRim]; //// _oFlexParticles.m_particles[nVertMesh].invMass = 0; //###NOW### //// //aVertsFlexGenerated [nVertMesh] = aVertsRimBaked [nVertRim]; //// //aNormalsFlexGenerated[nVertMesh] = aNormalsRimBaked[nVertRim]; ////} ////=== Set the visible mesh verts to the particle verts (1:1 ratio) === //Vector3[] aVertsPresentation = _oMeshNow.vertices; //for (int nVert = 0; nVert < GetNumVerts(); nVert++) // aVertsPresentation[nVert] = _oFlexParticles.m_particles[nVert].pos; //_oMeshNow.vertices = aVertsPresentation; //_oMeshNow.RecalculateNormals(); //###NOW### //_oMeshNow.RecalculateBounds(); //###NOW### }
public void PreContainerUpdate(uFlex.FlexSolver solver, uFlex.FlexContainer cntr, uFlex.FlexParameters parameters) { }