GameObject CreateMirrorObject(SpaceShipConnector parentConnector, GameObject childObj, SpaceShipPart childPart, SpaceShipConnector childConnector) { // Check if a mirror connector exists int mirrorConnectorIndex = getMirrorConnectorIndex(parentConnector); if (mirrorConnectorIndex == -1) { return(null); } // Instanciate the same object and mirror its matrix GameObject mirrorObj = Instantiate(childObj); mirrorObj.transform.position = Vector3.Scale(mirrorObj.transform.position, mirrorVector); mirrorObj.transform.localScale = Vector3.Scale(mirrorObj.transform.localScale, mirrorVector); mirrorObj.transform.rotation = Quaternion.Euler(Vector3.Scale(mirrorObj.transform.rotation.eulerAngles, new Vector3(1, -1, -1))); ParticleSystem[] psList = mirrorObj.GetComponentsInChildren <ParticleSystem>(); foreach (ParticleSystem ps in psList) { ps.transform.localScale = Vector3.Scale(ps.transform.localScale, mirrorVector); } // removeOpenConnector(mirrorConnectorIndex); // Add mirrored child part connectors to open connectors list AppendChildObjectConnectors(mirrorObj, childPart, childConnector); return(mirrorObj); }
SpaceShipConnector pickConnector() { int targetWeight = (int)(UnityEngine.Random.value * openConnectorsWeight); SpaceShipConnector connector = null; float weightAccum = 0; int index = 0; for (; index < openConnectors.Count; ++index) { connector = openConnectors[index]; weightAccum += connector.weight; if (weightAccum >= targetWeight) { break; } } if (debug) { Debug.Log("parent connector: " + index); } return(connector); }
SpaceShipPart LoadPart(GameObject mesh) { SpaceShipPart part = new SpaceShipPart(); part.name = mesh.name; part.mesh = mesh.GetComponentInChildren <MeshFilter>().sharedMesh; part.connectors = new List <SpaceShipConnector>(); // Extract connectors from vertex colors Color[] colors = part.mesh.colors; int[] tris = part.mesh.triangles; Vector3[] verts = part.mesh.vertices; Vector3[] normals = part.mesh.normals; Vector3 connectorPosition = new Vector3(); Vector3 connectorNormal = new Vector3(); //Debug.Log(colors); for (int i = 0; i < tris.Length;) { if (colors[tris[i]] != Color.green) { i += 3; continue; } connectorNormal.Set(0, 0, 0); connectorPosition.Set(0, 0, 0); for (int v = i + 6; i < v; ++i) { int vIndex = tris[i]; connectorPosition += verts[vIndex]; connectorNormal += normals[vIndex]; } connectorPosition /= 6; connectorNormal /= 6; SpaceShipConnector c = new SpaceShipConnector(); c.position = connectorPosition; c.normal = connectorNormal.normalized; part.connectors.Add(c); } part.obj = Instantiate(mesh); part.obj.SetActive(false); MeshRenderer renderer = part.obj.GetComponentInChildren <MeshRenderer>(); renderer.receiveShadows = false; renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; part.obj.transform.parent = generatedParts.transform; return(part); }
void AppendChildObjectConnectors(GameObject childObj, SpaceShipPart childPart, SpaceShipConnector usedChildConnector) { foreach (SpaceShipConnector cnt in childPart.connectors) { if (cnt == usedChildConnector) { continue; } SpaceShipConnector worldCnt = new SpaceShipConnector(); worldCnt.normal = childObj.transform.TransformDirection(cnt.normal).normalized; worldCnt.position = childObj.transform.TransformPoint(cnt.position); addOpenConnector(worldCnt); } }
GameObject CreateChildObject(GameObject parentObj, SpaceShipConnector parentConnector, SpaceShipPart childPart, SpaceShipConnector childConnector, bool addChildConnectors, bool zRotOnly) { GameObject childObj = CreateObject(childPart); //DebugConnectors(childObj, childPart, cc); AssembleParts(parentObj, parentConnector, childObj, childConnector, zRotOnly); // Add child part connectors to open connectors list if (addChildConnectors) { AppendChildObjectConnectors(childObj, childPart, childConnector); } removeOpenConnector(parentConnector); return(childObj); }
int getMirrorConnectorIndex(SpaceShipConnector refCnt) { Vector3 mirrorPos = Vector3.Scale(refCnt.position, mirrorVector); int mirrorConnectorIndex = -1; for (int index = 0; index < openConnectors.Count; ++index) { SpaceShipConnector cnt = openConnectors[index]; if (cnt != refCnt && Vector3.SqrMagnitude(cnt.position - mirrorPos) < 0.0001) { mirrorConnectorIndex = index; break; } } return(mirrorConnectorIndex); }
private void addOpenConnector(SpaceShipConnector cnt) { float zness = Mathf.Abs(Vector3.Dot(cnt.normal, Vector3.forward)); cnt.weight = 1 + zness * uniformity * 100; openConnectorsWeight += cnt.weight; int index = 0; for (; index < openConnectors.Count; ++index) { if (openConnectors[index].weight < cnt.weight) { break; } } openConnectors.Insert(index, cnt); }
void DebugConnectors(GameObject obj, SpaceShipPart part, int selected) { for (int i = 0; i < part.connectors.Count; ++i) { SpaceShipConnector c = part.connectors[i]; float angle = Vector3.Angle(Vector3.up, c.normal); Vector3 axe = Vector3.Cross(Vector3.up, c.normal); Quaternion q = Quaternion.AngleAxis(angle, axe); if (debug) { GameObject dgo = (GameObject)Instantiate(debugConnectorObject, c.position, q); dgo.transform.SetParent(obj.transform); foreach (MeshRenderer r in dgo.GetComponentsInChildren <MeshRenderer>()) { r.material.color = i == selected ? Color.yellow : Color.gray; } } } }
private void generateArsenal(GameObject mainObj, float arsenalValue, GameObject partsGo) { int pointsCount = (int)(arsenalValue * openConnectors.Count); for (int i = 0; i < pointsCount; ++i) { var partsList = UnityEngine.Random.value > 0.5 ? softpoints : hardpoints; var childPart = partsList[(int)(UnityEngine.Random.value * (partsList.Count - 1))]; SpaceShipConnector parentConnector = pickConnector(); SpaceShipConnector childConnector = childPart.connectors[(int)(UnityEngine.Random.value * (childPart.connectors.Count - 1))]; if (parentConnector != null) { GameObject childObj = CreateChildObject(mainObj, parentConnector, childPart, childConnector, true, false); childObj.transform.SetParent(partsGo.transform); } else { print("oups, no connector"); } } }
void AssembleParts(GameObject parentObj, SpaceShipConnector parentConnector, GameObject childObj, SpaceShipConnector childConnector, bool zRotOnly) { Vector3 childNormal = (childObj.transform.TransformDirection(childConnector.normal)).normalized; if (parentConnector == null) { print("alex"); } Vector3 parentNormal = parentConnector.normal.normalized; Vector3 parentPos = parentConnector.position; // ROTATE THE CHILD AROUDN THE GLOBAL Z AXIS TO MATCH THE PARENTMOUNT Vector3 childZ = (new Vector3(childNormal.x, childNormal.y, 0.0f)).normalized; Vector3 parentZ = (new Vector3(parentNormal.x, parentNormal.y, 0.0f)).normalized; bool zRotation = false; if (childZ.magnitude > 0.0f && parentZ.magnitude > 0.0f) { float angZ = Vector3.Angle(childZ, parentZ); Vector3 cross = Vector3.Cross(childZ, parentZ); float sign = Mathf.Sign(cross.z); // print(' angZ', math.degrees(angZ)) if (angZ > 0.0f && angZ < 180.0f) { childObj.transform.localRotation *= Quaternion.AngleAxis((180f - angZ * sign), Vector3.back); zRotation = true; // child.matrix_world = rotZ * child.matrix_world } else if (angZ == 0.0f) { childObj.transform.localRotation = Quaternion.AngleAxis(180f, Vector3.back); zRotation = true; } //childNormal = (childMount.normal * child.matrix_world).normalized() } if (!zRotOnly && zRotation == false) { // ROTATE THE CHILD AROUND THE GLOBAL X AXIS TO MATCH THE PARENTMOUNT Vector3 childX = (new Vector3(0.0f, childNormal.y, childNormal.z)).normalized; Vector3 parentX = (new Vector3(0.0f, parentNormal.y, parentNormal.z)).normalized; if (childX.magnitude > 0.0f && parentX.magnitude > 0.0f) { float angX = Vector3.Angle(childX, parentX); Vector3 cross = Vector3.Cross(childX, parentX); float sign = Mathf.Sign(cross.x); if (angX > 0.0f && angX < 180.0f) { childObj.transform.localRotation *= Quaternion.AngleAxis((180f - angX * sign), Vector3.left); childNormal = (childObj.transform.TransformDirection(childConnector.normal)).normalized; } } } Vector3 childY = (new Vector3(childNormal.x, 0.0f, childNormal.z)).normalized; Vector3 parentY = (new Vector3(parentNormal.x, 0.0f, parentNormal.z)).normalized; if (!zRotOnly && childY.magnitude > 0.0f && parentY.magnitude > 0.0f) { float angY = Vector3.Angle(childY, parentY); Vector3 cross = Vector3.Cross(childY, parentY); float sign = -Mathf.Sign(cross.y); if (angY > 0.0f && angY < 180.0f) { childObj.transform.localRotation *= Quaternion.AngleAxis(180f - angY * sign, Vector3.up); childNormal = (childObj.transform.TransformDirection(childConnector.normal)).normalized; } } // SET CHILD POSITION Vector3 childPos = childObj.transform.TransformPoint(childConnector.position); childObj.transform.localPosition = parentPos - childPos; }
private void removeOpenConnector(SpaceShipConnector cnt) { openConnectorsWeight -= cnt.weight; openConnectors.Remove(cnt); }
private GameObject generateRockets(GameObject mainObj, float rocketValue) { SpaceShipConnector selectedConnector = null; bool mirrored = false; // rear rocket, centered or mirrored foreach (SpaceShipConnector cnt in openConnectors) { if (cnt.normal.z <= 0.999) { continue; } int mirrorCntIndex = getMirrorConnectorIndex(cnt); if (Mathf.Abs(cnt.position.x) < 0.0001 && mirrorCntIndex == -1) { continue; } if (selectedConnector == null || cnt.position.z < selectedConnector.position.z) { selectedConnector = cnt; mirrored = mirrorCntIndex != -1; } } // Side rockets if (selectedConnector == null) { float selectedZDist = 0; foreach (SpaceShipConnector cnt in openConnectors) { if (Mathf.Abs(cnt.normal.z) >= 0.0001) { continue; } int mirrorCntIndex = getMirrorConnectorIndex(cnt); if (mirrorCntIndex == -1) { continue; } float distFromZAxis = (cnt.position - (new Vector3(0, 0, cnt.position.z))).sqrMagnitude; if (selectedConnector == null || distFromZAxis > selectedZDist) { selectedConnector = cnt; selectedZDist = distFromZAxis; mirrored = true; } } if (selectedConnector == null) { // rear rocket, single uncentered foreach (SpaceShipConnector cnt in openConnectors) { if (cnt.normal.z <= 0.999) { continue; } if (selectedConnector == null || cnt.position.z < selectedConnector.position.z) { selectedConnector = cnt; mirrored = false; } } if (selectedConnector == null) { if (debug) { Debug.Log("No rocket connector found"); } return(null); } if (debug) { Debug.Log("uncentered"); } } } GameObject rocketsGo = new GameObject(); rocketsGo.transform.parent = mainObj.transform; rocketsGo.name = "rockets"; SpaceShipPart rocketPart; if (mirrored) { rocketPart = siderockets[(int)(UnityEngine.Random.value * (siderockets.Count - 1))]; } else { rocketPart = rockets[(int)(UnityEngine.Random.value * (rockets.Count - 1))]; } GameObject rocketObj = CreateChildObject(mainObj, selectedConnector, rocketPart, rocketPart.connectors[0], false, true); rocketObj.transform.SetParent(rocketsGo.transform); if (mirrored) { GameObject mirrorObj = CreateMirrorObject(selectedConnector, rocketObj, rocketPart, rocketPart.connectors[0]); mirrorObj.transform.SetParent(rocketsGo.transform); } return(rocketsGo); }
/** * Generator */ public SpaceShip GenerateShip(char[] dna) { string dnaString = new string(dna); SpaceShip se = new SpaceShip(); int previousSeed = UnityEngine.Random.seed; UnityEngine.Random.seed = dnaString.GetHashCode(); // population, population density, GINI index (equity), nuclear, CO2, weapons and manufacture. float shipNormalizedLength = Mathf.Max((float)((int)dna[0] - 65) / 26.0f, 0); float scale = scaleRange.x + (shipNormalizedLength * (scaleRange.y - scaleRange.x)); int seed = dnaString.GetHashCode(); float normalizedDisp = Mathf.Max((float)((int)dna[5] - 65) / 26.0f, 0); int iterations = (int)(iterationsRange.x + (normalizedDisp * (iterationsRange.y - iterationsRange.x))); float uniformity = Mathf.Max((float)((int)dna[1] - 65) / 26.0f, 0); float arsenal = Mathf.Max((float)((int)dna[4] - 65) / 26.0f, 0); int rockets = Mathf.Max((int)dna[2] - 65, 0); float co2 = Mathf.Max((float)((int)dna[3] - 65) / 26.0f, 0); Mathf.Max((int)dna[3] - 65, 0); co2 = debrisRange.x + (co2 * (debrisRange.y - debrisRange.x)); print("dna: " + dnaString + " seed " + seed + ", " + "scale " + scale + ", " + "iterations " + iterations + ", " + "uniformity " + uniformity + ", " + "arsenal " + arsenal + ", " + "rockets " + rockets); int f = (int)(UnityEngine.Random.value * (hulls.Count - 1)); SpaceShipPart parentPart = hulls[f]; if (debug) { Debug.Log("parent hulls: " + f); } GameObject mainObj = new GameObject(); mainObj.name = "Generated Ship"; GameObject parentObj = CreateObject(parentPart); parentObj.transform.SetParent(mainObj.transform); GameObject partsGo = new GameObject(); partsGo.transform.parent = mainObj.transform; partsGo.name = "Arsenal"; se.renderer = parentObj.GetComponent <Renderer>(); mainObj.transform.parent = rootObject.transform; openConnectors = new List <SpaceShipConnector>(); openConnectorsWeight = 0; foreach (SpaceShipConnector cnt in parentPart.connectors) { addOpenConnector(cnt); } if (addRockets) { se.rockets = generateRockets(mainObj, rockets); } int depth = 0; while (depth++ < iterations) { // Pick a random parent connector if (openConnectors.Count == 0) { break; } SpaceShipConnector parentConnector = pickConnector(); // Pick a random child part SpaceShipPart childPart = null; int p = (int)(UnityEngine.Random.value * (parts.Count - 1)); if (debug) { Debug.Log("child part: " + p); } childPart = parts[p]; // Pick a random child connector SpaceShipConnector childConnector = pickChildConnector(childPart); if (parentConnector == null) { print("bob"); } // Create a child object and assemble the 2 parts GameObject childObj = CreateChildObject(parentObj, parentConnector, childPart, childConnector, true, false); childObj.transform.SetParent(partsGo.transform); //addedParts.Add(childObj); GameObject mirrorObj = CreateMirrorObject(parentConnector, childObj, childPart, childConnector); if (mirrorObj) { mirrorObj.transform.SetParent(partsGo.transform); //addedParts.Add(mirrorObj); } parentObj = childObj; parentPart = childPart; } generateArsenal(mainObj, arsenal, partsGo); openConnectors = null; if (combine) { Combine(mainObj); } if (computeObjectBounds) { BoxCollider collider = ComputeObjectBounds(mainObj); // Rescale Vector3 s = collider.bounds.size; print("scale " + scale); print("bounds " + s); float objectLength = Mathf.Max(s.x, Mathf.Max(s.y, s.z)); print("objectLength " + objectLength); float localScale = scale / objectLength; print("localScale " + localScale); mainObj.transform.localScale = new Vector3(localScale, localScale, localScale); } // Debug.Log("collider.bounds.size "+collider.bounds.size); mainObj.transform.Rotate(new Vector3(0, 180, 0)); currentMaterial = materials[UnityEngine.Random.Range(0, materials.Length)]; MeshRenderer mainObjRenderer = mainObj.GetComponentInChildren <MeshRenderer>(); if (mainObjRenderer != null) { if (debug) { mainObjRenderer.sharedMaterial = this.debugMaterial; } else { mainObjRenderer.sharedMaterial = currentMaterial; } } GameObject rocketsGo = se.rockets; if (rocketsGo) { for (int i = 0; i < rocketsGo.transform.childCount; i++) { GameObject go = rocketsGo.transform.GetChild(i).gameObject; MeshRenderer r = go.GetComponentInChildren <MeshRenderer>(); if (r != null) { if (debug) { r.sharedMaterial = this.debugMaterial; } else { r.sharedMaterial = currentMaterial; // r.material.color = UnityEngine.Random.ColorHSV(0, 1, 0, 1,0,1); } } } } if (partsGo) { for (int i = 0; i < partsGo.transform.childCount; i++) { GameObject go = partsGo.transform.GetChild(i).gameObject; MeshRenderer r = go.GetComponentInChildren <MeshRenderer>(); if (r != null) { if (debug) { r.sharedMaterial = this.debugMaterial; } else { r.sharedMaterial = currentMaterial; } } } } se.main = mainObj; se.parts = partsGo; if (debrisParticleSystem != null) { ParticleSystem.EmissionModule pe = debrisParticleSystem.emission; pe.rateOverTime = co2; debrisParticleSystem.Clear(); debrisParticleSystem.Simulate(debrisParticleSystem.main.duration); debrisParticleSystem.Play(); ParticleSystem.ShapeModule ps = debrisParticleSystem.shape; Bounds b = se.main.GetComponent <Collider>().bounds; ps.angle = 27; ps.length = b.size.z; Vector3 tp = debrisParticleSystem.transform.localPosition; tp.z = b.size.z * 0.25f; debrisParticleSystem.transform.localPosition = tp; } return(se); }