コード例 #1
0
        void PrepareScene(Transform locationRoot, Dictionary <string, string> savedStandardMeshes, Dictionary <string, string> savedObjectMeshes)
        {
            for (int i = 0; i < locationRoot.childCount; i++)
            {
                Transform             loc           = locationRoot.GetChild(i);
                WG_LocationController locController = loc.GetComponent <WG_LocationController>();
                if (locController != null)
                {
                    locController.PrepareLocation("Assets" + assetMeshPath,
                                                  "Assets" + assetMaterialPath,
                                                  "Assets" + assetTexturePath,
                                                  "Assets" + assetMinimapPath,
                                                  lightMapShader,
                                                  minimapSize, minimapCamera, minimapCameraHeight, exportLightmapHDR,
                                                  savedStandardMeshes, savedObjectMeshes);
                }
            }

            //prepare navmesh
            WG_TerrainBuilder builderComponent = builder.gameObject.GetComponent <WG_TerrainBuilder>();
            NavMeshData       data             = builderComponent.GetNavmeshData();

            if (data != null)
            {
                SaveNavmeshAsset(data);
                localNavMesh = data;
            }
        }
コード例 #2
0
        public void BuildNavmeshOnly()
        {
            WG_LocationController[] locations = GetComponentsInChildren <WG_LocationController>();
            if (locations.Length > 0)
            {
                WG_LocationController loc        = locations[0];
                NavMeshSurface        navSurface = loc.groundGO.GetComponent <NavMeshSurface>();
                navSurface.BuildNavMesh();

                SaveNavMeshData(navSurface.navMeshData);
            }
        }
コード例 #3
0
 WG_LocationController GetLocationByCoordinates(IntPair coords, List <WG_LocationController> locations)
 {
     for (int i = 0; i < locations.Count; i++)
     {
         WG_LocationController loc = locations[i];
         if (loc.u == coords.u && loc.v == coords.v)
         {
             return(loc);
         }
     }
     return(null);
 }
コード例 #4
0
        void PrepareScene(Transform locationRoot, Dictionary <string, string> savedStandardMeshes, Dictionary <string, string> savedObjectMeshes)
        {
            for (int i = 0; i < locationRoot.childCount; i++)
            {
                Transform             loc           = locationRoot.GetChild(i);
                WG_LocationController locController = loc.GetComponent <WG_LocationController>();
                if (locController != null)
                {
                    locController.PrepareLocation("Assets" + assetMeshPath,
                                                  "Assets" + assetMaterialPath,
                                                  "Assets" + assetTexturePath,
                                                  "Assets" + assetMinimapPath,
                                                  lwrpShader, stdShaders, lmMode,
                                                  minimapSize, minimapCamera, minimapCameraHeight, exportLightmapHDR, ldrAmbientCompensation, ldrLightmapMultiplier,
                                                  savedStandardMeshes, savedObjectMeshes);
                }
            }

            PrepareNavmesh();
        }
コード例 #5
0
        void ExportScene(Transform locationRoot)
        {
            for (int i = 0; i < locationRoot.childCount; i++)
            {
                Transform             loc           = locationRoot.GetChild(i);
                WG_LocationController locController = loc.GetComponent <WG_LocationController>();

                if (locController != null)
                {
                    locController.ExportLocation("Assets" + assetLocationPath, minimapSize, minimapCamera, minimapCameraHeight, "Assets" + assetMinimapPath);
                }
            }

            //export navmesh
#if UNITY_EDITOR
            WG_TerrainBuilder builderComponent = builder.gameObject.GetComponent <WG_TerrainBuilder>();
            NavMeshData       data             = builderComponent.GetNavmeshData();
            string            navmeshAssetPath = "";
            if (data != null)
            {
                navmeshAssetPath = "navmeshes/" + data.name;
                AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(data)).SetAssetBundleNameAndVariant(navmeshAssetPath, "");
            }
            else
            {
                if (localNavMesh == null)
                {
                    Debug.Log("Navmesh data is null, can't export it.");
                }
                else
                {
                    Debug.Log("Use local version of the navmesh data object.");
                    data             = localNavMesh;
                    navmeshAssetPath = "navmeshes/" + localNavMesh.name;
                    AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(localNavMesh)).SetAssetBundleNameAndVariant(navmeshAssetPath, "");
                }
            }

            //create xml with navmeshlink and starting points
            GlobalLocation globalLocation = new GlobalLocation();
            if (navmeshAssetPath.Length > 0 && data != null)
            {
                globalLocation.navmeshData = new NavmeshData()
                {
                    link = navmeshAssetPath, name = data.name
                };
                if (exportPlayerPositionsInLocations)
                {
                    globalLocation.positions = new List <PositionData>();
                    WG_Position[] positions = FindObjectsOfType <WG_Position>();
                    for (int i = 0; i < positions.Length; i++)
                    {
                        Vector3 pos = positions[i].gameObject.transform.position;
                        globalLocation.positions.Add(new PositionData()
                        {
                            positionX = pos.x, positionY = pos.y, positionZ = pos.z
                        });
                    }

                    if (globalLocation.positions.Count == 0)
                    {
                        Debug.Log("No start positions on the scene. Add default position (0, 0, 0).");
                        globalLocation.positions.Add(new PositionData()
                        {
                            positionX = 0.0f, positionY = 0.0f, positionZ = 0.0f
                        });
                    }
                }


                globalLocation.bounds = new LocationsBounds()
                {
                    minU = builderComponent.segmentsMinX,
                    maxU = builderComponent.segmenstMaxX,
                    minV = builderComponent.segmentsMinY,
                    maxV = builderComponent.segmenstMaxY
                };

                globalLocation.locationSize = new LocationSize()
                {
                    value = builderComponent.segmentSize
                };

                string globalLocationName      = "global_location";
                string globalLocationAssetPath = "Assets" + assetLocationPath + globalLocationName + ".xml";
                globalLocation.Save(globalLocationAssetPath);
                AssetDatabase.ImportAsset(globalLocationAssetPath, ImportAssetOptions.ForceUpdate);
                AssetImporter.GetAtPath(globalLocationAssetPath).SetAssetBundleNameAndVariant("locations/" + globalLocationName, "");

                //export server data
                SavePlayerPositions();
                //SaveCollisionMap(data);
                SaveCollisionMap(serverPath);
                SaveTowerPositions();
            }
#endif
        }
コード例 #6
0
        WG_LocationController EmitSegment(int u, int v, float segmentSize, float meshSquareSize, Transform root, bool[,] map, Material floorMaterial, Material wallsMaterial, float height, float uvPadding)
        {
            //create game object
            GameObject location = new GameObject()
            {
                name = "location_" + u.ToString() + "_" + v.ToString()
            };

            location.transform.SetParent(root);
            location.transform.position = new Vector3(u * segmentSize, 0.0f, v * segmentSize);
            WG_MarchingSquares marchingSquares = new WG_MarchingSquares();
            MeshDataClass      mountainsData   = marchingSquares.GenerateMesh(map, false, -segmentSize / 2, segmentSize / 2, -segmentSize / 2, segmentSize / 2, meshSquareSize, height, false, false, 0f);
            MeshDataClass      floorData       = marchingSquares.GenerateMesh(map, true, -segmentSize / 2, segmentSize / 2, -segmentSize / 2, segmentSize / 2, meshSquareSize, 0, true, true, height);
            //get walls vertices and triangles from generaton of the floor
            MeshDataClass wallsData = marchingSquares.GetWallsData();

            //union ground and mountains
            Vector3[] vertices = new Vector3[mountainsData.vertices.Count + floorData.vertices.Count];
            int       mountainsVerticesCount = mountainsData.vertices.Count;

            for (int i = 0; i < mountainsVerticesCount; i++)
            {
                vertices[i] = mountainsData.vertices[i];
            }

            for (int i = 0; i < floorData.vertices.Count; i++)
            {
                vertices[mountainsVerticesCount + i] = floorData.vertices[i];
            }
            //re-enumerate triangles
            int[] triangles = new int[mountainsData.triangles.Count + floorData.triangles.Count];
            int   mountainsTrianglesCount = mountainsData.triangles.Count;

            for (int i = 0; i < mountainsTrianglesCount; i++)
            {
                triangles[i] = mountainsData.triangles[i];
            }

            for (int i = 0; i < floorData.triangles.Count; i++)
            {
                triangles[mountainsTrianglesCount + i] = floorData.triangles[i] + mountainsVerticesCount;
            }
            GameObject groundGO = new GameObject("Ground")
            {
                isStatic = true
            };

            groundGO.transform.SetParent(location.transform, false);
            MeshRenderer groundRenderer = groundGO.AddComponent <MeshRenderer>();

            groundRenderer.material = floorMaterial;
            Mesh groundMesh = new Mesh()
            {
                vertices = vertices, triangles = triangles
            };

            groundMesh.Simplify();
            groundMesh.RecalculateNormals();
            //ground uv
            Vector2[] groundUV       = new Vector2[groundMesh.vertexCount];
            Vector2[] groundUV2      = new Vector2[groundMesh.vertexCount];
            Vector3[] groundVertices = groundMesh.vertices;
            Vector2[] vertexNormals  = marchingSquares.GetVertexNormals(groundMesh.vertices, groundMesh.triangles);
            for (int i = 0; i < groundVertices.Length; i++)
            {
                groundUV[i]  = new Vector2(0.5f + groundVertices[i].x / segmentSize, 0.5f + groundVertices[i].z / segmentSize);
                groundUV2[i] = groundUV[i] - uvPadding * vertexNormals[i];
            }

            groundMesh.uv  = groundUV;
            groundMesh.uv2 = groundUV2;

            MeshFilter groundFilter = groundGO.AddComponent <MeshFilter>();

            groundFilter.mesh = groundMesh;

            //next walls
            bool       createWalls = false;
            GameObject wallsGO     = new GameObject("Walls")
            {
                isStatic = true
            };

            if (wallsData.vertices.Count > 0)
            {
                createWalls = true;
                wallsGO.transform.SetParent(location.transform, false);
                MeshRenderer wallsRenderer = wallsGO.AddComponent <MeshRenderer>();
                wallsRenderer.material = wallsMaterial;
                Mesh wallsMesh = new Mesh()
                {
                    vertices = wallsData.vertices.ToArray(), triangles = wallsData.triangles.ToArray()
                };

                wallsMesh.RecalculateNormals();
                //next we should calculate uv coordinates
                //all polygons are separate 4-sided polygons
                Vector2[] wallsUV = marchingSquares.GetWallsUV();
                Vector2[] uv1     = new Vector2[wallsUV.Length];
                Vector2[] uv2     = new Vector2[wallsUV.Length];
                //uv2 should be fit to the square [0, 1]x[0, 1]
                //for uv1 rescale 1 to walls height
                float wallLength = marchingSquares.GetWallLength();
                for (int i = 0; i < wallsUV.Length; i++)
                {
                    Vector2 uv = wallsUV[i];
                    uv1[i] = new Vector2(uv.x / height, uv.y);
                    uv2[i] = new Vector2(uv.x / wallLength, uv.y);
                }

                wallsMesh.uv  = uv1;
                wallsMesh.uv2 = uv2;

                MeshFilter wallsFilter = wallsGO.AddComponent <MeshFilter>();
                wallsFilter.mesh = wallsMesh;
            }


            WG_LocationController locationController = location.AddComponent <WG_LocationController>();

            locationController.groundGO = groundGO;
            locationController.wallsGO  = createWalls ? wallsGO : null;
            locationController.u        = u;
            locationController.v        = v;

            if (!createWalls)
            {
                UnityEngine.Object.DestroyImmediate(wallsGO);
            }

            return(locationController);
        }
コード例 #7
0
        public void BuildMesh()
        {
#if UNITY_EDITOR
            //clear generated segments
            navmeshExist = false;
            //create helper object for all sub-generated objects
            GameObject store = new GameObject()
            {
                name = "Temp Store"
            };
            Transform[] allTransforms = gameObject.GetComponentsInChildren <Transform>();
            for (int trIndex = allTransforms.Length - 1; trIndex >= 0; trIndex--)
            {
                GameObject go = allTransforms[trIndex].gameObject;
                //try to get noise primitive component
                //if this component is null, then delete game object
                WG_Primitive_PerlinNoise noiseComponent = go.GetComponent <WG_Primitive_PerlinNoise>();
                WG_Primitive_Paint       paintComponent = go.GetComponent <WG_Primitive_Paint>();
                WG_Painter      painterComponent        = go.GetComponent <WG_Painter>();
                WG_VisualCenter visCenterComponent      = go.GetComponent <WG_VisualCenter>();
                if (go != gameObject && noiseComponent == null && paintComponent == null && painterComponent == null && visCenterComponent == null)
                {
                    if (clearAll)
                    {
                        DestroyImmediate(go);
                    }
                    else
                    {
                        //check is this object contains location controller
                        WG_LocationController locController = go.GetComponent <WG_LocationController>();
                        if (locController != null)
                        {//this is location root object, destoy it
                            DestroyImmediate(go);
                        }
                        else
                        {     //this is not location root, may be walls or ground object
                            if (go.name == groundName || go.name == wallsName || go.name == meshRootName)
                            { //this is generated ground or wall object, destoy it
                                DestroyImmediate(go);
                            }
                            else
                            {//this is sub-placed object, store it
                                if (PrefabUtility.GetOutermostPrefabInstanceRoot(go) == null || PrefabUtility.GetOutermostPrefabInstanceRoot(go) == go)
                                {
                                    go.transform.SetParent(store.transform, true);
                                }
                            }
                        }
                    }
                }
            }
            //fill map for all location segments
            bool[,] map = new bool[(segmenstMaxX - segmentsMinX + 1) * meshSquaresCount + 1, (segmenstMaxY - segmentsMinY + 1) * meshSquaresCount + 1];
            WG_Primitive_BaseNoise[] noises = gameObject.GetComponentsInChildren <WG_Primitive_BaseNoise>();
            float   meshSquareSize          = segmentSize / meshSquaresCount;
            Vector2 bottomLeftCorner        = new Vector2((segmentsMinX - 0.5f) * segmentSize, (segmentsMinY - 0.5f) * segmentSize);
            for (int x = 0; x < map.GetLength(0); x++)
            {
                for (int y = 0; y < map.GetLength(1); y++)
                {
                    Vector2 pos = new Vector2(x * meshSquareSize, y * meshSquareSize) + bottomLeftCorner;
                    map[x, y] = IsPointMountains(pos, noises);
                }
            }

            //next create root for location segments
            GameObject locationsRoot = new GameObject {
                name = meshRootName
            };
            locationsRoot.transform.SetParent(gameObject.transform);
            //create location generator
            WG_SegmentsGenerator         generator = new WG_SegmentsGenerator();
            List <WG_LocationController> locations = generator.GenerateLocationSegments(this, segmentSize, meshSquareSize, meshSquaresCount, segmentsMinX, segmenstMaxX, segmentsMinY, segmenstMaxY, locationsRoot, groundMaterial, mountainsMaterial, wallsMaterial, map, mountainsHeight, !(forceUpdate && buildMesh), navMeshCutVolume, uv2Padding);
#endif

#if UNITY_EDITOR
            //after generation we should place back all stored objects, we will place it inside location root object
            Transform[] storedObjects = store.GetComponentsInChildren <Transform>();
            for (int tfmIndex = 0; tfmIndex < storedObjects.Length; tfmIndex++)
            {
                Transform tfm = storedObjects[tfmIndex];
                if (tfm.gameObject != store)
                {
                    Vector3 position          = tfm.position;
                    IntPair locCoords         = WG_Helper.GetLocationCoordinates(position, segmentSize);
                    WG_LocationController loc = GetLocationByCoordinates(locCoords, locations);
                    if (loc != null)
                    {
                        //rever prefab properties (mesh and material)
                        GameObject prefabMaster  = PrefabUtility.GetOutermostPrefabInstanceRoot(tfm.gameObject);
                        MeshFilter meshComponent = tfm.GetComponent <MeshFilter>();
                        if ((prefabMaster == null && meshComponent != null) || prefabMaster == tfm.gameObject)
                        {
                            Vector3    scale  = tfm.localScale;
                            GameObject source = PrefabUtility.GetCorrespondingObjectFromSource(tfm.gameObject);
                            if (source != null)
                            {
                                PrefabUtility.RevertPrefabInstance(tfm.gameObject, InteractionMode.UserAction);
                            }

                            tfm.localScale = scale;

                            //move object inside location
                            tfm.SetParent(loc.gameObject.transform, true);
                            tfm.position += loc.gameObject.transform.position;
                        }
                    }
                    else
                    {
                        Debug.Log("There is no locations with coordinates " + locCoords.ToString() + ", so skip the object " + tfm.gameObject.name);
                    }
                }
            }
            //delete temp store
            DestroyImmediate(store);
            #endif

            BuildNavmeshOnly();
        }
コード例 #8
0
        void ExportScene(Transform locationRoot)
        {
            WG_Helper.ClearFolder(Application.dataPath + assetLocationSOPath);

            for (int i = 0; i < locationRoot.childCount; i++)
            {
                Transform             loc           = locationRoot.GetChild(i);
                WG_LocationController locController = loc.GetComponent <WG_LocationController>();

                if (locController != null)
                {
                    locController.ExportLocation("Assets" + assetLocationXMLPath, "Assets" + assetLocationSOPath, minimapSize, minimapCamera, minimapCameraHeight, "Assets" + assetMinimapPath);
                }
            }

#if UNITY_EDITOR
            //export navmesh
            WG_TerrainBuilder builderComponent = builder.gameObject.GetComponent <WG_TerrainBuilder>();
            NavMeshData       data             = builderComponent.GetNavmeshData();
            string            navmeshAssetPath = "";
            if (data != null)
            {
                navmeshAssetPath = "navmeshes/" + data.name;
                AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(data)).SetAssetBundleNameAndVariant(navmeshAssetPath, "");
            }
            else
            {
                if (localNavMesh == null)
                {
                    Debug.Log("Navmesh data is null, can't export it.");
                }
                else
                {
                    Debug.Log("Use local version of the navmesh data object.");
                    data             = localNavMesh;
                    navmeshAssetPath = "navmeshes/" + localNavMesh.name;
                    AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(localNavMesh)).SetAssetBundleNameAndVariant(navmeshAssetPath, "");
                }
            }

            //create xml with navmeshlink and starting points
            GlobalLocation globalLocation = new GlobalLocation();
            if (navmeshAssetPath.Length > 0 && data != null)
            {
                globalLocation.navmeshData = new NavmeshData()
                {
                    link = navmeshAssetPath, name = data.name
                };
                if (exportPlayerPositionsInLocations)
                {
                    globalLocation.positions = new List <PositionData>();
                    WG_Position[] positions = WG_Helper.FindObjectsOfTypeAll <WG_Position>().ToArray();// FindObjectsOfType<WG_Position>();
                    for (int i = 0; i < positions.Length; i++)
                    {
                        Vector3 pos = positions[i].gameObject.transform.position;
                        IntPair loc = WG_Helper.GetLocationCoordinates(pos, builderComponent.segmentSize);
                        if (loc.u >= builderComponent.segmentsMinX && loc.u <= builderComponent.segmenstMaxX && loc.v >= builderComponent.segmentsMinY && loc.v <= builderComponent.segmenstMaxY)
                        {
                            globalLocation.positions.Add(new PositionData()
                            {
                                positionX = pos.x, positionY = pos.y, positionZ = pos.z
                            });
                        }
                    }

                    if (globalLocation.positions.Count == 0)
                    {
                        Debug.Log("No start positions on the scene. Add default position (0, 0, 0).");
                        globalLocation.positions.Add(new PositionData()
                        {
                            positionX = 0.0f, positionY = 0.0f, positionZ = 0.0f
                        });
                    }
                }


                globalLocation.bounds = new LocationsBounds()
                {
                    minU = builderComponent.segmentsMinX,
                    maxU = builderComponent.segmenstMaxX,
                    minV = builderComponent.segmentsMinY,
                    maxV = builderComponent.segmenstMaxY
                };

                globalLocation.locationSize = new LocationSize()
                {
                    value = builderComponent.segmentSize
                };

                string globalLocationName      = "global_location";
                string globalLocationAssetPath = "Assets" + assetLocationXMLPath + globalLocationName + ".xml";
                globalLocation.Save(globalLocationAssetPath);
                AssetDatabase.ImportAsset(globalLocationAssetPath, ImportAssetOptions.ForceUpdate);
                AssetImporter.GetAtPath(globalLocationAssetPath).SetAssetBundleNameAndVariant("locations/" + globalLocationName, "");

                //export server data
                SavePlayerPositions(builderComponent);
                SaveCollisionMap(serverPath);
                SaveTowerPositions(builderComponent);

                //also export locations data to SO
                GlobalLocationDataSO globalSO = ScriptableObjectUtility.CreateAsset <GlobalLocationDataSO>("Assets" + assetLocationSOPath, globalLocationName);
                globalSO.minU = builderComponent.segmentsMinX;
                globalSO.maxU = builderComponent.segmenstMaxX;
                globalSO.minV = builderComponent.segmentsMinY;
                globalSO.maxV = builderComponent.segmenstMaxY;

                globalSO.size = builderComponent.segmentSize;

                globalSO.navmeshName = data.name;
                globalSO.navmeshLink = navmeshAssetPath;

                if (exportPlayerPositionsInLocations)
                {
                    globalSO.startPositions = new List <Vector3>();
                    for (int pi = 0; pi < globalLocation.positions.Count; pi++)
                    {
                        globalSO.startPositions.Add(new Vector3(globalLocation.positions[pi].positionX, globalLocation.positions[pi].positionY, globalLocation.positions[pi].positionZ));
                    }
                }

                EditorUtility.SetDirty(globalSO);
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
                AssetImporter.GetAtPath("Assets" + assetLocationSOPath + globalLocationName + ".asset").SetAssetBundleNameAndVariant("locations_so/" + globalLocationName, "");
            }
#endif
        }
コード例 #9
0
        void CombineLocation(GameObject locationRoot)
        {
#if UNITY_EDITOR
            //we should collect objects with the same material
            Dictionary <int, List <CombinerDataContainer> > materialMap = new Dictionary <int, List <CombinerDataContainer> >();
            Dictionary <int, Material> materials = new Dictionary <int, Material>();

            Transform[] allTransforms = locationRoot.transform.GetComponentsInChildren <Transform>();
            for (int i = 0; i < allTransforms.Length; i++)
            {
                GameObject            go            = allTransforms[i].gameObject;
                WG_LocationController locController = go.GetComponent <WG_LocationController>();
                if (locController == null)
                {
                    //Debug.Log(allTransforms[i].gameObject.name);
                    GameObject prefab = PrefabUtility.GetOutermostPrefabInstanceRoot(go);
                    if (prefab != null && prefab == go) // ignore individual generated objects
                    {                                   //this object is prefab, so, dive to it subobjects
                        //use this code only when we consider the root prefab object and ignore for all it subobjects
                        GameObject  source        = PrefabUtility.GetCorrespondingObjectFromSource(prefab);
                        Transform[] sourceSubtfms = source.transform.GetComponentsInChildren <Transform>();
                        Transform   goTfm         = go.transform;
                        if (sourceSubtfms.Length == 1)
                        {
                            //prefab contains only one object (it builded by proBuilder)
                            //use changed mesh filter of the original scene object
                            MeshFilter   mFilter   = go.GetComponent <MeshFilter>();
                            MeshRenderer mRenderer = go.GetComponent <MeshRenderer>();
                            if (mFilter != null && mRenderer != null)
                            {
                                Material m   = mRenderer.sharedMaterial;
                                int      mId = m.GetInstanceID();
                                if (materialMap.ContainsKey(mId))
                                {
                                    materialMap[mId].Add(new CombinerDataContainer()
                                    {
                                        go = go, worldMatrix = go.transform.localToWorldMatrix                                                /*toCenterTfm = goTfm*/
                                    });
                                }
                                else
                                {
                                    materialMap.Add(mId, new List <CombinerDataContainer>()
                                    {
                                        new CombinerDataContainer()
                                        {
                                            go = go, worldMatrix = go.transform.localToWorldMatrix                                                                                /*toCenterTfm = goTfm */
                                        }
                                    });
                                    materials.Add(mId, m);
                                }
                            }
                        }
                        else
                        {//for large prefab we use master prefab objects
                            for (int j = 0; j < sourceSubtfms.Length; j++)
                            {
                                GameObject   subObj    = sourceSubtfms[j].gameObject;
                                MeshFilter   mFilter   = subObj.GetComponent <MeshFilter>();
                                MeshRenderer mRenderer = subObj.GetComponent <MeshRenderer>();
                                if (mFilter != null && mRenderer != null && mFilter.sharedMesh != null) // ignore subobject, if the master prefab does not contains the mesh
                                {                                                                       //this object contains mesh
                                    Material m   = mRenderer.sharedMaterial;
                                    int      mId = m.GetInstanceID();
                                    if (materialMap.ContainsKey(mId))
                                    {
                                        materialMap[mId].Add(new CombinerDataContainer()
                                        {
                                            go = subObj, worldMatrix = go.transform.localToWorldMatrix * subObj.transform.localToWorldMatrix                                                /*toCenterTfm = goTfm, localTfm = subObj.transform*/
                                        });
                                    }
                                    else
                                    {
                                        materialMap.Add(mId, new List <CombinerDataContainer>()
                                        {
                                            new CombinerDataContainer()
                                            {
                                                go = subObj, worldMatrix = go.transform.localToWorldMatrix * subObj.transform.localToWorldMatrix                                                                                /*toCenterTfm = goTfm, localTfm = subObj.transform*/
                                            }
                                        });
                                        materials.Add(mId, m);
                                    }
                                }
                            }
                        }

                        //mark original objects and disable it
                        go.AddComponent <WG_Tag_MasterPrefab>();
                        go.SetActive(false);
                    }
                }
            }

            //builded material map
            Matrix4x4 rootMatrix = locationRoot.transform.worldToLocalMatrix;
            foreach (int mId in materialMap.Keys)
            {
                //Debug.Log(mId.ToString() + ": " + materials[mId].name);
                //we should create new mesh for all objects with this material
                List <Vector3> vertices  = new List <Vector3>();
                List <int>     triangles = new List <int>();
                List <Vector2> uvs       = new List <Vector2>();
                List <Vector3> normals   = new List <Vector3>();
                List <Vector4> tangents  = new List <Vector4>();

                int indexShift = 0;

                for (int i = 0; i < materialMap[mId].Count; i++)
                {
                    GameObject go = materialMap[mId][i].go;  // here we should use transform relative to the master prefab (we should store it separatly)
                    //Debug.Log("\tobject " + go.name);
                    //Transform tfm = materialMap[mId][i].toCenterTfm;
                    //Matrix4x4 globalMatrix = tfm.localToWorldMatrix;

                    //Matrix4x4   = rootMatrix * globalMatrix;
                    Matrix4x4 changeMatrix = rootMatrix * materialMap[mId][i].worldMatrix;
                    //if(materialMap[mId][i].localTfm != null)
                    //{
                    //changeMatrix = changeMatrix * materialMap[mId][i].localTfm.localToWorldMatrix;
                    //}

                    MeshFilter mFilter = go.GetComponent <MeshFilter>();
                    Mesh       mesh    = mFilter.sharedMesh;
                    Vector3[]  vs      = mesh.vertices;
                    for (int j = 0; j < vs.Length; j++)
                    {
                        vertices.Add(changeMatrix.MultiplyPoint(vs[j]));
                    }
                    //Debug.Log("\t\tvetices: " + vs.Length.ToString());
                    int[] trs = mesh.triangles;
                    for (int j = 0; j < trs.Length; j++)
                    {
                        triangles.Add(trs[j] + indexShift);
                    }

                    Vector2[] mvs = mesh.uv;
                    for (int j = 0; j < vs.Length; j++)
                    {
                        uvs.Add(mvs[j]);
                    }

                    Vector3[] nms = mesh.normals;
                    for (int j = 0; j < nms.Length; j++)
                    {
                        normals.Add(changeMatrix.MultiplyVector(nms[j]).normalized);
                    }
                    Vector4[] tgs = mesh.tangents;
                    for (int j = 0; j < tgs.Length; j++)
                    {
                        Vector4 t = changeMatrix.MultiplyVector(tgs[j]);
                        t.w = tgs[j].w;
                        tangents.Add(t);
                    }
                    //Debug.Log("\t\tnormals: " + nms.Length.ToString());

                    indexShift += vs.Length;
                }

                Mesh combinedMesh = new Mesh();
                combinedMesh.vertices  = vertices.ToArray();
                combinedMesh.triangles = triangles.ToArray();
                combinedMesh.uv        = uvs.ToArray();
                combinedMesh.normals   = normals.ToArray();
                combinedMesh.tangents  = tangents.ToArray();
                //Debug.Log("\tset vertices: " + vertices.Count.ToString() + ", normals: " + normals.Count.ToString());

                Unwrapping.GenerateSecondaryUVSet(combinedMesh);

                //create game object
                GameObject combinedGO = new GameObject("combined_" + materials[mId].name)
                {
                    isStatic = true
                };
                MeshFilter cmf = combinedGO.AddComponent <MeshFilter>();
                cmf.mesh = combinedMesh;

                combinedGO.transform.SetParent(locationRoot.transform, false);
                MeshRenderer cmr = combinedGO.AddComponent <MeshRenderer>();
                cmr.material = materials[mId];

                combinedGO.AddComponent <WG_Tag_CombineMesh>();
                //StaticEditorFlags flags = StaticEditorFlags.NavigationStatic | StaticEditorFlags.ContributeGI;
                //GameObjectUtility.SetStaticEditorFlags(combinedGO, flags);
            }
#endif
        }