private void ProcessSprings(bool sizeChanged) { if (sizeChanged) { m_springIndices = new int[m_springsCount * 2]; m_springRestLengths = new float[m_springsCount]; m_springCoefficients = new float[m_springsCount]; } for (int iId = 0; iId < m_flexGameObjects.Count && iId < m_activeInstacesCount; iId++) { FlexParticles particles = m_flexGameObjects[iId].GetComponent <FlexParticles>(); FlexSprings springs = m_flexGameObjects[iId].GetComponent <FlexSprings>(); if (springs && springs.enabled) { for (int sId = 0; sId < springs.m_springsCount; sId++) { m_springIndices[sId * 2 + 0 + springs.m_springsIndex * 2] = springs.m_springIndices[sId * 2 + 0] + particles.m_particlesIndex; m_springIndices[sId * 2 + 1 + springs.m_springsIndex * 2] = springs.m_springIndices[sId * 2 + 1] + particles.m_particlesIndex; m_springRestLengths[sId + springs.m_springsIndex] = springs.m_springRestLengths[sId]; m_springCoefficients[sId + springs.m_springsIndex] = springs.m_springCoefficients[sId]; } } } }
void Start() { m_flexParticles = GetComponent <FlexParticles>(); m_flexSprings = GetComponent <FlexSprings>(); m_flexTriangles = GetComponent <FlexTriangles>(); m_flexInflatable = GetComponent <FlexInflatable>(); m_mesh = GetComponent <MeshFilter>().mesh; m_vertices = m_mesh.vertices; m_triangles = m_mesh.triangles; m_uvs = m_mesh.uv; m_origUvs = m_mesh.uv; //if(m_uvs.Length == 0) //{ // m_uvs = new Vector2[m_vertices.Length]; // m_origUvs = new Vector2[m_vertices.Length]; //} //texture seams (duplicate vertices) are currently not supported during tearing if (m_mesh.vertexCount != m_flexParticles.m_particlesCount) { Debug.LogWarning("Closed mesh with texture seams detected. This is currently not supported by uFlex v0.5. You may still tear closed meshes but plase remove any textures from object's material as UV mapping will be removed"); m_mesh = new Mesh(); m_vertices = new Vector3[m_flexParticles.m_particlesCount]; // m_uvs = new Vector2[m_flexParticles.m_particlesCount]; m_uvs = new Vector2[0]; for (int i = 0; i < m_flexParticles.m_particlesCount; i++) { m_vertices[i] = transform.InverseTransformPoint(m_flexParticles.m_particles[i].pos); // m_uvs[i] = m_origUvs[mappingsRev[i]]; } m_mesh.vertices = m_vertices; // m_mesh.uv = m_uvs; m_mesh.triangles = m_flexTriangles.m_triangleIndices; m_mesh.RecalculateNormals(); m_mesh.RecalculateBounds(); GetComponent <MeshFilter>().mesh = m_mesh; } this.mappings = new int[m_mesh.vertexCount * 2]; this.mappingsRev = new int[m_mesh.vertexCount * 2]; for (int i = 0; i < m_mesh.vertexCount; i++) { Vector3 v = m_vertices[i]; bool mappingFound = false; float minDistance = 100000.0f; int minId = 0; for (int j = 0; j < m_flexParticles.m_particlesCount; j++) { // float dist = Vector3.Distance(v, transform.InverseTransformPoint(m_flexBody.m_particles[j])); float dist = Vector3.Distance(v, m_flexParticles.m_particles[j].pos); if (dist < minDistance) { minDistance = dist; minId = j; } } if (minDistance < this.m_maxSearchDistance) { this.mappings[i] = minId; this.mappingsRev[minId] = i; mappingFound = true; } if (!mappingFound) { Debug.Log("MappingMissing: " + i); } } //int vertexCount = m_mesh.vertexCount; //int[] triangles = m_mesh.triangles; //int triIndicesCount = triangles.Length; //int trianglesCount = triIndicesCount / 3; //int[] uniqueVerticesIds = new int[vertexCount]; //int[] origToUniqueVertMapping = new int[vertexCount]; //int uniqueVerticesCount = FlexExt.flexExtCreateWeldedMeshIndices(m_vertices, vertexCount, uniqueVerticesIds, origToUniqueVertMapping, 0.00001f); //Debug.Log("Welding Mesh: " + uniqueVerticesCount + "/" + vertexCount); //Vector4[] uniqueVertices4 = new Vector4[uniqueVerticesCount]; //for (int i = 0; i < uniqueVerticesCount; i++) //{ // uniqueVertices4[i] = m_vertices[uniqueVerticesIds[i]]; //} //int[] uniqueTriangles = new int[trianglesCount * 3]; //for (int i = 0; i < trianglesCount * 3; i++) //{ // uniqueTriangles[i] = origToUniqueVertMapping[triangles[i]]; //} //m_clothMeshPtr = uFlexAPI.uFlexCreateTearableClothMesh(uniqueVertices4, uniqueVerticesCount, uniqueVerticesCount * 2, uniqueTriangles, trianglesCount, m_stretchKs, m_bendKs, 0); m_clothMeshPtr = uFlexAPI.uFlexCreateTearableClothMesh(m_flexParticles.m_particles, m_flexParticles.m_particlesCount, m_flexParticles.m_particlesCount * 2, m_flexTriangles.m_triangleIndices, m_flexTriangles.m_trianglesCount, m_stretchKs, m_bendKs, 0.0f); }
private void UpdateCounts() { m_particlesCount = 0; m_springsCount = 0; m_shapesCount = 0; m_shapeIndicesCount = 0; m_trianglesCount = 0; m_inflatablesCount = 0; m_activeInstacesCount = 0; for (int iId = 0; iId < m_flexGameObjects.Count; iId++) { m_flexGameObjects[iId].m_instanceId = iId; FlexParticles particles = m_flexGameObjects[iId].GetComponent <FlexParticles>(); FlexTriangles triangles = m_flexGameObjects[iId].GetComponent <FlexTriangles>(); FlexSprings springs = m_flexGameObjects[iId].GetComponent <FlexSprings>(); FlexShapeMatching shapes = m_flexGameObjects[iId].GetComponent <FlexShapeMatching>(); FlexInflatable inflatable = m_flexGameObjects[iId].GetComponent <FlexInflatable>(); if (particles && particles.enabled) { if (m_particlesCount + particles.m_particlesCount <= m_maxParticlesCount) { particles.m_particlesIndex = m_particlesCount; m_particlesCount += particles.m_particlesCount; m_activeInstacesCount++; } else { Debug.Log("Current particles count exceeded their maximum number for this container"); } } if (springs && springs.enabled) { springs.m_springsIndex = m_springsCount; m_springsCount += springs.m_springsCount; } if (shapes && shapes.enabled) { shapes.m_shapesIndex = m_shapesCount; shapes.m_shapesIndicesIndex = m_shapeIndicesCount; m_shapesCount += shapes.m_shapesCount; m_shapeIndicesCount += shapes.m_shapeIndicesCount; } if (triangles && triangles.enabled) { triangles.m_trianglesIndex = m_trianglesCount; m_trianglesCount += triangles.m_trianglesCount; } if (inflatable && inflatable.enabled) { inflatable.m_inflatableIndex = m_inflatablesCount; m_inflatablesCount++; } } }
void OnGUI() { bool hasFlexComponent = false; GUILayout.Label("uFlex v0.5 - Developer Utils", EditorStyles.whiteLargeLabel); EditorGUILayout.HelpBox("This window is for advanced users. Improper use may break the uFlex objects.", MessageType.Warning); if (Selection.activeGameObject) { GUILayout.Label(Selection.activeGameObject.name, EditorStyles.boldLabel); FlexParticles particles = Selection.activeGameObject.GetComponent <FlexParticles>(); if (particles) { EditorGUILayout.Separator(); GUILayout.Label("Particles", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); m_mass = EditorGUILayout.FloatField("Particles Masses: ", m_mass); if (GUILayout.Button("Set ")) { Debug.Log("Mass Set To " + m_mass); float invMass = 1.0f / m_mass; for (int i = 0; i < particles.m_particlesCount; i++) { //skip locked particles if (particles.m_particles[i].invMass == 0) { continue; } particles.m_particles[i].invMass = invMass; } SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Apply Color")) { for (int i = 0; i < particles.m_particlesCount; i++) { particles.m_colours[i] = particles.m_colour; } SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } if (GUILayout.Button("Randomize Colors")) { for (int i = 0; i < particles.m_particlesCount; i++) { // particles.m_colours[i] = new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value, 1.0f); particles.m_colours[i] = UnityEngine.Random.ColorHSV(0.0f, 1.0f, 0.0f, 1.0f, 0.5f, 1.0f); } SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Randomize Spacing")) { for (int i = 0; i < particles.m_particlesCount; i++) { particles.m_particles[i].pos += new Vector3(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value) * 0.1f; } SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } if (GUILayout.Button("Activate All")) { particles.m_particlesActivity = new bool[particles.m_particlesCount]; for (int i = 0; i < particles.m_particlesCount; i++) { particles.m_particlesActivity[i] = true; } SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } if (GUILayout.Button("Deactivate All")) { particles.m_particlesActivity = new bool[particles.m_particlesCount]; for (int i = 0; i < particles.m_particlesCount; i++) { particles.m_particlesActivity[i] = false; } SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } //if (GUILayout.Button("Deactivate Half")) //{ // particles.m_particlesActivity = new bool[particles.m_particlesCount]; // for (int i = 0; i < particles.m_particlesCount / 2; i++) // { // particles.m_particlesActivity[i] = true; // } // for (int i = particles.m_particlesCount / 2; i < particles.m_particlesCount; i++) // { // particles.m_particlesActivity[i] = false; // } // SceneView.RepaintAll(); // EditorUtility.SetDirty(particles); //} if (GUILayout.Button("Upgrade to v0.5")) { particles.m_densities = new float[particles.m_maxParticlesCount]; particles.m_velocities = new Vector3[particles.m_maxParticlesCount]; particles.m_phases = new int[particles.m_maxParticlesCount]; particles.m_restParticles = new Particle[particles.m_maxParticlesCount]; particles.m_smoothedParticles = new Particle[particles.m_maxParticlesCount]; particles.m_particlesActivity = new bool[particles.m_maxParticlesCount]; int phase = Flex.MakePhase(particles.m_collisionGroup, (int)particles.m_interactionType); for (int i = 0; i < particles.m_particlesCount; i++) { particles.m_velocities[i] = particles.m_initialVelocity; particles.m_particlesActivity[i] = true; particles.m_phases[i] = phase; particles.m_restParticles[i] = particles.m_particles[i]; particles.m_smoothedParticles[i] = particles.m_particles[i]; } SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } if (GUILayout.Button("Add FlexRopeMesh")) { FlexRopeMesh frm = Selection.activeGameObject.AddComponent <FlexRopeMesh>(); frm.m_particles = particles; frm.InitRope(particles.m_particlesCount); MeshFilter meshFilter = Selection.activeGameObject.AddComponent <MeshFilter>(); meshFilter.sharedMesh = frm.m_mesh; MeshRenderer rend = Selection.activeGameObject.AddComponent <MeshRenderer>(); Material mat = new Material(Shader.Find("Diffuse")); mat.name = "RopeMat"; mat.color = Color.yellow; rend.material = mat; SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } hasFlexComponent = true; } FlexSprings springs = Selection.activeGameObject.GetComponent <FlexSprings>(); if (springs) { EditorGUILayout.Separator(); GUILayout.Label("Springs", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Add Long Range Attachments to Rope")) { int ropeSegments = particles.m_particlesCount - 1; float restLength = Vector3.Distance(particles.m_particles[0].pos, particles.m_particles[1].pos); //distance + bend + tether (long range attachments) int springsCount = ropeSegments + (ropeSegments - 1) + ropeSegments; springs.m_springsCount = springsCount; Array.Resize <int>(ref springs.m_springIndices, springsCount * 2); Array.Resize <float>(ref springs.m_springCoefficients, springsCount); Array.Resize <float>(ref springs.m_springRestLengths, springsCount); for (int i = 0; i < ropeSegments; i++) { springs.m_springIndices[(ropeSegments + ropeSegments - 1) * 2 + i * 2 + 0] = 0; springs.m_springIndices[(ropeSegments + ropeSegments - 1) * 2 + i * 2 + 1] = i + 1; //negative stiffness means tether constraints //(i.e. prevents spring stretch but not its compression) springs.m_springCoefficients[(ropeSegments + ropeSegments - 1) + i] = -0.001f; springs.m_springRestLengths[(ropeSegments + ropeSegments - 1) + i] = i * restLength; } } EditorGUILayout.EndHorizontal(); } FlexShapeMatching shapes = Selection.activeGameObject.GetComponent <FlexShapeMatching>(); if (shapes) { EditorGUILayout.Separator(); GUILayout.Label("Shapes", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); m_clusterStiffness = EditorGUILayout.FloatField("Clusters Stiffness: ", m_clusterStiffness); if (GUILayout.Button("Set")) { for (int i = 0; i < shapes.m_shapesCount; i++) { shapes.m_shapeCoefficients[i] = m_clusterStiffness; } Debug.Log("Clusters Ks Set To " + m_clusterStiffness); SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); GUILayout.Label("Skinning"); EditorGUILayout.BeginHorizontal(); m_skinFalloff = EditorGUILayout.FloatField("Falloff: ", m_skinFalloff); m_skinMaxDist = EditorGUILayout.FloatField("Max Distance: ", m_skinMaxDist); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); inputMesh = EditorGUILayout.ObjectField(new GUIContent("Input Mesh", "The input mesh"), inputMesh, typeof(Mesh), true) as Mesh; if (GUILayout.Button("Generate Skinning") && inputMesh) { Vector3[] vertices = inputMesh.vertices; float[] skinWeights = new float[inputMesh.vertexCount * 4]; int[] skinIndices = new int[inputMesh.vertexCount * 4]; FlexExt.flexExtCreateSoftMeshSkinning(vertices, inputMesh.vertexCount, shapes.m_shapeCenters, shapes.m_shapesCount, m_skinFalloff, m_skinMaxDist, skinWeights, skinIndices); Mesh mesh = new Mesh(); mesh.name = this.inputMesh.name + "FlexMesh"; mesh.vertices = this.inputMesh.vertices; mesh.triangles = this.inputMesh.triangles; mesh.normals = this.inputMesh.normals; mesh.uv = this.inputMesh.uv; Transform[] bones = new Transform[shapes.m_shapesCount]; BoneWeight[] boneWeights = new BoneWeight[this.inputMesh.vertexCount]; Matrix4x4[] bindPoses = new Matrix4x4[shapes.m_shapesCount]; Vector3[] rigidRestPoses = new Vector3[shapes.m_shapesCount]; for (int i = 0; i < shapes.m_shapesCount; i++) { rigidRestPoses[i] = shapes.m_shapeCenters[i]; bones[i] = new GameObject("FlexShape_" + i).transform; bones[i].parent = Selection.activeGameObject.transform; bones[i].localPosition = shapes.m_shapeCenters[i]; bones[i].localRotation = Quaternion.identity; bindPoses[i] = bones[i].worldToLocalMatrix * Selection.activeGameObject.transform.localToWorldMatrix; } for (int i = 0; i < this.inputMesh.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/" + this.inputMesh.name + "FlexMesh.asset"); AssetDatabase.SaveAssets(); FlexSkinnedMesh skin = Selection.activeGameObject.AddComponent <FlexSkinnedMesh>(); skin.m_bones = bones; skin.m_boneWeights = boneWeights; skin.m_bindPoses = bindPoses; SkinnedMeshRenderer rend = Selection.activeGameObject.AddComponent <SkinnedMeshRenderer>(); rend.sharedMesh = mesh; // rend.sharedMesh = this.inputMesh; rend.updateWhenOffscreen = true; rend.quality = SkinQuality.Bone4; rend.bones = bones; SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Upgrade to v0.5")) { int shapeIndex = 0; int shapeIndexOffset = 0; shapes.m_shapeTranslations = new Vector3[shapes.m_shapesCount]; shapes.m_shapeRotations = new Quaternion[shapes.m_shapesCount]; shapes.m_shapeRestPositions = new Vector3[shapes.m_shapeIndicesCount]; int shapeStart = 0; for (int s = 0; s < shapes.m_shapesCount; s++) { shapes.m_shapeTranslations[s] = new Vector3(); shapes.m_shapeRotations[s] = Quaternion.identity; // int indexOffset = shapeIndexOffset; //m_shapeOffsets[shapeIndex + 1] = shapes.m_shapeOffsets[s] + indexOffset; //m_shapeCoefficients[shapeIndex] = shapes.m_shapeCoefficients[s]; //m_shapeTranslations[shapeIndex] = shapes.m_shapeTranslations[s]; //m_shapeRotations[shapeIndex] = shapes.m_shapeRotations[s]; 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.m_particles[p].pos; shapes.m_shapeRestPositions[shapeIndexOffset] = pos - shapes.m_shapeCenters[s]; // m_shapeIndices[shapeIndexOffset] = shapes.m_shapeIndices[i] + particles.m_particlesIndex; shapeIndexOffset++; } shapeStart = shapeEnd; } SceneView.RepaintAll(); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } hasFlexComponent = true; } } if (!hasFlexComponent) { GUILayout.Label("Select GameObject with Flex Components", EditorStyles.boldLabel); } }