private GameObject CreateLODModels() { GameObject retn = new GameObject("Detail Root"); BoxCollider collider = retn.AddComponent <BoxCollider>(); collider.size = model.GetBoundingBoxSize(); for (int i = 0; i < model.DetailLevels; i++) { SubObject subObject = model.GetDetailLevel(i); GameObject go = CreateRenderableGameObject(subObject); go.transform.parent = retn.transform; } if (model.DetailLevels > 1) { LODGroup lodGroup = retn.AddComponent <LODGroup>(); LOD[] lods = new LOD[model.DetailLevels]; for (int i = 0; i < model.DetailLevels; i++) { lods[i] = new LOD(1f / (i + 1), retn.transform.GetChild(i).GetComponents <Renderer>()); } lodGroup.SetLODs(lods); lodGroup.RecalculateBounds(); } return(retn); }
void Start() { group = gameObject.AddComponent <LODGroup>(); LOD[] lods = new LOD[4]; int i = 0; while (i < 4) { PrimitiveType primType = PrimitiveType.Cube; if (i == 1) { primType = PrimitiveType.Capsule; } if (i == 2) { primType = PrimitiveType.Sphere; } if (i == 3) { primType = PrimitiveType.Cylinder; } GameObject go = GameObject.CreatePrimitive(primType); go.transform.parent = gameObject.transform; Renderer[] renderers = new Renderer[1]; renderers[0] = go.renderer; lods[i] = new LOD(1.0F / (i + 1), renderers); i++; } group.SetLODS(lods); group.RecalculateBounds(); }
void SetCullingPercents() { if (cullPercent > 1.0f) { cullPercent = 1.0f; } if (cullPercent < 0.0f) { cullPercent = 0.0f; } if (Selection.objects == null) { Debug.Log("Nothing Selected!"); return; } foreach (GameObject g in Selection.objects) { if (g.GetComponent <LODGroup>() == null) { return; } LODGroup group = g.GetComponent <LODGroup>(); LOD[] lods = group.GetLODs(); Renderer[] renderers = lods[0].renderers; lods[0] = new LOD(cullPercent, renderers); group.SetLODs(lods); group.RecalculateBounds(); } }
public static void ConfigureLODGroup(LODGroup lodGroup, LOD[] lodList) { if (EP.useEditorUndo) { Undo.RecordObject(lodGroup.gameObject, "Configure LODGroup"); } // Configure all transition fractions for (int f = 0; f < lodList.Length; ++f) { lodList[f].screenRelativeTransitionHeight = screenRelativeTransitionHeight(f, lodList.Length); } // Configure crossfade relative to transition fractions // NOTE: Final transition is to culled rendering lodGroup.fadeMode = LODFadeMode.CrossFade; lodGroup.animateCrossFading = false; for (int f = 0; f < lodList.Length; ++f) { var lastHeight = f - 1 >= 0 ? lodList[f - 1].screenRelativeTransitionHeight : 1f; var thisHeight = lodList[f].screenRelativeTransitionHeight; var nextHeight = f + 1 < lodList.Length ? lodList[f + 1].screenRelativeTransitionHeight : 0f; lodList[f].fadeTransitionWidth = fadeTransitionWidth * (thisHeight - nextHeight) / (lastHeight - thisHeight); // fadeTransitionWidth is entirely in this LoD, but is proportionate to the next LoD. // This is important for culling, which should not begin until within fadeTransitionWidth of the culling height } lodGroup.SetLODs(lodList); lodGroup.RecalculateBounds(); }
static int RecalculateBounds(IntPtr L) { LuaScriptMgr.CheckArgsCount(L, 1); LODGroup obj = LuaScriptMgr.GetNetObject <LODGroup>(L, 1); obj.RecalculateBounds(); return(0); }
public static void CalculateLODGroupBoundingBox(LODGroup group) { if (group == null) { throw new ArgumentNullException("group"); } group.RecalculateBounds(); }
void AddLODGroupForTransform(Transform target) { LODGroup lodGroup = target.gameObject.AddComponent <LODGroup>(); LOD[] lods = LODChildCount(target); lodGroup.SetLODS(lods); lodGroup.RecalculateBounds(); }
//Install LOD information void InstallLods() { if (this.transform == null || this.transform.childCount == 0) { return; } Transform baseTurrel = this.transform.GetChild(0); if (baseTurrel != null) { LODGroup oldLod = baseTurrel.gameObject.GetComponent <LODGroup>(); if (oldLod == null) { LODGroup lod = baseTurrel.gameObject.AddComponent <LODGroup>(); Renderer[] rends = baseTurrel.gameObject.GetComponentsInChildren <Renderer>(); List <List <Renderer> > renderers = new List <List <Renderer> >(); for (int i = 0; i < rends.Length; i++) { string curName = rends[i].gameObject.name; if (curName[curName.Length - 1] == ')') { string cuting = "(Clone)"; curName = curName.Replace(cuting, ""); } int lodGroup = -1; if (int.TryParse(curName[curName.Length - 1].ToString(), out lodGroup)) { if (renderers.Count <= lodGroup + 1) { for (int j = 0; j < lodGroup + 1 - renderers.Count; j++) { renderers.Add(new List <Renderer>()); } } renderers[lodGroup].Add(rends[i]); } } LOD[] lods = new LOD[renderers.Count]; for (int i = 0; i < lods.Length; i++) { lods[i].renderers = renderers[i].ToArray(); float x = 10f / lods.Length * (i + 1); if (i < lods.Length * 0.5f) { lods[i].screenRelativeTransitionHeight = (-1.5f * x + 10f) / 10f + 0.02f; } else { lods[i].screenRelativeTransitionHeight = (-0.5f * x + 5f) / 10f + 0.02f; } } lod.SetLODs(lods); lod.RecalculateBounds(); } } }
public bool PostBuild(int lodIndex, Mesh visualMesh, Mesh collisionMesh, ChunkTriggerBounds bounds) { var hasVisualMesh = chunks[lodIndex].PostBuild(visualMesh, collisionMesh, bounds); if (LODCount > 1) { lodGroup.RecalculateBounds(); } return(hasVisualMesh); }
private void Update() { ReEnableForcedDisabledLOD(); //If no LOD was rendered or culled (last LOD level), set controller LOD to lowest level if (_currentLODLevel == -1) { if (_overrideController.OnLODLevelChanged(-1)) { _LODGroup.RecalculateBounds(); } } else { //Swith to avatar based on LOD SwitchToAvatar(_overrideController.GetAvatar() ?? _origAvatar); //Reset LOD level _currentLODLevel = -1; } }
public void AddIt() { LODGroup lODGroup = this.gameObject.GetComponent <LODGroup>(); LOD[] Lods = new LOD[1]; // Fill up Renderer[] arrays. This is the list of drawables per LOD level Lods[0].renderers = this.GetComponentsInChildren <Renderer>(); // Make it live! lODGroup.SetLODS(Lods); lODGroup.RecalculateBounds(); }
static void AddMRLG() { GameObject[] gobs = Selection.gameObjects; foreach (GameObject gob in gobs) { LODGroup g = gob.AddComponent <LODGroup> (); LOD[] lods = new LOD[1]; lods [0].screenRelativeTransitionHeight = 0.11f; lods [0].renderers = gob.GetComponentsInChildren <Renderer> (); g.SetLODs(lods); g.RecalculateBounds(); } }
private void ClearVisibility() { if (lodGroup != null) { lodGroup.localReferencePoint = Vector3.zero; lodGroup.RecalculateBounds(); lodGroup = null; } if (renderers != null) { renderers.Clear(); } localOccludee = new OccludeeSphere(-1); }
void Start() { // Programmatically create a LOD group and add LOD levels. // Create a GUI that allows for forcing a specific LOD level. group = gameObject.GetComponent <LODGroup>(); // Add 4 LOD levels LOD[] lods = new LOD[3]; for (int i = 0; i < group.lodCount; i++) { PrimitiveType primType = PrimitiveType.Cube; switch (i) { case 1: primType = PrimitiveType.Capsule; break; case 2: primType = PrimitiveType.Sphere; break; case 3: primType = PrimitiveType.Cylinder; break; } GameObject go = GameObject.CreatePrimitive(primType); go.transform.parent = gameObject.transform; Renderer[] renderers = new Renderer[1]; renderers[0] = go.GetComponent <Renderer>(); float screenRelativeTransitionHeight = 1f; switch (i) { case 1: screenRelativeTransitionHeight = 0.25f; break; case 2: screenRelativeTransitionHeight = 0.05f; break; case 3: screenRelativeTransitionHeight = 0.02f; break; } lods[i] = new LOD(screenRelativeTransitionHeight, renderers); } group.SetLODs(lods); group.RecalculateBounds(); }
private void SavePrefabs(Mesh[,,] generatedMeshes, GrassBakeSettings grassBakeSettings, string path) { GameObject topParentObject = new GameObject(); Vector2 tileSize = grassBakeSettings.extents / grassBakeSettings.numTiles; for (int x = 0; x < generatedMeshes.GetLength(0); ++x) { for (int y = 0; y < generatedMeshes.GetLength(1); ++y) { GameObject tileParentObject = new GameObject(); tileParentObject.transform.parent = topParentObject.transform; tileParentObject.name = "Tile" + x + y; LODGroup lodGroup = tileParentObject.AddComponent <LODGroup>(); LOD[] lods = new LOD[generatedMeshes.GetLength(2)]; for (int i = 0; i < generatedMeshes.GetLength(2); ++i) { GameObject generatedGrass = new GameObject(); generatedGrass.name = "" + x + y + "_LOD" + i; generatedGrass.transform.position = new Vector3( x * tileSize.x - generatedMeshes.GetLength(0) * tileSize.x / 2f, 0f, y * tileSize.y - generatedMeshes.GetLength(1) * tileSize.y / 2f); MeshFilter meshFilter = generatedGrass.AddComponent <MeshFilter>(); meshFilter.sharedMesh = generatedMeshes[x, y, i]; MeshRenderer meshRenderer = generatedGrass.AddComponent <MeshRenderer>(); meshRenderer.sharedMaterial = grassBakeSettings.grassLODLevelSettings[i].grassMaterial; generatedGrass.transform.parent = tileParentObject.transform; Renderer[] renderers = new Renderer[1]; renderers[0] = meshRenderer; lods[i] = new LOD(grassBakeSettings.grassLODLevelSettings[i].lodPercent, renderers); } lodGroup.SetLODs(lods); lodGroup.RecalculateBounds(); } } PrefabUtility.SaveAsPrefabAsset(topParentObject, path); DestroyImmediate(topParentObject); AssetDatabase.SaveAssets(); }
static void AddBridgeLG() { GameObject[] gobs = Selection.gameObjects; foreach (GameObject gob in gobs) { Renderer r = gob.GetComponent <Renderer> (); LODGroup g = gob.AddComponent <LODGroup> (); List <Renderer> list = new List <Renderer> (); gob.GetComponentsInChildren <Renderer> (true, list); LOD[] lods = new LOD[1]; lods [0].screenRelativeTransitionHeight = 0.4f; list.Remove(r); lods [0].renderers = list.ToArray(); g.SetLODs(lods); g.RecalculateBounds(); } }
public static int RecalculateBounds(IntPtr l) { int result; try { LODGroup lodgroup = (LODGroup)LuaObject.checkSelf(l); lodgroup.RecalculateBounds(); LuaObject.pushValue(l, true); result = 1; } catch (Exception e) { result = LuaObject.error(l, e); } return(result); }
bool IncludeLODGroup(LODGroup lodGroup, GDOC_ManagementMode mode, GDOC_UpdateMode movementMode = GDOC_UpdateMode.Static, GDOC_Occludee parentOccludee = null) { var e = lodGroup.gameObject.AddComponent <GDOC_Occludee>(); lodGroup.RecalculateBounds(); e.mode = GDOC_OccludeeMode.MeshRendererGroup; e.movementMode = movementMode; e.isTemporary = true; e.managementMode = mode; e.GrabLODGroupRenderers(); e.Init(); e.isImportant = e.volumeSizeSqr > 2; AddOccludee(e, parentOccludee); return(false); }
void AddLODs() { if (cullPercent > 1.0f) { cullPercent = 1.0f; } if (cullPercent < 0.0f) { cullPercent = 0.0f; } if (Selection.objects == null) { Debug.Log("Nothing Selected!"); return; } foreach (GameObject g in Selection.objects) { if (g.GetComponent <LODGroup>() == null) { g.AddComponent <LODGroup>(); } else { return; } LODGroup group = g.GetComponent <LODGroup>(); LOD[] lods = new LOD[1]; //Renderer[] renderers = new Renderer[1]; //renderers[0] = g.transform.GetComponent<Renderer>(); Renderer[] renderers = g.transform.GetComponentsInChildren <Renderer>(); lods[0] = new LOD(cullPercent, renderers); group.SetLODs(lods); group.RecalculateBounds(); } }
public void MergeMeshes() { MeshFilter[] meshFilters = GetComponentsInChildren <MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length - 1]; int index = 0; for (int i = 0; i < meshFilters.Length; i++) { if (meshFilters[i].sharedMesh != null) { // if (meshFilters[i].sharedMesh == null) continue; combine[index].mesh = meshFilters[i].sharedMesh; combine[index++].transform = meshFilters[i].transform.localToWorldMatrix; } } MeshFilter meshF = transform.GetComponent <MeshFilter>(); meshF.sharedMesh = new Mesh(); meshF.sharedMesh.name = "lightpoles"; meshF.sharedMesh.CombineMeshes(combine); meshF.sharedMesh.RecalculateBounds(); if (lodGroup != null) { lodGroup.RecalculateBounds(); } // transform.gameObject.SetActive(true); foreach (Transform go in gameObject.transform.Cast <Transform>().Reverse()) { DestroyImmediate(go.gameObject); } MeshCollider mColl = gameObject.GetComponent <MeshCollider>(); mColl.sharedMesh = meshF.sharedMesh; }
void Start() { // Programmatically create a LOD group and add LOD levels. // Create a GUI that allows for forcing a specific LOD level. group = gameObject.AddComponent <LODGroup> (); // Add 4 LOD levels LOD[] lods = new LOD[4]; for (int i = 0; i < 4; i++) { PrimitiveType primType = PrimitiveType.Cube; switch (i) { case 1: primType = PrimitiveType.Capsule; break; case 2: primType = PrimitiveType.Sphere; break; case 3: primType = PrimitiveType.Cylinder; break; } GameObject go = GameObject.CreatePrimitive(primType); go.transform.parent = gameObject.transform; Renderer[] renderers = new Renderer[1]; renderers[0] = go.GetComponent <Renderer> (); float v = 1.0F / (i + 1); lods[i] = new LOD(v, renderers); Debug.Log(i + " screenrelative transition height: " + v); } group.SetLODs(lods); group.RecalculateBounds(); }
private static void ParseFile_SceneShapesAttributes(XmlReader xml, ref I3DModel model, Entity part) { Entity.ShapeType type; if (!Enum.TryParse(xml.LocalName, out type)) { throw new Exception($"Unrecognized shape type {xml.LocalName}"); } part.Type = type; string name = ParseString(xml.GetAttribute("name")); //I3DTransform I3DTransform t = part.gameObject.AddComponent <I3DTransform>(); t.Name = name; t.Id = ParseInt(xml.GetAttribute("nodeId")); t.IndexPath = ""; //TODO: Make this t.Visibility = ParseBool(xml.GetAttribute("visibility"), true); t.ClipDistance = ParseInt(xml.GetAttribute("clipDistance"), 1000000); t.MinClipDistance = ParseInt(xml.GetAttribute("minClipDistance")); t.ObjectMask = ParseInt(xml.GetAttribute("objectMask"), 0xffff); t.LOD = ParseBool(xml.GetAttribute("lodDistance")); //Transform part.gameObject.transform.localPosition = ParseVector3(xml.GetAttribute("translation")); part.gameObject.transform.localEulerAngles = ParseVector3(xml.GetAttribute("rotation")); Vector3 scale = xml.GetAttribute("scale") != null?ParseVector3(xml.GetAttribute("scale")) : Vector3.one; //scale.x *= -1; part.gameObject.transform.localScale = scale; //Rigidbody bool bStatic = ParseBool(xml.GetAttribute("static")); bool bDynamic = ParseBool(xml.GetAttribute("dynamic")); bool bKinematic = ParseBool(xml.GetAttribute("kinematic")); if (bStatic || bDynamic || bKinematic) { t.RigidBody = true; I3DRigidBody r = part.gameObject.AddComponent <I3DRigidBody>(); if (bStatic) { r.Type = RigidBodyType.Static; } else if (bDynamic) { r.Type = RigidBodyType.Dynamic; } else { r.Type = RigidBodyType.Kinematic; } r.Compound = ParseBool(xml.GetAttribute("compound")); r.CompoundChild = ParseBool(xml.GetAttribute("compoundChild")); r.Collision = ParseBool(xml.GetAttribute("collision"), true); r.Trigger = ParseBool(xml.GetAttribute("trigger")); r.CollisionMask = ParseInt(xml.GetAttribute("collisionMask")); r.Restitution = ParseFloat(xml.GetAttribute("restitution")); r.StaticFriction = ParseFloat(xml.GetAttribute("staticFriction"), 0.5f); r.DynamicFriction = ParseFloat(xml.GetAttribute("dynamicFriction"), 0.5f); r.LinearDamping = ParseFloat(xml.GetAttribute("linearDamping"), 0.5f); r.AngularDamping = ParseFloat(xml.GetAttribute("angularDamping"), 0.5f); r.Density = ParseFloat(xml.GetAttribute("density"), 1); r.SolverIterations = ParseInt(xml.GetAttribute("solverIterationCount"), 4); //r.Mass = ParseFloat(xml.GetAttribute("mass"), 0.5f); } //Shape if (part.Type == Entity.ShapeType.Shape) { if (name.EndsWith("_lod0") || name.EndsWith("_lod1") || name.EndsWith("_lod2")) { Transform parent = part.transform.parent; LODGroup lodGroup = parent.GetComponent <LODGroup>(); if (lodGroup == null) { lodGroup = parent.gameObject.AddComponent <LODGroup>(); lodGroup.SetLODs(new LOD[] {}); } int lodIndex = ParseInt(name.Substring(name.Length - 1)); LOD lod = new LOD { renderers = new Renderer[] { part.GetComponent <MeshRenderer>() } }; List <LOD> lods = lodGroup.GetLODs().ToList(); if (lodIndex > lods.Count) { lods.Add(lod); } else { lods.Insert(lodIndex, lod); } // Update the transition point for all LODs float lodGap = 1f / lods.Count; for (int i = 0; i < lods.Count; i++) { lods[i] = new LOD((lods.Count - i - 1) * lodGap, lods[i].renderers); } lodGroup.SetLODs(lods.ToArray()); lodGroup.RecalculateBounds(); } Shape s = part.gameObject.AddComponent <Shape>(); s.ID = ParseInt(xml.GetAttribute("shapeId")); s.CastShadows = ParseBool(xml.GetAttribute("castsShadows")); s.ReceiveShadows = ParseBool(xml.GetAttribute("receiveShadows")); s.NonRenderable = ParseBool(xml.GetAttribute("nonRenderable")); s.BuildNavMeshMask = ParseInt(xml.GetAttribute("buildNavMeshMask")); s._Materials = Shape.ParseMaterialString(ParseString(xml.GetAttribute("materialIds"))); part.Shape = s; //Assign the shape object according to ID foreach (I3DShapeData sh in model.ShapeDatas) { if (part.Shape.ID != sh.ID) { continue; } part.Shape.ID = sh.ID; part.Shape.Name = sh.Name; part.Shape.Mesh = sh.Mesh; part.GetComponent <MeshFilter>().mesh = sh.Mesh; break; } //Assign material according to ID part.Shape.Materials = new I3DMaterial[part.Shape._Materials.Length]; for (int i = 0; i < part.Shape._Materials.Length; i++) { int shapeMatId = part.Shape._Materials[i]; foreach (I3DMaterial mat in model.Materials) { if (mat.Id != shapeMatId) { continue; } part.Shape.Materials[i] = mat; } } } else if (part.Type == Entity.ShapeType.TerrainTransformGroup) { int heightMapId = ParseInt(xml.GetAttribute("heightMapId")); //int patchSize = ParseInt(xml.GetAttribute("patchSize")); float heightScale = ParseFloat(xml.GetAttribute("heightScale")); float unitsPerPixel = ParseFloat(xml.GetAttribute("unitsPerPixel")); I3DFile heightMapFile = model.GetFile(heightMapId); if (heightMapFile != null) { I3DTerrain i3DTerrain = part.gameObject.AddComponent <I3DTerrain>(); i3DTerrain.AlphaWidth = ParseInt(xml.GetAttribute("lodTextureSize")); i3DTerrain.AlphaHeight = ParseInt(xml.GetAttribute("lodTextureSize")); i3DTerrain.Terrain = part.gameObject.AddComponent <Terrain>(); i3DTerrain.TerrainData = new TerrainData(); i3DTerrain.TerrainCollider = part.gameObject.AddComponent <TerrainCollider>(); i3DTerrain.HeightMapScale = heightScale; i3DTerrain.HeightMapUnitsPerPixel = unitsPerPixel; i3DTerrain.HeightMap = TextureLoader.GetTexture(heightMapFile.AbsolutePath); i3DTerrain.BuildHeightmap(); } } else if (part.Type == Entity.ShapeType.Layer) { I3DFile detailMapFile = model.GetFile(ParseInt(xml.GetAttribute("detailMapId"))); // Detail map = diffuse texture I3DFile normalMapFile = model.GetFile(ParseInt(xml.GetAttribute("normalMapId"))); // Normal map = normal texture I3DFile weightMapFile = model.GetFile(ParseInt(xml.GetAttribute("weightMapId"))); // Weight map = splat map? //I3DFile distanceMapFile = model.GetFile(ParseInt(xml.GetAttribute("distanceMapId"))); // Distance map = low-res diffuse texture int unitSize = ParseInt(xml.GetAttribute("unitSize")); //int distanceMapUnitSize = ParseInt(xml.GetAttribute("distanceMapUnitSize")); // Unknown SplatPrototype splat = new SplatPrototype { texture = TextureLoader.GetTexture(detailMapFile.AbsolutePath), normalMap = TextureLoader.GetTexture(normalMapFile.AbsolutePath), tileSize = new Vector2(unitSize, unitSize), tileOffset = Vector2.zero }; I3DTerrain i3Dterrain = part.GetComponentInParent <I3DTerrain>(); i3Dterrain.Layers.Add(new I3DTerrainLayer { Priority = ParseInt(xml.GetAttribute("priority")), Attributes = ParseVector4(xml.GetAttribute("attributes")), SplatMap = splat, Weights = I3DTerrainUtil.Parse8BitMap(TextureLoader.GetTexture(weightMapFile.AbsolutePath)) }); } }
public void MergeMeshes() { // else Debug.LogWarning("Please assign rooftop material in CS Rooftops Component"); MeshFilter[] meshFilters = rooftopHolder.GetComponentsInChildren <MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length - 1]; int index = 0; for (int i = 0; i < meshFilters.Length; i++) { if (meshFilters[i].sharedMesh != null) { // if (meshFilters[i].sharedMesh == null) continue; combine[index].mesh = meshFilters[i].sharedMesh; combine[index++].transform = meshFilters[i].transform.localToWorldMatrix; } } MeshFilter meshF = rooftopHolder.transform.GetComponent <MeshFilter>(); meshF.sharedMesh = new Mesh(); meshF.sharedMesh.CombineMeshes(combine); ///assign new color // Mesh newMesh = new Mesh(); // newMesh.vertices = meshF.sharedMesh.vertices; // newMesh.normals = meshF.sharedMesh.normals; // newMesh.uv = meshF.sharedMesh.uv; // newMesh.colors = new Color[meshF.sharedMesh.vertices.Length]; // newMesh.triangles = meshF.sharedMesh.triangles; // for (int v = 0; v < newMesh.colors.Length; v++) // { // newMesh.colors[v] = new Color(0, 0, 1, 0); // } //meshF.sharedMesh = newMesh; meshF.sharedMesh.RecalculateBounds(); if (lodComponent != null) { lodComponent.RecalculateBounds(); } foreach (Transform go in rooftopHolder.transform.Cast <Transform>().Reverse()) { DestroyImmediate(go.gameObject); } if (rooftopHolder.GetComponent <MeshRenderer>() == null) { rh = rooftopHolder.AddComponent <MeshRenderer>() as MeshRenderer; rh = rooftopHolder.GetComponent <MeshRenderer>(); rh.sharedMaterial = greebleMat; } rh = rooftopHolder.GetComponent <MeshRenderer>(); rh.sharedMaterial = greebleMat; Renderer[] renderers = new Renderer[1]; LOD[] lod = new LOD[1]; renderers[0] = rooftopHolder.GetComponent <Renderer>(); lod[0] = new LOD(lodDistance, renderers); lodComponent.SetLODs(lod); if (animateLodFade) { lodComponent.fadeMode = LODFadeMode.CrossFade; } else { lodComponent.fadeMode = LODFadeMode.None; } lodComponent.animateCrossFading = animateLodFade; //if (meshF.sharedMesh.vertices.Length < 3) //{ // DestroyImmediate(rooftopHolder); // noMesh = true; //} //else noMesh = false; }
public static void CreateFileForResult(List <Core_Voxel.Result> resultList, Shader[] shaders, string[] shaderKeywords, Vector2[] shaderRemaps, float scale, Vector3 pivot) { var diffuseShader = shaders[0]; for (int index = 0; index < resultList.Count; index++) { var result = resultList[index]; bool lod = result.VoxelModels.Length > 1; bool isRig = !lod && result.IsRigged; int realLodNum = result.IsRigged ? 1 : result.VoxelModels.Length; var root = new GameObject(result.FileName).transform; var meshs = new List <Mesh>(); var materialsMap = new Dictionary <Texture2D, Material[]>(); Transform[] lodRoots = new Transform[realLodNum]; for (int lodIndex = 0; lodIndex < realLodNum; lodIndex++) { var voxelModel = result.VoxelModels[lodIndex]; var model = CreateModelFrom(voxelModel.RootNode, voxelModel.Materials, root, pivot, ref meshs, ref materialsMap, isRig, result.WithAvatar, shaders, shaderKeywords, shaderRemaps, scale); model.name = string.Format("Root{0}", lod ? "_lod " + lodIndex.ToString() : ""); lodRoots[lodIndex] = model; // Rig if (isRig) { Vector3 halfModelSize = voxelModel.ModelSize[0] * 0.5f; halfModelSize.x = Mathf.Floor(halfModelSize.x); halfModelSize.y = Mathf.Floor(halfModelSize.y); halfModelSize.z = Mathf.Floor(halfModelSize.z); var skinMR = model.GetComponent <SkinnedMeshRenderer>(); if (skinMR) { Vector3 rootBoneOffset = halfModelSize * scale; var boneTFList = new List <Transform>(); if (voxelModel.RootBones != null) { for (int i = 0; i < voxelModel.RootBones.Length; i++) { var boneTF = CreateBoneTransform(voxelModel.RootBones[i], model, scale, ref boneTFList); if (boneTF) { boneTF.localPosition -= rootBoneOffset; } } } skinMR.bones = boneTFList.ToArray(); skinMR.rootBone = model; // Bind Poses var poses = new Matrix4x4[boneTFList.Count]; for (int i = 0; i < boneTFList.Count; i++) { poses[i] = boneTFList[i].worldToLocalMatrix * model.localToWorldMatrix; } skinMR.sharedMesh.bindposes = poses; } // Foot Fix model.localPosition = (halfModelSize - voxelModel.FootPoints[lodIndex]) * scale; } } // Lod if (lod) { LODGroup group = root.gameObject.AddComponent <LODGroup>(); LOD[] lods = new LOD[realLodNum]; for (int i = 0; i < realLodNum; i++) { lods[i] = new LOD( i == realLodNum - 1 ? 0.001f : GetLodRant(result.VoxelModels[i].MaxModelBounds, i), lodRoots[i].GetComponentsInChildren <MeshRenderer>(true) ); } #if UNITY_5_0 || UNITY_5_1 || UNITY_4 group.SetLODS(lods); group.RecalculateBounds(); #else group.SetLODs(lods); group.RecalculateBounds(); #endif } else if (!isRig && root.childCount > 0) { var newRoot = root.GetChild(0); newRoot.name = root.name; root = newRoot; } // File string path = Util.CombinePaths( result.ExportRoot, result.ExportSubRoot, result.FileName + result.Extension ); path = Util.FixPath(path); string parentPath = Util.GetParentPath(path); Util.CreateFolder(parentPath); if (result.Extension == ".prefab") { Object prefab; if (Util.FileExists(path)) { prefab = AssetDatabase.LoadAssetAtPath <Object>(path); if (prefab as GameObject) { var group = (prefab as GameObject).GetComponent <LODGroup>(); if (group) { Object.DestroyImmediate(group, true); } } Object[] things = AssetDatabase.LoadAllAssetRepresentationsAtPath(path); foreach (Object o in things) { Object.DestroyImmediate(o, true); } } else { #if UNITY_4 || UNITY_5 || UNITY_2017 || UNITY_2018_1 || UNITY_2018_2 prefab = PrefabUtility.CreateEmptyPrefab(path); #else // 2018.3+ var tempObject = new GameObject(); prefab = PrefabUtility.SaveAsPrefabAsset(tempObject, path); Object.DestroyImmediate(tempObject, false); #endif } if (prefab) { // Assets for (int i = 0; i < meshs.Count; i++) { meshs[i].name = GetIndexedName("Mesh", i, meshs.Count); AssetDatabase.AddObjectToAsset(meshs[i], path); } int currentIndex = 0; foreach (var textureMat in materialsMap) { textureMat.Key.name = GetIndexedName("Texture", currentIndex, materialsMap.Count); AssetDatabase.AddObjectToAsset(textureMat.Key, path); var mats = textureMat.Value; for (int i = 0; i < mats.Length; i++) { mats[i].name = GetIndexedName("Material", currentIndex, materialsMap.Count) + "_" + i.ToString(); AssetDatabase.AddObjectToAsset(mats[i], path); } currentIndex++; } // Avatar if (isRig && result.WithAvatar) { var avatar = GetVoxelAvatarInRoot(root); if (avatar) { avatar.name = result.FileName; AssetDatabase.AddObjectToAsset(avatar, path); // Animator var ani = root.GetComponent <Animator>(); if (!ani) { ani = root.gameObject.AddComponent <Animator>(); } ani.avatar = avatar; } else { Debug.LogWarning("[Voxel to Unity] Failed to get avatar from the prefab. Use \"+ Human Bones\" button in rig editor to create bones and don\'t change their names and layout."); } } // Prefab #if UNITY_4 || UNITY_5 || UNITY_2017 || UNITY_2018_1 || UNITY_2018_2 PrefabUtility.ReplacePrefab(root.gameObject, prefab, ReplacePrefabOptions.ReplaceNameBased); #else // 2018.3+ prefab = PrefabUtility.SaveAsPrefabAsset(root.gameObject, path); #endif } } else // Obj { string objFolderPath = Util.CombinePaths(parentPath, result.FileName); string textureFolderPath = Util.CombinePaths(objFolderPath, "Textures"); Util.CreateFolder(objFolderPath); VoxelPostprocessor.TheShader = diffuseShader; // Assets var model = result.VoxelModels[0]; for (int modelIndex = 0; modelIndex < model.Meshs.Length; modelIndex++) { string modelIndexedName = GetIndexedName(result.FileName, modelIndex, model.Meshs.Length); string modelPathRoot = Util.CombinePaths(objFolderPath, modelIndexedName); // Texture string texturePath = Util.CombinePaths(textureFolderPath, modelIndexedName + ".png"); texturePath = Util.FixPath(texturePath); var texture = model.Textures[modelIndex]; Util.ByteToFile(texture.EncodeToPNG(), texturePath); VoxelPostprocessor.AddTexture(texturePath); // Meshs var uMesh = model.Meshs[modelIndex]; for (int i = 0; i < uMesh.Count; i++) { uMesh[i].name = GetIndexedName("Mesh", i, uMesh.Count); string obj = Util.GetObj(uMesh[i]); string objPath = GetIndexedName(modelPathRoot, i, uMesh.Count) + ".obj"; bool hasObjBefore = Util.FileExists(objPath); Util.Write(obj, objPath); VoxelPostprocessor.AddObj(objPath, texturePath); if (hasObjBefore) { AssetDatabase.ImportAsset(Util.FixedRelativePath(objPath), ImportAssetOptions.ForceUpdate); } } } } // Delete Objects if (root.parent) { Object.DestroyImmediate(root.parent.gameObject, false); } else { Object.DestroyImmediate(root.gameObject, false); } } AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); AssetDatabase.SaveAssets(); Resources.UnloadUnusedAssets(); EditorApplication.delayCall += VoxelPostprocessor.ClearAsset; }
public void SaveAsPrefab(bool groupedSave = false) { string name = gameObject.name; string path = saveTreeFolder; if (string.IsNullOrEmpty(path)) { return; } bool replacePrefab = false; if (!System.IO.Directory.Exists(path)) { EditorUtility.DisplayDialog("Invalid Path", "The path is not valid, you can chose it with the find folder button", "Ok"); return; } if (AssetDatabase.LoadAssetAtPath(path + "/" + name + ".prefab", typeof(GameObject))) // Overriding prefab dialog { if (EditorUtility.DisplayDialog("Are you sure?", "The prefab already exists. Do you want to overwrite it?", "Yes", "No")) { FileUtil.DeleteFileOrDirectory(Path.Combine(path, name + "_meshes")); AssetDatabase.Refresh(); replacePrefab = true; } else { name += "_1"; } } Mesh[] meshes = new Mesh[4]; string meshesFolder = AssetDatabase.CreateFolder(path, name + "_meshes"); meshesFolder = AssetDatabase.GUIDToAssetPath(meshesFolder) + Path.DirectorySeparatorChar; Material[] materials = SaveMaterials(meshesFolder); GameObject TreeObject = new GameObject(name); // Tree game object LODGroup group = TreeObject.AddComponent <LODGroup>(); // LOD Group group.fadeMode = LODFadeMode.CrossFade; int lodNumber = 4; // Creating LODs LOD[] lods = new LOD[lodNumber + 1]; // Generating Billboard Lod = 3; GenerateTree(true); GameObject billboard = CreateBillboard(meshesFolder, name); Renderer[] bill_re = new Renderer[1] { billboard.GetComponent <MeshRenderer>() }; lods[lodNumber] = new LOD(.01f, bill_re); for (int lod = lodNumber - 1; lod > -1; lod--) // create and save all LOD meshes { string meshPath = meshesFolder + name + "_LOD" + lod.ToString() + ".mesh"; //updating path for each LOD Lod = lod; Mesh mesh = GenerateTree(ao: true); meshes[lod] = mesh; AssetDatabase.CreateAsset(mesh, meshPath); } for (int i = 0; i < lodNumber; i++) // assigning lod meshes to LOD array { GameObject go = new GameObject(name + "_LOD" + i.ToString()); go.transform.parent = TreeObject.transform; MeshFilter mf = go.AddComponent <MeshFilter>(); mf.mesh = meshes[i]; Renderer[] re = new Renderer[1] { go.AddComponent <MeshRenderer>() }; // the renderer to put in LODs re[0].sharedMaterials = materials; float t = Mathf.Pow((i + 1) * 1f / (lodNumber + 1), 1); // float between 0 and 1 following f(x) = pow(x, n) lods[i] = new LOD((1 - t) * 0.9f + t * .01f, re); // assigning renderer lods[i].fadeTransitionWidth = 0.25f; } billboard.transform.parent = TreeObject.transform; // making billboard child of tree object group.SetLODs(lods); // assigning LODs to lod group group.RecalculateBounds(); string prefabPath = path + "/" + name + ".prefab"; TreeObject.AddComponent <MtreeWind>(); Object prefab; if (replacePrefab) { Object targetPrefab = AssetDatabase.LoadAssetAtPath(path + "/" + name + ".prefab", typeof(GameObject)); prefab = PrefabUtility.ReplacePrefab(TreeObject, targetPrefab, ReplacePrefabOptions.ConnectToPrefab); } else { prefab = PrefabUtility.CreatePrefab(prefabPath, TreeObject, ReplacePrefabOptions.ConnectToPrefab); } AssetDatabase.SaveAssets(); DestroyImmediate(TreeObject); if (!groupedSave) { // select newly created prefab in folder Selection.activeObject = prefab; // Also flash the folder yellow to highlight it EditorGUIUtility.PingObject(prefab); EditorUtility.DisplayDialog("Prefab saved !", "The prefab is saved, you can now delete the tree and use the prefab instead", "Ok"); } }
public void MergeMeshes() { // else Debug.LogWarning("Please assign rooftop material in CS Rooftops Component"); rooftopHolder[iteration].transform.localScale = new Vector3(1, 1, 1); MeshFilter[] meshFilters = rooftopHolder[iteration].GetComponentsInChildren <MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length]; int index = 0; for (int x = 0; x < meshFilters.Length; x++) { if (meshFilters[x].sharedMesh != null) { // if (meshFilters[i].sharedMesh == null) continue; combine[index].mesh = meshFilters[x].sharedMesh; combine[index++].transform = meshFilters[x].transform.localToWorldMatrix; } } MeshFilter meshF = rooftopHolder[iteration].transform.GetComponent <MeshFilter>(); meshF.sharedMesh = new Mesh(); meshF.sharedMesh.CombineMeshes(combine); meshF.sharedMesh.RecalculateBounds(); if (lodComponent != null) { lodComponent.RecalculateBounds(); } foreach (Transform go in rooftopHolder[iteration].transform.Cast <Transform>().Reverse()) { DestroyImmediate(go.gameObject); } if (rooftopHolder[iteration].GetComponent <MeshRenderer>() == null) { rh = rooftopHolder[iteration].AddComponent <MeshRenderer>() as MeshRenderer; rh = rooftopHolder[iteration].GetComponent <MeshRenderer>(); rh.sharedMaterial = greebleMat[iteration]; } rh = rooftopHolder[iteration].GetComponent <MeshRenderer>(); rh.sharedMaterial = greebleMat[iteration]; Renderer[] renderers = new Renderer[1]; LOD[] lod = new LOD[1]; renderers[0] = rooftopHolder[iteration].GetComponent <Renderer>(); lod[0] = new LOD(lodDistance, renderers); lodComponent.SetLODs(lod); if (animateLodFade) { lodComponent.fadeMode = LODFadeMode.CrossFade; } else { lodComponent.fadeMode = LODFadeMode.None; } lodComponent.animateCrossFading = animateLodFade; rooftopHolder[iteration].transform.position = gameObject.transform.position; rooftopHolder[iteration].transform.rotation = gameObject.transform.rotation; rooftopHolder[iteration].transform.localScale = new Vector3(1, bmComponent.scale, 1); }
void Mesh() { counting = 0; canMerge = false; int numOfseObjList = 0; totalcount = dataDic.Count; foreach (string key in dataDic.Keys) { counting++; UpdateProgress(); if (showList.Count > 0 && showList[numOfseObjList] == false) { numOfseObjList++; continue; } numOfseObjList++; if (polyMergeCountDic[key] > 65000) { continue; } NewFolder(meshContainsName, key); LOD[] lods = new LOD[dataDic[key].Count]; int lodCount = 0; int merCoung = 0; foreach (MergeData m in dataDic[key]) { //Mesh for (int i = 0; i < m._matLists.Count; i++) { subMeshList = m._subMeshLists[i]; string header = meshContainsName; GameObject mergedObject = new GameObject(header + "_" + m._objectLists[i][0].name + "_" + m._matLists[i][0].name, typeof(MeshFilter), typeof(MeshRenderer)); Mesh combinedMesh = CombineSubmeshes(subMeshList, mergedObject); if (m._tranMeshColLists.Count != 0) { int mesColCou = 0; for (int t = 0; t < m._tranMeshColLists.Count; t++) { GameObject addMesh = new GameObject(m._meshColLists[t].name + "_" + mesColCou); mesColCou++; MeshCollider mc = addMesh.AddComponent <MeshCollider> (); mc.sharedMesh = m._meshColLists[t]; addMesh.transform.position = m._tranMeshColLists[t].transform.position; addMesh.transform.rotation = m._tranMeshColLists[t].transform.rotation; addMesh.transform.localScale = m._tranMeshColLists[t].localScale; addMesh.transform.SetParent(mergedObject.transform); } } AssetDatabase.CreateAsset(combinedMesh, filePath + "/" + header + "_" + m._objectLists[i][0].name + "_" + m._matLists[i][0].name + ".asset"); mergedObject.GetComponent <MeshFilter>().mesh = combinedMesh; mergedObject.GetComponent <MeshRenderer>().sharedMaterials = m._matLists[i].ToArray(); lodList.Add(mergedObject); Renderer[] renderers = new Renderer[1]; renderers[0] = mergedObject.GetComponent <Renderer>(); lods[lodCount] = new LOD(1.0f / (lodCount + 2f), renderers); lodCount++; } } string m_header = meshContainsName; GameObject newMergedObj = new GameObject(m_header + "_" + key); foreach (GameObject n in lodList) { n.transform.SetParent(newMergedObj.transform); } if (lodGroup) { LODGroup lodObj = newMergedObj.AddComponent <LODGroup> (); lodObj.SetLODs(lods); lodObj.RecalculateBounds(); for (int n = lodObj.GetLODs().Count() - 1; n >= 0; n--) { if (lodObj.GetLODs()[n].renderers.Length == 0) { List <LOD> _lodObj = lodObj.GetLODs().ToList(); _lodObj.RemoveAt(n); lodObj.SetLODs(_lodObj.ToArray()); } } if (lodRTH.ContainsKey(key)) { lods = lodObj.GetLODs(); for (int u = 0; u < lodRTH[key].Count; u++) { lods [u].screenRelativeTransitionHeight = lodRTH [key] [u]; } lodObj.SetLODs(lods); } } PrefabUtility.CreatePrefab(filePath + "/" + m_header + "_" + key + ".prefab", (GameObject)newMergedObj, ReplacePrefabOptions.ConnectToPrefab); lodList.Clear(); } }
public void CreateWMOObject() { if (terrainHandler.working) { WMO.WMOStruct data = WMO.AllWMOData.Dequeue(); GameObject WMOinstance = new GameObject(); terrainHandler.LoadedWMOIds[data.fileDataId] = WMOinstance; int nGroups = data.Info.nGroups; for (int g = 0; g < nGroups; g++) { // group object // GameObject GroupInstance = new GameObject(); GroupInstance.isStatic = true; GroupInstance.transform.SetParent(terrainHandler.LoadedWMOIds[data.fileDataId].transform); GroupInstance.name = data.groupsData[g].groupName; LODGroup Lodgroup = GroupInstance.AddComponent <LODGroup>(); LOD[] lods = new LOD[1]; Renderer[] renderers = new Renderer[data.groupsData[g].nBatches]; // Batches // for (int bn = 0; bn < data.groupsData[g].nBatches; bn++) { //////////////////////////////// #region object GameObject BatchInstance = new GameObject(); BatchInstance.isStatic = true; BatchInstance.transform.SetParent(GroupInstance.transform); BatchInstance.name = bn.ToString(); BatchInstance.transform.transform.eulerAngles = new Vector3(BatchInstance.transform.transform.eulerAngles.x, BatchInstance.transform.transform.eulerAngles.y - 180, GroupInstance.transform.transform.eulerAngles.z); #endregion //////////////////////////////// //////////////////////////////// #region mesh BatchInstance.AddComponent <MeshRenderer>(); BatchInstance.GetComponent <MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; renderers[bn] = BatchInstance.GetComponent <MeshRenderer>(); BatchInstance.AddComponent <MeshFilter>(); Mesh bmesh = new Mesh(); uint batchVertSize = data.groupsData[g].batch_MaxIndex[bn] - data.groupsData[g].batch_MinIndex[bn] + 1; Vector3[] batchVertices = new Vector3[batchVertSize]; Vector2[] batchUVs = new Vector2[batchVertSize]; Vector3[] batchNormals = new Vector3[batchVertSize]; Color32[] batchVertexColors = new Color32[batchVertSize]; List <int> batchTrianglesList = new List <int>(); int[] batchTriangles; int arrayPosition = 0; uint batch_startVertex = data.groupsData[g].batch_MinIndex[bn]; uint batch_endVertex = data.groupsData[g].batch_MaxIndex[bn]; for (uint v = batch_startVertex; v <= batch_endVertex; v++) { batchVertices[arrayPosition] = data.groupsData[g].vertices[v]; batchUVs[arrayPosition] = data.groupsData[g].UVs[v]; batchNormals[arrayPosition] = data.groupsData[g].normals[v]; if (!data.groupsData[g].flags.Hasvertexolors) { batchVertexColors[arrayPosition] = new Color32(127, 127, 127, 127); } else { batchVertexColors[arrayPosition] = data.groupsData[g].vertexColors[(int)v]; } arrayPosition++; } uint batch_startIndex = data.groupsData[g].batch_StartIndex[bn]; uint batch_nIndices = data.groupsData[g].batch_Count[bn]; for (uint idx = batch_startIndex; idx <= batch_startIndex + batch_nIndices - 2; idx = idx + 3) { uint in1 = data.groupsData[g].triangles[idx + 0]; uint in2 = data.groupsData[g].triangles[idx + 1]; uint in3 = data.groupsData[g].triangles[idx + 2]; int a = (int)(in1 - batch_startVertex); int b = (int)(in2 - batch_startVertex); int c = (int)(in3 - batch_startVertex); batchTrianglesList.Add(a); batchTrianglesList.Add(b); batchTrianglesList.Add(c); } batchTrianglesList.Reverse(); batchTriangles = batchTrianglesList.ToArray(); bmesh.vertices = batchVertices; bmesh.uv = batchUVs; bmesh.normals = batchNormals; bmesh.triangles = batchTriangles; bmesh.colors32 = batchVertexColors; BatchInstance.GetComponent <MeshFilter>().mesh = bmesh; BatchInstance.GetComponent <MeshRenderer>().sharedMaterial = missingMaterial; #endregion //////////////////////////////// //////////////////////////////// #region material uint TextureFileDataId = data.texturePaths[data.materials[data.groupsData[g].batchMaterialIDs[bn]].TextureId1]; BatchInstance.GetComponent <Renderer>().material = WMOmaterials[(int)data.materials[data.groupsData[g].batchMaterialIDs[bn]].ShaderType]; //////////////////////////////// #region Set Fragment Shader WMOFragmentShader shader = data.materials[data.groupsData[g].batchMaterialIDs[bn]].ShaderType; switch (shader) { case WMOFragmentShader.Diffuse: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderDiffuse", 1.0f); break; } case WMOFragmentShader.Specular: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderSpecular", 1.0f); break; } case WMOFragmentShader.Metal: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderMetal", 1.0f); break; } case WMOFragmentShader.Env: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderEnv", 1.0f); break; } case WMOFragmentShader.Opaque: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderOpaque", 1.0f); BatchInstance.GetComponent <Renderer>().material.SetFloat("_AlphaToMask", 1.0f); break; } default: { BatchInstance.GetComponent <Renderer>().material.SetFloat("_ShaderDiffuse", 1.0f); break; } } #endregion //////////////////////////////// //////////////////////////////// #region Set Material Flags // F_UNCULLED // int Culling = 2; // on (only front) if (data.materials[data.groupsData[g].batchMaterialIDs[bn]].flags.F_UNCULLED) { Culling = 0; // off (both sides_ } BatchInstance.GetComponent <Renderer>().material.SetFloat("F_UNCULLED", Culling); // F_UNLIT // if (data.materials[data.groupsData[g].batchMaterialIDs[bn]].flags.F_UNLIT) { BatchInstance.GetComponent <Renderer>().material.EnableKeyword("F_UNLIT"); } //BatchInstance.GetComponent<Renderer>().material.SetFloat("_F_UNLIT", data.materials[data.groupsData[g].batchMaterialIDs[bn]].flags.F_UNLIT ? 1 : 0); // F_UNFOGGED // BatchInstance.GetComponent <Renderer>().material.SetFloat("_F_UNFOGGED", data.materials[data.groupsData[g].batchMaterialIDs[bn]].flags.F_UNFOGGED ? 1 : 0); #endregion //////////////////////////////// //////////////////////////////// #region Set Blending Mode // set default blend: One Zero, basicly off UnityEngine.Rendering.BlendMode source = UnityEngine.Rendering.BlendMode.One; UnityEngine.Rendering.BlendMode destination = UnityEngine.Rendering.BlendMode.Zero; BlendingMode blending = data.materials[data.groupsData[g].batchMaterialIDs[bn]].BlendMode; switch (blending) { case BlendingMode.Opaque: { source = UnityEngine.Rendering.BlendMode.One; destination = UnityEngine.Rendering.BlendMode.Zero; break; } case BlendingMode.AlphaKey: { source = UnityEngine.Rendering.BlendMode.One; destination = UnityEngine.Rendering.BlendMode.Zero; break; } case BlendingMode.Alpha: { source = UnityEngine.Rendering.BlendMode.SrcAlpha; destination = UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha; break; } case BlendingMode.Additive: { source = UnityEngine.Rendering.BlendMode.One; destination = UnityEngine.Rendering.BlendMode.One; break; } case BlendingMode.Modulate: { source = UnityEngine.Rendering.BlendMode.DstColor; destination = UnityEngine.Rendering.BlendMode.Zero; break; } case BlendingMode.Modulate2x: { source = UnityEngine.Rendering.BlendMode.DstColor; destination = UnityEngine.Rendering.BlendMode.SrcColor; break; } case BlendingMode.ModulateAdditive: { source = UnityEngine.Rendering.BlendMode.DstColor; destination = UnityEngine.Rendering.BlendMode.One; break; } default: { Debug.Log("BlendMode To Add: " + blending.ToString() + " Texture Used: " + TextureFileDataId); source = UnityEngine.Rendering.BlendMode.One; destination = UnityEngine.Rendering.BlendMode.Zero; break; } } BatchInstance.GetComponent <Renderer>().material.SetInt("MySrcMode", (int)source); BatchInstance.GetComponent <Renderer>().material.SetInt("MyDstMode", (int)destination); #endregion //////////////////////////////// //////////////////////////////// #region Assign Textures if (LoadedWMOTextures.ContainsKey(TextureFileDataId)) { BatchInstance.GetComponent <Renderer>().material.SetTexture("_MainTex", LoadedWMOTextures[TextureFileDataId]); } else { try { Texture2Ddata tdata = data.textureData[TextureFileDataId]; Texture2D tex = new Texture2D(tdata.width, tdata.height, tdata.textureFormat, tdata.hasMipmaps); tex.LoadRawTextureData(tdata.TextureData); tex.Apply(); LoadedWMOTextures[TextureFileDataId] = tex; BatchInstance.GetComponent <Renderer>().material.SetTexture("_MainTex", tex); } catch (Exception ex) { Debug.Log("Error: Loading RawTextureData @ WMOhandler"); Debug.LogException(ex); } } #endregion //////////////////////////////// #endregion //////////////////////////////// } lods[0] = new LOD(.1f, renderers); Lodgroup.SetLODs(lods); Lodgroup.animateCrossFading = true; Lodgroup.fadeMode = LODFadeMode.SpeedTree; Lodgroup.RecalculateBounds(); } terrainHandler.LoadedWMOIds[data.fileDataId].transform.position = data.position; terrainHandler.LoadedWMOIds[data.fileDataId].transform.rotation = data.rotation; terrainHandler.LoadedWMOIds[data.fileDataId].transform.localScale = data.scale; if (data.uniqueID != -1) { if (terrainHandler.ADTBlockWMOParents[data.uniqueID] != null) { terrainHandler.LoadedWMOIds[data.fileDataId].transform.SetParent(terrainHandler.ADTBlockWMOParents[data.uniqueID].transform); } else { Destroy(terrainHandler.LoadedWMOIds[data.fileDataId]); } } terrainHandler.LoadedWMOIds[data.fileDataId].name = data.Info.wmoID.ToString(); terrainHandler.frameBusy = false; } }
public void SaveAsPrefab(bool groupedSave = false, bool usingHDRP = false) { var oldMesh = filter.sharedMesh; string name = gameObject.name; string path = saveTreeFolder; if (string.IsNullOrEmpty(path)) { return; } #if (UNITY_2017 || UNITY_2018_1 || UNITY_2018_2) bool replacePrefab = false; //=> value never Used, taged by dan_wipf => used for unity up to 2018.2 #endif if (!System.IO.Directory.Exists(path)) { EditorUtility.DisplayDialog("Invalid Path", "The path is not valid, you can chose it with the find folder button", "Ok"); return; } if (AssetDatabase.LoadAssetAtPath(path + "/" + name + ".prefab", typeof(GameObject))) // Overriding prefab dialog { if (EditorUtility.DisplayDialog("Are you sure?", "The prefab already exists. Do you want to overwrite it?", "Yes", "No")) { FileUtil.DeleteFileOrDirectory(Path.Combine(path, name + "_meshes")); #if (UNITY_2017 || UNITY_2018_1 || UNITY_2018_2) replacePrefab = true; // => value never Used, taged by dan_wipf => used for unity up to 2018.2 #endif } else { name += "_1"; } } Mesh[] meshes = new Mesh[LODs.Count]; string meshesFolder = AssetDatabase.CreateFolder(path, name + "_meshes"); meshesFolder = AssetDatabase.GUIDToAssetPath(meshesFolder) + Path.DirectorySeparatorChar; Material[] materials = SaveMaterials(meshesFolder); GameObject TreeObject = new GameObject(name); // Tree game object LODGroup group = TreeObject.AddComponent <LODGroup>(); // LOD Group group.fadeMode = LODFadeMode.CrossFade; LOD[] lods = new LOD[LODs.Count + 1]; // Generating Billboard LodIndex = LODs.Count - 1; GenerateTree(true); GameObject billboard = CreateBillboard(meshesFolder, name, usingHDRP); Renderer[] bill_re = new Renderer[1] { billboard.GetComponent <MeshRenderer>() }; lods[lods.Length - 1] = new LOD(.01f, bill_re); for (LodIndex = LODs.Count - 1; LodIndex >= 0; LodIndex--) // create and save all LOD meshes { string meshPath = meshesFolder + name + "_LOD" + LodIndex + ".mesh"; //updating path for each LOD Mesh mesh = GenerateTree(instantAo: true); meshes[LodIndex] = mesh; AssetDatabase.CreateAsset(mesh, meshPath); } for (int i = 0; i < LODs.Count; i++) // assigning lod meshes to LOD array { GameObject go = new GameObject(name + "_LOD" + i.ToString()); go.transform.parent = TreeObject.transform; MeshFilter mf = go.AddComponent <MeshFilter>(); mf.mesh = meshes[i]; Renderer[] re = new Renderer[1] { go.AddComponent <MeshRenderer>() }; // the renderer to put in LODs re[0].sharedMaterials = materials; float t = Mathf.Pow((i + 1) * 1f / (LODs.Count + 1), 1); // float between 0 and 1 following f(x) = pow(x, n) lods[i] = new LOD((1 - t) * 0.9f + t * .01f, re); // assigning renderer lods[i].fadeTransitionWidth = 0.25f; } billboard.transform.parent = TreeObject.transform; // making billboard child of tree object group.SetLODs(lods); // assigning LODs to lod group group.animateCrossFading = true; group.RecalculateBounds(); string prefabPath = path + "/" + name + ".prefab"; Object prefab; #if (UNITY_2017 || UNITY_2018_1 || UNITY_2018_2) if (replacePrefab) { Object targetPrefab = AssetDatabase.LoadAssetAtPath(path + "/" + name + ".prefab", typeof(GameObject)); prefab = PrefabUtility.ReplacePrefab(TreeObject, targetPrefab, ReplacePrefabOptions.ConnectToPrefab); } else { prefab = PrefabUtility.CreatePrefab(prefabPath, TreeObject, ReplacePrefabOptions.ConnectToPrefab); } #else prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(TreeObject, prefabPath, InteractionMode.AutomatedAction); #endif AssetDatabase.SaveAssets(); DestroyImmediate(TreeObject); if (!groupedSave) { // select newly created prefab in folder Selection.activeObject = prefab; // Also flash the folder yellow to highlight it EditorGUIUtility.PingObject(prefab); EditorUtility.DisplayDialog("Prefab saved !", "The prefab is saved, you can now delete the tree and use the prefab instead", "Ok"); } LodIndex = 0; filter.sharedMesh = oldMesh; }
public static void GenerateBillboards(Bounds bounds, FoliageCell cell, GameObject owner, List <FoliageInstance> trees, FoliageType type, bool addLodGroup, float screenFadeSize, bool animatedCrossFade) { int[] originalTriangles = m_SystemQuadTriangles; GameObject meshObj = new GameObject(); // Mark object as static #if UNITY_EDITOR GameObjectUtility.SetStaticEditorFlags(meshObj, StaticEditorFlags.OccludeeStatic | StaticEditorFlags.ReflectionProbeStatic); #endif string name = string.Format("MeshCell[{0}_{1}]", cell.GetHashCode(), type.m_Prefab.name); Transform existing = owner.transform.Find(name); if (existing != null) { #if UNITY_EDITOR if (UnityEditor.EditorApplication.isPlaying == false) { Object.DestroyImmediate(existing.gameObject); } else { Object.Destroy(existing.gameObject); } #else Object.Destroy(existing.gameObject); #endif existing = null; } meshObj.transform.SetParent(owner.transform); meshObj.name = name; var data = type.m_RuntimeData.m_SpeedTreeData; Vector3 worldScale = new Vector3(data.m_Size.x, data.m_Size.y, data.m_Size.x); // Set material MeshRenderer rend = meshObj.AddComponent <MeshRenderer>(); rend.sharedMaterial = GenerateBillboardMaterial(type.m_RuntimeData.m_SpeedTreeData); MeshFilter filter = meshObj.AddComponent <MeshFilter>(); Mesh treeMesh = new Mesh(); treeMesh.name = meshObj.name; List <Vector4> m_TempWorldPositions = new List <Vector4>(); List <Vector3> m_TempWorldScales = new List <Vector3>(); List <Vector3> m_TempQuadVertices = new List <Vector3>(); List <Vector4> m_TempQuadTangents = new List <Vector4>(); List <Vector3> m_TempQuadNormals = new List <Vector3>(); List <int> m_TempQuadIndices = new List <int>(); for (int treeIndex = 0; treeIndex < trees.Count; treeIndex++) { Vector3 position = trees[treeIndex].m_Position; Vector3 scale = trees[treeIndex].m_Scale; float rot = trees[treeIndex].m_Rotation.eulerAngles.y * Mathf.Deg2Rad; // Offset world position, by the grounding factor Vector3 instancePos = position; // Don't use this, but offset in shader, so that we can have that correct hue // instancePos.y += data.m_Size.z; // Scale by the world scale too so that we don't have to do an extra multip Vector3 instanceScale = scale; instanceScale.Scale(worldScale); // Add the world and scale data for (int index = 0; index < 4; index++) { Vector4 posAndRot = instancePos; posAndRot.w = rot; m_TempWorldPositions.Add(posAndRot); m_TempWorldScales.Add(instanceScale); } // Add stanard quad data m_TempQuadVertices.AddRange(m_SystemQuadVertices); m_TempQuadTangents.AddRange(m_SystemQuadTangents); m_TempQuadNormals.AddRange(m_SystemQuadNormals); // Calculate triangle indixes m_TempQuadIndices.AddRange(originalTriangles); for (int triIndex = 0; triIndex < 6; triIndex++) { // Just add to the triangles the existing triangles + the new indices m_TempQuadIndices[triIndex + 6 * treeIndex] = originalTriangles[triIndex] + 4 * treeIndex; } } treeMesh.Clear(); // Set standard data treeMesh.SetVertices(m_TempQuadVertices); treeMesh.SetNormals(m_TempQuadNormals); treeMesh.SetTangents(m_TempQuadTangents); // Set the custom data treeMesh.SetUVs(1, m_TempWorldPositions); treeMesh.SetUVs(2, m_TempWorldScales); // Set triangles and do not calculate bounds treeMesh.SetTriangles(m_TempQuadIndices, 0, false); // Set the manually calculated bounds treeMesh.bounds = bounds; treeMesh.UploadMeshData(true); // Set the mesh filter.mesh = treeMesh; if (addLodGroup) { // Add the mesh' lod group LODGroup group = meshObj.AddComponent <LODGroup>(); group.animateCrossFading = false; if (animatedCrossFade) { group.fadeMode = LODFadeMode.CrossFade; group.animateCrossFading = true; } else { group.fadeMode = LODFadeMode.None; group.animateCrossFading = false; } group.SetLODs(new LOD[] { new LOD(screenFadeSize, new Renderer[] { rend }) }); group.RecalculateBounds(); } #if UNITY_EDITOR UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(meshObj.scene); #endif }