示例#1
0
            //removing v2,
            public void Replace( VoxelVert v2  )
            {
                //assigning this to all v2 faces
                for (int f = 0; f<6; f++)
                    if (v2.faces[f]!=null) for (int v=0; v<8; v++)
                        if (v2.faces[f].verts[v] == v2)  v2.faces[f].verts[v] = this;

                for (int i = 0; i<6; i++)
                {
                    //if (v2.neigs[i]!=null) AddNeig(v2.neigs[i]);
                    if (v2.faces[i]!=null) AddFace(v2.faces[i]);
                }
            }
示例#2
0
        public void CalculateTerrain()
        {
            terrainProgress = Progress.threadStarted;
            //bool isMainThread = System.Threading.Thread.CurrentThread.ManagedThreadId == Voxel.mainThreadId;
            //bool isMainThread = false;

            int x=0; int y=0; int z=0; //int nx=0; int ny=0; int nz=0;
            int dir = 0; int v=0; int f=0; int i = 0;
            VoxelBlock block; VoxelFace face; VoxelVert vert;// VoxelFace nface;
            //Vector3 pos;

            System.Collections.Generic.List<VoxelFace> faces = new System.Collections.Generic.List<VoxelFace>();

            #region Calculating top and bottom points
            int topPoint = land.data.GetTopPoint(offsetX, offsetZ, offsetX+size, offsetZ+size)+1;
            int bottomPoint = Mathf.Max(0, land.data.GetBottomPoint(offsetX, offsetZ, offsetX+size, offsetZ+size)-2);
            int shortHeight = topPoint - bottomPoint;

            //emergency exit if chunk contains no blocks
            if (topPoint<=1) { visibleFaces.Clear(); terrainProgress = Progress.calculated; return; }
            #endregion

            bool[] existMatrix = new bool[size*size*shortHeight];
            land.data.GetExistMatrix (existMatrix,  offsetX, bottomPoint, offsetZ,  offsetX+size, topPoint, offsetZ+size);

            VoxelBlock[] blocks = new VoxelBlock[size*shortHeight*size];

            #region Creating all faces

            //for (y=bottomPoint; y<topPoint; y++)
            for (y=0; y<shortHeight; y++)
                for (x=0; x<size; x++)
                    for (z=0; z<size; z++)
                {
                    i = z*shortHeight*size + y*size + x;

                    //if exists
                    //if (land.data.GetExist(x+offsetX,y,z+offsetZ))
                    if (existMatrix[z*size*shortHeight + y*size + x])
                        for (dir = 0; dir<6; dir++)
                    {
                        //if has face at this side
                        if (x+VoxelFace.dirToPosX[dir] >= 0 && x+VoxelFace.dirToPosX[dir] < size &&  //cap sides here
                            y+VoxelFace.dirToPosY[dir] >= 0 && y+VoxelFace.dirToPosY[dir] < shortHeight &&
                            z+VoxelFace.dirToPosZ[dir] >= 0 && z+VoxelFace.dirToPosZ[dir] < size &&
                            !existMatrix[ (z+VoxelFace.dirToPosZ[dir])*size*shortHeight + (y+VoxelFace.dirToPosY[dir])*size + x+VoxelFace.dirToPosX[dir] ])
                        {
                            if (blocks[i]==null)
                            {
                                blocks[i] = new VoxelBlock(x,y+bottomPoint,z);

                                if (x<land.overlap || x>=size-land.overlap ||
                                    z<land.overlap || z>=size-land.overlap ||
                                    y == 0)
                                        blocks[i].visible = false;
                                else blocks[i].visible = true;

                                byte typeNum = land.data.GetBlock(x+offsetX, y+bottomPoint, z+offsetZ);
                                if (typeNum < land.types.Length) blocks[i].type = land.types[typeNum];
                                else blocks[i].type = land.types[0];

                                blocks[i].chunk = this;
                            }

                            face = new VoxelFace();
                            faces.Add(face);

                            blocks[i].faces[dir] = face;

                            face.block = blocks[i];
                            face.dir = (byte)dir;

                            //setting face type, and adding it to used types array
                            //face.type = (byte)land.data.GetBlock(x+offsetX, y+bottomPoint, z+offsetZ);
                            //if (!usedTypes.Contains(face.type)) usedTypes.Add(face.type);

                            face.visible = face.block.type.filled; //land.data.exist[face.block.type]; //land.types[face.block.type].visible;

                            //setting coords
                            for (v=0;v<9;v++)
                            {
                                //pos = VoxelVert.posTable[ dir*9 + v ] + new Vector3(x,y,z);
                                //face.coords[v] = 1000000 + pos.x*20000 + pos.y*200 + pos.z*2;
                            }
                        }
                    }
                }
            #endregion

            #region Welding internal, Welding neig

            int maxSize = size-1;
            int maxHeight = shortHeight-1;

            for (y=0; y<shortHeight; y++)
                for (x=0; x<size; x++)
                    for (z=0; z<size; z++)
            {
                    int stepz = shortHeight*size;
                    i = z*stepz + y*size + x;

                    if (blocks[i]!=null) for (dir = 0; dir<6; dir++)
                    {
                        block = blocks[i];
                        face = block.faces[dir];
                        if (face==null) continue;

                        //weld this block
                        switch (dir)
                        {
                        case 0: face.Weld( block, 5,  0,1,2, 2,1,0); face.Weld( block, 2,  2,3,4, 2,1,0);
                            face.Weld( block, 4,  4,5,6, 2,1,0); face.Weld( block, 3,  6,7,0, 2,1,0);

                            if (x>0) face.Weld( blocks[i-1], 0,  6,7,0, 4,3,2);
                            if (z>0) face.Weld( blocks[i-stepz], 0,  4,5,6, 2,1,0);

                            break;

                        case 1: face.Weld( block, 5,  0,1,2, 6,5,4); face.Weld( block, 3,  2,3,4, 6,5,4);
                            face.Weld( block, 4,  4,5,6, 6,5,4); face.Weld( block, 2,  6,7,0, 6,5,4);

                            if (x>0) face.Weld( blocks[i-1], 1,  2,3,4, 0,7,6);
                            if (z>0) face.Weld( blocks[i-stepz], 1,  4,5,6, 2,1,0);

                            break;

                        case 2: face.Weld( block, 0,  0,1,2, 4,3,2); face.Weld( block, 5,  2,3,4, 0,7,6);
                            face.Weld( block, 1,  4,5,6, 0,7,6); face.Weld( block, 4,  6,7,0, 4,3,2);

                            if (y>0) face.Weld( blocks[i-size], 2,  4,5,6, 2,1,0);
                            if (z>0) face.Weld( blocks[i-stepz], 2,  6,7,0, 4,3,2);

                            break;

                        case 3: face.Weld( block, 0,  0,1,2, 0,7,6); face.Weld( block, 4,  2,3,4, 0,7,6);
                            face.Weld( block, 1,  4,5,6, 4,3,2); face.Weld( block, 5,  6,7,0, 4,3,2);

                            if (y>0) face.Weld( blocks[i-size], 3,  4,5,6, 2,1,0);
                            if (z>0) face.Weld( blocks[i-stepz], 3,  2,3,4, 0,7,6);

                            break;

                        case 4: face.Weld( block, 0,  0,1,2, 6,5,4); face.Weld( block, 2,  2,3,4, 0,7,6);
                            face.Weld( block, 1,  4,5,6, 6,5,4); face.Weld( block, 3,  6,7,0, 4,3,2);

                            if (y>0) face.Weld( blocks[i-size], 4,  4,5,6, 2,1,0);
                            if (x>0) face.Weld( blocks[i-1], 4,  6,7,0, 4,3,2);

                            break;

                        case 5: face.Weld( block, 0,  0,1,2, 2,1,0); face.Weld( block, 3,  2,3,4, 0,7,6);
                            face.Weld( block, 1,  4,5,6, 2,1,0); face.Weld( block, 2,  6,7,0, 4,3,2);

                            if (y>0) face.Weld( blocks[i-size], 5,  4,5,6, 2,1,0);
                            if (x>0) face.Weld( blocks[i-1], 5,  2,3,4, 0,7,6);

                            break;
                        }
                    }
            }
            #endregion

            #region Cross-welding

            for (y=0; y<shortHeight; y++)
                for (x=0; x<size; x++)
                    for (z=0; z<size; z++)
            {
                    int stepz = shortHeight*size;
                    i = z*stepz + y*size + x;
                    int j = i;

                    if (blocks[i]!=null) for (dir = 0; dir<6; dir++)
                    {
                        face = blocks[i].faces[dir];
                        if (face==null) continue;

                        //weld cross block
                        if (dir==0 && y<maxHeight)
                        {
                            j = i+size;
                            if (x>0) face.Weld( blocks[j-1], 2,  6,7,0, 6,5,4); 		//x-1,y+1,z
                            if (z>0) face.Weld( blocks[j-stepz], 5,  4,5,6, 6,5,4); 	//x,y+1,z-1
                            if (x<maxSize) face.Weld( blocks[j+1], 3,  2,3,4, 6,5,4); 	//x+1,y+1,z
                            if (z<maxSize) face.Weld( blocks[j+stepz], 4,  0,1,2, 6,5,4); 	//x,y+1,z+1
                        }

                        else if (dir==1 && y>0)
                        {
                            j = i-size;
                            if (x>0) face.Weld( blocks[j-1], 2,  2,3,4, 2,1,0);		//x-1,y-1,z
                            if (z>0) face.Weld( blocks[j-stepz], 5,  4,5,6, 2,1,0);		//x,y-1,z-1
                            if (x<maxSize) face.Weld( blocks[j+1], 3,  6,7,0, 2,1,0);		//x+1,y-1,z
                            if (z<maxSize) face.Weld( blocks[j+stepz], 4,  0,1,2, 2,1,0);		//x,y-1,z+1
                        }

                        else if (dir==2 && x<maxSize)
                        {
                            j = i+1;
                            if (y>0) face.Weld( blocks[j-size], 0,  4,5,6, 0,7,6);		//x+1,y-1,z
                            if (z>0) face.Weld( blocks[j-stepz], 5,  6,7,0, 4,3,2);		//x+1,y,z-1
                            if (y<maxHeight) face.Weld( blocks[j+size], 1,  0,1,2, 4,3,2);//x+1,y+1,z
                            if (z<maxSize) face.Weld( blocks[j+stepz], 4,  2,3,4, 0,7,6);		//x+1,y,z+1
                        }

                        else if (dir==3 && x>0)
                        {
                            j = i-1;
                            if (y>0) face.Weld( blocks[j-size], 0,  4,5,6, 4,3,2);		//x-1,y-1,z
                            if (z>0) face.Weld( blocks[j-stepz], 5,  2,3,4, 0,7,6);		//x-1,y,z-1
                            if (y<maxHeight) face.Weld( blocks[j+size], 1,  0,1,2, 0,7,6);//x-1,y+1,z
                            if (z<maxSize) face.Weld( blocks[j+stepz], 4,  6,7,0, 4,3,2);		//x-1,y,z+1
                        }

                        else if (dir==4 && z>0)
                        {
                            j = i-stepz;
                            if (y>0) face.Weld( blocks[j-size], 0,  4,5,6, 2,1,0);		//x,y-1,z-1
                            if (x>0) face.Weld( blocks[j-1], 2,  6,7,0, 4,3,2);		//x-1,y,z-1
                            if (y<maxHeight) face.Weld( blocks[j+size], 1,  0,1,2, 2,1,0);//x,y+1,z-1
                            if (x<maxSize) face.Weld( blocks[j+1], 3,  2,3,4, 0,7,6);		//x+1,y,z-1
                        }

                        else if (dir==5 && z<maxSize)
                        {
                            j = i+stepz;
                            if (y>0) face.Weld( blocks[j-size], 0,  4,5,6, 6,5,4);		//x,y-1,z+1
                            if (x>0) face.Weld( blocks[j-1], 2,  2,3,4, 0,7,6);		//x-1,y,z+1
                            if (y<maxHeight) face.Weld( blocks[j+size], 1,  0,1,2, 6,5,4);//x,y+1,z+1
                            if (x<maxSize) face.Weld( blocks[j+1], 3,  6,7,0, 4,3,2);		//x+1,y,z+1
                        }

                        for (v=0;v<9;v++)
                        {
                            vert = face.verts[v];

                            //setting new vert
                            if (vert==null)
                            {
                                vert = new VoxelVert();
                                face.verts[v] = vert;
                            }

                            vert.pos = VoxelVert.posTable[ dir*9 + v ] + new Vector3(x,y,z);

                            vert.AddFace(face);
                        }

                        //face.LinkVerts();
                    }
            }
            #endregion

            #region Linking (adding verts neigs)
            for (f=0;f<faces.Count;f++) faces[f].LinkVerts();
            #endregion

            #region Lifting on BottomPoint
            for (f=0;f<faces.Count;f++)
            {
                face = faces[f];
                for (v=0;v<9;v++)
                    if (!face.verts[v].processed)
                {
                    face.verts[v].pos += new Vector3(0,bottomPoint,0);
                    face.verts[v].processed = true;
                }
            }

            for (f=0;f<faces.Count;f++) //clearing
                for (v=0;v<9;v++)
                    faces[f].verts[v].processed = false;
            #endregion

            #region Relaxing

            //setting vert relax
            for (f=0;f<faces.Count;f++)
            {

                for (v=0;v<9;v++)
                {
                    faces[f].verts[v].relax += faces[f].block.type.smooth;
                    faces[f].verts[v].relaxCount += 1;
                }
            }

            for (f=0;f<faces.Count;f++)
                for (v=0;v<9;v++)
                    if (faces[f].verts[v].relaxCount != 0)
            {
                faces[f].verts[v].relax = faces[f].verts[v].relax / faces[f].verts[v].relaxCount;
                faces[f].verts[v].relaxCount = 0;
            }

            //averaging corners
            for (f=0;f<faces.Count;f++)
            {
                face = faces[f];

                if (!face.verts[0].processed) { face.verts[0].pos += face.verts[0].GetRelax()*2; face.verts[0].processed=true; }
                if (!face.verts[2].processed) { face.verts[2].pos += face.verts[2].GetRelax()*2; face.verts[2].processed=true; }
                if (!face.verts[4].processed) { face.verts[4].pos += face.verts[4].GetRelax()*2; face.verts[4].processed=true; }
                if (!face.verts[6].processed) { face.verts[6].pos += face.verts[6].GetRelax()*2; face.verts[6].processed=true; }
            }

            //averaging mid verts
            for (f=0;f<faces.Count;f++)
            {
                face = faces[f];

                face.verts[1].pos = (face.verts[0].pos + face.verts[2].pos) * 0.5f;
                face.verts[3].pos = (face.verts[2].pos + face.verts[4].pos) * 0.5f;
                face.verts[5].pos = (face.verts[4].pos + face.verts[6].pos) * 0.5f;
                face.verts[7].pos = (face.verts[6].pos + face.verts[0].pos) * 0.5f;

                face.verts[8].pos = (face.verts[0].pos + face.verts[2].pos + face.verts[4].pos + face.verts[6].pos) * 0.25f;

                //returning processed flags
                face.verts[0].processed = false;
                face.verts[2].processed = false;
                face.verts[4].processed = false;
                face.verts[6].processed = false;
            }

            //seconary relax
            for (f=0;f<faces.Count;f++)
            {
                face = faces[f];

                for (v=0;v<9;v++)
                    if (!face.verts[v].processed)
                {
                    face.verts[v].relaxed = face.verts[v].GetRelax();
                    face.verts[v].processed = true;
                }
            }

            for (f=0;f<faces.Count;f++)
                for (v=0;v<9;v++)
                    faces[f].verts[v].processed = false;

            for (f=0;f<faces.Count;f++)
            {
                face = faces[f];

                for (v=0;v<9;v++)
                    if (!face.verts[v].processed)
                {
                    face.verts[v].pos += face.verts[v].relaxed;
                    face.verts[v].processed = true;
                }
            }
            #endregion

            #region Setting normals
            for (f=0;f<faces.Count;f++)
            {
                face = faces[f];

                face.verts[0].normal += Vector3.Cross(face.verts[1].pos-face.verts[0].pos, face.verts[7].pos-face.verts[0].pos).normalized;
                face.verts[2].normal += Vector3.Cross(face.verts[3].pos-face.verts[2].pos, face.verts[1].pos-face.verts[2].pos).normalized;
                face.verts[4].normal += Vector3.Cross(face.verts[5].pos-face.verts[4].pos, face.verts[3].pos-face.verts[4].pos).normalized;
                face.verts[6].normal += Vector3.Cross(face.verts[7].pos-face.verts[6].pos, face.verts[5].pos-face.verts[6].pos).normalized;

                face.verts[1].normal += Vector3.Cross(face.verts[8].pos-face.verts[1].pos, face.verts[0].pos-face.verts[1].pos).normalized +
                    Vector3.Cross(face.verts[2].pos-face.verts[1].pos, face.verts[8].pos-face.verts[1].pos).normalized;
                face.verts[3].normal += Vector3.Cross(face.verts[8].pos-face.verts[3].pos, face.verts[2].pos-face.verts[3].pos).normalized +
                    Vector3.Cross(face.verts[4].pos-face.verts[3].pos, face.verts[8].pos-face.verts[3].pos).normalized;
                face.verts[5].normal += Vector3.Cross(face.verts[8].pos-face.verts[5].pos, face.verts[4].pos-face.verts[5].pos).normalized +
                    Vector3.Cross(face.verts[6].pos-face.verts[5].pos, face.verts[8].pos-face.verts[5].pos).normalized;
                face.verts[7].normal += Vector3.Cross(face.verts[8].pos-face.verts[7].pos, face.verts[6].pos-face.verts[7].pos).normalized +
                    Vector3.Cross(face.verts[0].pos-face.verts[7].pos, face.verts[8].pos-face.verts[7].pos).normalized;

                face.verts[8].normal = Vector3.Cross(face.verts[1].pos-face.verts[5].pos, face.verts[3].pos-face.verts[7].pos).normalized;
            }

            if (land.normalsRandom > 0.01f)
            {
                for (x=0; x<size; x++)
                    for (z=0; z<size; z++)
                        for (y=0; y<shortHeight; y++)
                    {
                        i = z*shortHeight*size + y*size + x;

                        if (blocks[i]==null) continue;
                        if (!blocks[i].visible) continue;

                        Vector3 normalRandom = new Vector3(Random.value-0.5f, Random.value-0.5f, Random.value-0.5f)*1;

                        for (f=0;f<6;f++) if (blocks[i].faces[f]!=null && blocks[i].faces[f].visible)
                            for (v=0;v<9;v++) blocks[i].faces[f].verts[v].normal += normalRandom;
                    }
            }
            #endregion

            #region Set visible faces
            //visibleFaces.Clear();
            visibleFaces = new System.Collections.Generic.List<VoxelFace>();
            for (x=0; x<size; x++)
                for (z=0; z<size; z++)
                    for (y=0; y<shortHeight; y++)
                {
                    i = z*shortHeight*size + y*size + x;

                    if (blocks[i]==null) continue;
                    if (!blocks[i].visible) continue;
                    for (f=0;f<6;f++) if (blocks[i].faces[f]!=null && blocks[i].faces[f].visible)
                        visibleFaces.Add(blocks[i].faces[f]);
                }
            #endregion

            #region Set collider hierarchy
            boundsMin = new Vector2(offsetX + land.overlap, offsetZ + land.overlap);
            boundsMax = new Vector2(offsetX - land.overlap*2 + size, offsetZ - land.overlap*2 + size);
            boundsCenter = (boundsMin+boundsMax) / 2f;

            faceHolders = new FaceHolder[16];
            int facesPerHolder = Mathf.CeilToInt((size-land.overlap*2) / 4f);
            for (x=0; x<4; x++)
                for (z=0; z<4; z++)
            {
                faceHolders[z*4+x] = new FaceHolder();
                faceHolders[z*4+x].faces = new List<VoxelFace>();
                faceHolders[z*4+x].min = new Vector2(boundsMin.x + facesPerHolder*x, boundsMin.y + facesPerHolder*z);
                faceHolders[z*4+x].center = faceHolders[z*4+x].min + new Vector2(facesPerHolder/2f, facesPerHolder/2f);

                if (x==3) faceHolders[z*4+x].max = new Vector2(boundsMax.x, boundsMin.y + facesPerHolder*(z+1));
                else if (z==3) if (x==3) faceHolders[z*4+x].max = new Vector2(boundsMin.x + facesPerHolder*(x+1), boundsMax.y);
                else faceHolders[z*4+x].max = new Vector2(boundsMin.x + facesPerHolder*(x+1), boundsMin.y + facesPerHolder*(z+1));
            }

            for (f=0; f<visibleFaces.Count; f++)
            {
                face = visibleFaces[f];
                x = face.block.x / facesPerHolder;
                z = face.block.z / facesPerHolder;
                faceHolders[z*4+x].faces.Add(face);
            }
            #endregion

            terrainProgress = Progress.calculated;
        }
示例#3
0
            public void AddNeig( VoxelVert vert  )
            {
                if (neigs==null) neigs = new VoxelVert[7];
                if (neigCount==0) { neigs[0]=vert; neigCount=1; return; }

                switch (neigCount)
                {
                case 0:
                    neigs[0]=vert;
                    neigCount=1;
                    break;

                case 1:
                    if (neigs[0].coords!=vert.coords)
                    {
                        neigs[1]=vert;
                        neigCount=2;
                    }
                    break;

                default:
                    for (int i=0; i<neigCount; i++)
                        if (neigs[i].coords == vert.coords) return; //already added
                    neigs[neigCount]=vert;
                    neigCount++;
                    break;
                }
            }