Пример #1
0
 public void addObject(String key, warp_Object obj)
 {
     obj.name = key;
     objectData.Add(key, obj);
     obj.parent         = this;
     objectsNeedRebuild = true;
 }
 public void addObject(String key, warp_Object obj)
 {
     obj.name=key;
     objectData.Add(key, obj);
     obj.parent=this;
     objectsNeedRebuild=true;
 }
Пример #3
0
        public warp_FXLensFlare( String name, warp_Scene scene, bool zBufferSensitive ) : base( scene )
	    {
            this.zBufferSensitive = zBufferSensitive;

		    flareObject=new warp_Object();
		    flareObject.addVertex(new warp_Vertex(1f,1f,1f));
		    flareObject.rebuild();

		    scene.addObject(name, flareObject);
	    }
Пример #4
0
        public warp_FXLensFlare(String name, warp_Scene scene, bool zBufferSensitive) : base(scene)
        {
            this.zBufferSensitive = zBufferSensitive;

            flareObject = new warp_Object();
            flareObject.addVertex(new warp_Vector(1f, 1f, 1f));
            flareObject.rebuild();

            scene.addObject(name, flareObject);
        }
 public static void projectTop(warp_Object obj)
 {
     obj.rebuild();
     warp_Vector min = obj.minimum();
     warp_Vector max = obj.maximum();
     float du = 1 / (max.x - min.x);
     float dv = 1 / (max.z - min.z);
     for (int i = 0; i < obj.vertices; i++)
     {
         obj.fastvertex[i].u = (obj.fastvertex[i].pos.x - min.x) * du;
         obj.fastvertex[i].v = (obj.fastvertex[i].pos.z - min.z) * dv;
     }
 }
Пример #6
0
		public static void projectCylindric(warp_Object obj)
		{
			obj.rebuild();
			warp_Vector min = obj.minimum();
			warp_Vector max = obj.maximum();
			float dz = 1 / (max.z - min.z);
			for (int i = 0; i < obj.vertices; i++)
			{
				obj.fastvertex[i].pos.buildCylindric();
				obj.fastvertex[i].u = obj.fastvertex[i].pos.theta / (2 * 3.14159265f);
				obj.fastvertex[i].v = (obj.fastvertex[i].pos.z - min.z) * dz;
			}
		}		
        public static void projectCylindric(warp_Object obj)
        {
            obj.rebuild();
            warp_Vector min = obj.minimum();
            warp_Vector max = obj.maximum();
            float       dz  = 1 / (max.z - min.z);

            for (int i = 0; i < obj.vertices; i++)
            {
                obj.fastvertex[i].pos.buildCylindric();
                obj.fastvertex[i].u = obj.fastvertex[i].pos.theta / (2 * 3.14159265f);
                obj.fastvertex[i].v = (obj.fastvertex[i].pos.z - min.z) * dz;
            }
        }
        public static void projectFrontal(warp_Object obj)
        {
            obj.rebuild();
            warp_Vector min = obj.minimum();
            warp_Vector max = obj.maximum();
            float       du  = 1 / (max.x - min.x);
            float       dv  = 1 / (max.y - min.y);

            for (int i = 0; i < obj.vertices; i++)
            {
                obj.fastvertex[i].u = (obj.fastvertex[i].pos.x - min.x) * du;
                obj.fastvertex[i].v = 1 - (obj.fastvertex[i].pos.y - min.y) * dv;
            }
        }
Пример #9
0
        public static warp_Object BOX(float xsize, float ysize, float zsize)
        {
            float x = (float)Math.Abs(xsize / 2);
            float y = (float)Math.Abs(ysize / 2);
            float z = (float)Math.Abs(zsize / 2);

            float xx, yy, zz;

            warp_Object n = new warp_Object();

            int[] xflag = new int[6];
            int[] yflag = new int[6];
            int[] zflag = new int[6];

            xflag[0] = 10;
            yflag[0] = 3;
            zflag[0] = 0;
            xflag[1] = 10;
            yflag[1] = 15;
            zflag[1] = 3;
            xflag[2] = 15;
            yflag[2] = 3;
            zflag[2] = 10;
            xflag[3] = 10;
            yflag[3] = 0;
            zflag[3] = 12;
            xflag[4] = 0;
            yflag[4] = 3;
            zflag[4] = 5;
            xflag[5] = 5;
            yflag[5] = 3;
            zflag[5] = 15;

            for (int side = 0; side < 6; side++)
            {
                for (int i = 0; i < 4; i++)
                {
                    xx = ((xflag[side] & (1 << i)) > 0) ? x : -x;
                    yy = ((yflag[side] & (1 << i)) > 0) ? y : -y;
                    zz = ((zflag[side] & (1 << i)) > 0) ? z : -z;
                    n.addVertex(xx, yy, zz, i & 1, (i & 2) >> 1);
                }
                int t = side << 2;
                n.addTriangle(t, t + 2, t + 3);
                n.addTriangle(t, t + 3, t + 1);
            }

            return(n);
        }
Пример #10
0
		public static warp_Object BOX(float xsize, float ysize, float zsize)
		{
			float x = (float) Math.Abs(xsize / 2);
			float y = (float) Math.Abs(ysize / 2);
			float z = (float) Math.Abs(zsize / 2);

			float xx, yy, zz;

			warp_Object n = new warp_Object();
			int[] xflag = new int[6];
			int[] yflag = new int[6];
			int[] zflag = new int[6];

			xflag[0] = 10;
			yflag[0] = 3;
			zflag[0] = 0;
			xflag[1] = 10;
			yflag[1] = 15;
			zflag[1] = 3;
			xflag[2] = 15;
			yflag[2] = 3;
			zflag[2] = 10;
			xflag[3] = 10;
			yflag[3] = 0;
			zflag[3] = 12;
			xflag[4] = 0;
			yflag[4] = 3;
			zflag[4] = 5;
			xflag[5] = 5;
			yflag[5] = 3;
			zflag[5] = 15;

			for (int side = 0; side < 6; side++)
			{
				for (int i = 0; i < 4; i++)
				{
					xx = ( (xflag[side] & (1 << i)) > 0) ? x : -x;
					yy = ( (yflag[side] & (1 << i)) > 0) ? y : -y;
					zz = ( (zflag[side] & (1 << i)) > 0) ? z : -z;
					n.addVertex(xx, yy, zz, i & 1, (i & 2) >> 1);
				}
				int t = side << 2;
				n.addTriangle(t, t + 2, t + 3);
				n.addTriangle(t, t + 3, t + 1);
			}

			return n;
		}
Пример #11
0
        public static warp_Object ROTATIONOBJECT(warp_Vector[] path, int sides)
        {
            int         steps = sides + 1;
            warp_Object newObject = new warp_Object();
            double      alpha = 2 * pi / ((double)steps - 1);
            float       qx, qz;
            int         nodes = path.GetLength(0);
            warp_Vertex vertex = null;
            float       u, v;       // Texture coordinates

            for (int j = 0; j < steps; j++)
            {
                u = (float)(steps - j - 1) / (float)(steps - 1);
                for (int i = 0; i < nodes; i++)
                {
                    v  = (float)i / (float)(nodes - 1);
                    qx = (float)(path[i].x * Math.Cos(j * alpha) +
                                 path[i].z * Math.Sin(j * alpha));
                    qz = (float)(path[i].z * Math.Cos(j * alpha) -
                                 path[i].x * Math.Sin(j * alpha));
                    vertex   = new warp_Vertex(qx, path[i].y, qz);
                    vertex.u = u;
                    vertex.v = v;
                    newObject.addVertex(vertex);
                }
            }

            for (int j = 0; j < steps - 1; j++)
            {
                for (int i = 0; i < nodes - 1; i++)
                {
                    newObject.addTriangle(i + nodes * j, i + nodes * (j + 1),
                                          i + 1 + nodes * j);
                    newObject.addTriangle(i + nodes * (j + 1),
                                          i + 1 + nodes * (j + 1),
                                          i + 1 + nodes * j);
                }
            }

            for (int i = 0; i < nodes - 1; i++)
            {
                newObject.addTriangle(i + nodes * (steps - 1), i,
                                      i + 1 + nodes * (steps - 1));
                newObject.addTriangle(i, i + 1, i + 1 + nodes * (steps - 1));
            }
            return(newObject);
        }
Пример #12
0
        private void readNextJunk(string name, BinaryReader inStream)
        {
            readJunkHeader(inStream);

            if (currentJunkId == 0x3D3D /* mesh block */)
            {
                return;
            }

            if (currentJunkId == 0x4000 /* object block */)
            {
                currentObjectName = readString(inStream);
                return;
            }

            if (currentJunkId == 0x4100 /* triangular polygon object */)
            {
                currentObject = new warp_Object();
                _objects.Add(name + "_" + currentObjectName, currentObject);

                return;
            }

            if (currentJunkId == 0x4110 /* vertex list */)
            {
                readVertexList(inStream);
                return;
            }

            if (currentJunkId == 0x4120 /* point list */)
            {
                readPointList(inStream);
                return;
            }

            if (currentJunkId == 0x4140 /* mapping coordinates */)
            {
                readMappingCoordinates(inStream);
                return;
            }

            skipJunk(inStream);
        }
Пример #13
0
        public static warp_Object SIMPLEPLANE(float size, bool doubleSided)
        {
            warp_Object newObject = new warp_Object();

            newObject.addVertex(new warp_Vertex(-size, 0f, size, 0, 0));
            newObject.addVertex(new warp_Vertex(size, 0f, size, 4f, 0));
            newObject.addVertex(new warp_Vertex(size, 0f, -size, 4f, 4f));
            newObject.addVertex(new warp_Vertex(-size, 0f, -size, 0, 4f));

            newObject.addTriangle(0, 3, 2);
            newObject.addTriangle(0, 2, 1);

            if (doubleSided)
            {
                newObject.addTriangle(0, 2, 3);
                newObject.addTriangle(0, 1, 2);
            }

            return(newObject);
        }
Пример #14
0
		public static warp_Object SIMPLEPLANE(float size, bool doubleSided)
		{
			warp_Object newObject = new warp_Object();

            newObject.addVertex( new warp_Vertex( -size, 0f, size, 0, 0 ) );
            newObject.addVertex( new warp_Vertex( size, 0f, size, 4f, 0 ) );
            newObject.addVertex( new warp_Vertex( size, 0f, -size, 4f, 4f ) );
            newObject.addVertex( new warp_Vertex( -size, 0f, -size, 0, 4f ) );

			newObject.addTriangle(0, 3, 2);
			newObject.addTriangle(0, 2, 1);

			if(doubleSided)
			{
				newObject.addTriangle(0, 2, 3);
				newObject.addTriangle(0, 1, 2);
			}

			return newObject;
		}
Пример #15
0
        public warp_Object getClone()
        {
            warp_Object obj = new warp_Object();

            rebuild();
            for (int i = 0; i < vertices; i++)
            {
                obj.addVertex(fastvertex[i].getClone());
            }
            for (int i = 0; i < triangles; i++)
            {
                obj.addTriangle(fasttriangle[i].getClone());
            }
            obj.name         = name + " [cloned]";
            obj.material     = material;
            obj.matrix       = matrix.getClone();
            obj.normalmatrix = normalmatrix.getClone();
            obj.rebuild();
            return(obj);
        }
Пример #16
0
		public static warp_Object TUBE(warp_Vector[] path, float r, int steps, bool closed)
		{
			warp_Vector[] circle = new warp_Vector[steps];
			float angle;
			for (int i = 0; i < steps; i++)
			{
				angle = 2 * 3.14159265f * (float) i / (float) steps;
				circle[i] = new warp_Vector(r * warp_Math.cos(angle),
					r * warp_Math.sin(angle), 0f);
			}

			warp_Object newObject = new warp_Object();
			int segments = path.GetLength(0);
			warp_Vector forward, up, right;
			warp_Matrix frenetmatrix;
			warp_Vertex tempvertex;
			float relx, rely;
			int a, b, c, d;

			for (int i = 0; i < segments; i++)
			{
				// Calculate frenet frame matrix

				if (i != segments - 1)
				{
					forward = warp_Vector.sub(path[i + 1], path[i]);
				}
				else
				{
					if (!closed)
					{
						forward = warp_Vector.sub(path[i], path[i - 1]);
					}
					else
					{
						forward = warp_Vector.sub(path[1], path[0]);
					}
				}

				forward.normalize();
				up = new warp_Vector(0f, 0f, 1f);
				right = warp_Vector.getNormal(forward, up);
				up = warp_Vector.getNormal(forward, right);
				frenetmatrix = new warp_Matrix(right, up, forward);
				frenetmatrix.shift(path[i].x, path[i].y, path[i].z);

				// Add nodes

				relx = (float) i / (float) (segments - 1);
				for (int k = 0; k < steps; k++)
				{
					rely = (float) k / (float) steps;
					tempvertex = new warp_Vertex(circle[k].transform(frenetmatrix));
					tempvertex.u = relx;
					tempvertex.v = rely;
					newObject.addVertex(tempvertex);
				}
			}

			for (int i = 0; i < segments - 1; i++)
			{
				for (int k = 0; k < steps - 1; k++)
				{
					a = i * steps + k;
					b = a + 1;
					c = a + steps;
					d = b + steps;
					newObject.addTriangle(a, c, b);
					newObject.addTriangle(b, c, d);
				}
				a = (i + 1) * steps - 1;
				b = a + 1 - steps;
				c = a + steps;
				d = b + steps;
				newObject.addTriangle(a, c, b);
				newObject.addTriangle(b, c, d);
			}

			return newObject;
		}
Пример #17
0
		public static warp_Object ROTATIONOBJECT(warp_Vector[] path, int sides)
		{
			int steps = sides + 1;
			warp_Object newObject = new warp_Object();
			double alpha = 2 * pi / ( (double) steps - 1);
			float qx, qz;
			int nodes = path.GetLength(0);
			warp_Vertex vertex = null;
			float u, v; // Texture coordinates

			for (int j = 0; j < steps; j++)
			{
				u = (float) (steps - j - 1) / (float) (steps - 1);
				for (int i = 0; i < nodes; i++)
				{
					v = (float) i / (float) (nodes - 1);
					qx = (float) (path[i].x * Math.Cos(j * alpha) +
						path[i].z * Math.Sin(j * alpha));
					qz = (float) (path[i].z * Math.Cos(j * alpha) -
						path[i].x * Math.Sin(j * alpha));
					vertex = new warp_Vertex(qx, path[i].y, qz);
					vertex.u = u;
					vertex.v = v;
					newObject.addVertex(vertex);
				}
			}

			for (int j = 0; j < steps - 1; j++)
			{
				for (int i = 0; i < nodes - 1; i++)
				{
					newObject.addTriangle(i + nodes * j, i + nodes * (j + 1),
						i + 1 + nodes * j);
					newObject.addTriangle(i + nodes * (j + 1),
						i + 1 + nodes * (j + 1),
						i + 1 + nodes * j);

				}
			}

			for (int i = 0; i < nodes - 1; i++)
			{
				newObject.addTriangle(i + nodes * (steps - 1), i,
					i + 1 + nodes * (steps - 1));
				newObject.addTriangle(i, i + 1, i + 1 + nodes * (steps - 1));
			}
			return newObject;

		}
        private void readNextJunk(string name, BinaryReader inStream)
        {
            readJunkHeader(inStream);

            if (currentJunkId == 0x3D3D /* mesh block */)
            {
                return;
            }

            if (currentJunkId == 0x4000 /* object block */)
            {
                currentObjectName = readString(inStream);
                return;
            }

            if (currentJunkId == 0x4100 /* triangular polygon object */)
            {
                currentObject = new warp_Object();
                _objects.Add( name+"_"+currentObjectName, currentObject );

                return;
            }

            if (currentJunkId == 0x4110 /* vertex list */)
            {
                readVertexList(inStream);
                return;
            }

            if (currentJunkId == 0x4120 /* point list */)
            {
                readPointList(inStream);
                return;
            }

            if (currentJunkId == 0x4140 /* mapping coordinates */)
            {
                readMappingCoordinates(inStream);
                return;
            }

            skipJunk(inStream);
        }
Пример #19
0
		public warp_Object getClone()
		{
			warp_Object obj=new warp_Object();
			rebuild();
			for(int i=0;i<vertices;i++) obj.addVertex(fastvertex[i].getClone());
			for(int i=0;i<triangles;i++) obj.addTriangle(fasttriangle[i].getClone());
			obj.name=name+" [cloned]";
			obj.material=material;
			obj.matrix=matrix.getClone();
			obj.normalmatrix=normalmatrix.getClone();
			obj.rebuild();
			return obj;
		}
Пример #20
0
        public static warp_Object TUBE(warp_Vector[] path, float r, int steps, bool closed)
        {
            warp_Vector[] circle = new warp_Vector[steps];
            float         angle;

            for (int i = 0; i < steps; i++)
            {
                angle     = 2 * 3.14159265f * (float)i / (float)steps;
                circle[i] = new warp_Vector(r * warp_Math.cos(angle),
                                            r * warp_Math.sin(angle), 0f);
            }

            warp_Object newObject = new warp_Object();
            int         segments = path.GetLength(0);
            warp_Vector forward, up, right;
            warp_Matrix frenetmatrix;
            warp_Vertex tempvertex;
            float       relx, rely;
            int         a, b, c, d;

            for (int i = 0; i < segments; i++)
            {
                // Calculate frenet frame matrix

                if (i != segments - 1)
                {
                    forward = warp_Vector.sub(path[i + 1], path[i]);
                }
                else
                {
                    if (!closed)
                    {
                        forward = warp_Vector.sub(path[i], path[i - 1]);
                    }
                    else
                    {
                        forward = warp_Vector.sub(path[1], path[0]);
                    }
                }

                forward.normalize();
                up           = new warp_Vector(0f, 0f, 1f);
                right        = warp_Vector.getNormal(forward, up);
                up           = warp_Vector.getNormal(forward, right);
                frenetmatrix = new warp_Matrix(right, up, forward);
                frenetmatrix.shift(path[i].x, path[i].y, path[i].z);

                // Add nodes

                relx = (float)i / (float)(segments - 1);
                for (int k = 0; k < steps; k++)
                {
                    rely         = (float)k / (float)steps;
                    tempvertex   = new warp_Vertex(circle[k].transform(frenetmatrix));
                    tempvertex.u = relx;
                    tempvertex.v = rely;
                    newObject.addVertex(tempvertex);
                }
            }

            for (int i = 0; i < segments - 1; i++)
            {
                for (int k = 0; k < steps - 1; k++)
                {
                    a = i * steps + k;
                    b = a + 1;
                    c = a + steps;
                    d = b + steps;
                    newObject.addTriangle(a, c, b);
                    newObject.addTriangle(b, c, d);
                }
                a = (i + 1) * steps - 1;
                b = a + 1 - steps;
                c = a + steps;
                d = b + steps;
                newObject.addTriangle(a, c, b);
                newObject.addTriangle(b, c, d);
            }

            return(newObject);
        }
Пример #21
0
        private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim,
                bool useTextures)
        {
            const float MIN_SIZE = 2f;

            if ((PCode)prim.Shape.PCode != PCode.Prim)
                return;
            if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE)
                return;

            FacetedMesh renderMesh = null;
            Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset);

            if (m_renderMeshes)
            {
                if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero)
                {
                    // Try fetchinng the asset
                    byte[] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
                    if (sculptAsset != null)
                    {
                        // Is it a mesh?
                        if (omvPrim.Sculpt.Type == SculptType.Mesh)
                        {
                            AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
                            FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh);
                            meshAsset = null;
                        }
                        else // It's sculptie
                        {
                            IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>();
                            if (imgDecoder != null)
                            {
                                Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
                                if (sculpt != null)
                                {
                                    renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt,
                                                                                        DetailLevel.Medium);
                                    sculpt.Dispose();
                                }
                            }
                        }
                    }
                }
            }

            // If not a mesh or sculptie, try the regular mesher
            if (renderMesh == null)
            {
                renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium);
            }

            if (renderMesh == null)
                return;

            warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
            warp_Quaternion primRot = ConvertQuaternion(prim.RotationOffset);

            warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);

            if (prim.ParentID != 0)
            {
                SceneObjectGroup group = m_scene.SceneGraph.GetGroupByPrim(prim.LocalId);
                if (group != null)
                    m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootPart.RotationOffset)));
            }

            warp_Vector primScale = ConvertVector(prim.Scale);

            string primID = prim.UUID.ToString();

            // Create the prim faces
            // TODO: Implement the useTextures flag behavior
            for (int i = 0; i < renderMesh.Faces.Count; i++)
            {
                Face face = renderMesh.Faces[i];
                string meshName = primID + "-Face-" + i.ToString();

                // Avoid adding duplicate meshes to the scene
                if (renderer.Scene.objectData.ContainsKey(meshName))
                {
                    continue;
                }

                warp_Object faceObj = new warp_Object(face.Vertices.Count, face.Indices.Count / 3);

                for (int j = 0; j < face.Vertices.Count; j++)
                {
                    Vertex v = face.Vertices[j];

                    warp_Vector pos = ConvertVector(v.Position);
                    warp_Vector norm = ConvertVector(v.Normal);
                    
                    if (prim.Shape.SculptTexture == UUID.Zero)
                        norm = norm.reverse();
                    warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y);

                    faceObj.addVertex(vert);
                }

                for (int j = 0; j < face.Indices.Count; j += 3)
                {
                    faceObj.addTriangle(
                        face.Indices[j + 0],
                        face.Indices[j + 1],
                        face.Indices[j + 2]);
                }

                Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
                Color4 faceColor = GetFaceColor(teFace);
                string materialName = String.Empty;
                if (m_texturePrims && prim.Scale.LengthSquared() > m_texturePrimSize*m_texturePrimSize)
                    materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
                else
                    materialName = GetOrCreateMaterial(renderer, faceColor);

                faceObj.transform(m);
                faceObj.setPos(primPos);
                faceObj.scaleSelf(primScale.x, primScale.y, primScale.z);

                renderer.Scene.addObject(meshName, faceObj);

                renderer.SetObjectMaterial(meshName, materialName);
            }
        }
Пример #22
0
        private void CreatePrim(WarpRenderer renderer, ISceneChildEntity prim)
        {
            try
            {
                const float MIN_SIZE = 2f;

                if ((PCode) prim.Shape.PCode != PCode.Prim)
                    return;
                if (prim.Scale.LengthSquared() < MIN_SIZE*MIN_SIZE)
                    return;

                Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.GetRotationOffset());
                FacetedMesh renderMesh = null;

                // Are we dealing with a sculptie or mesh?
                if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero)
                {
                    // Try fetchinng the asset
                    byte[] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
                    if (sculptAsset != null)
                    {
                        // Is it a mesh?
                        if (omvPrim.Sculpt.Type == SculptType.Mesh)
                        {
                            AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
                            FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh);
                            meshAsset = null;
                        }
                        else // It's sculptie
                        {
                            Image sculpt = m_imgDecoder.DecodeToImage(sculptAsset);
                            if (sculpt != null)
                            {
                                renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap) sculpt,
                                                                                    DetailLevel.Medium);
                                sculpt.Dispose();
                            }
                        }
                    }
                }
                else // Prim
                {
                    renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium);
                }

                if (renderMesh == null)
                    return;

                warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
                warp_Quaternion primRot = ConvertQuaternion(prim.GetRotationOffset());

                warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);

                if (prim.ParentID != 0)
                {
                    ISceneEntity group = m_scene.GetGroupByPrim(prim.LocalId);
                    if (group != null)
                        m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootChild.GetRotationOffset())));
                }

                warp_Vector primScale = ConvertVector(prim.Scale);

                string primID = prim.UUID.ToString();

                // Create the prim faces
                for (int i = 0; i < renderMesh.Faces.Count; i++)
                {
                    Face face = renderMesh.Faces[i];
                    string meshName = primID + "-Face-" + i.ToString();

                    warp_Object faceObj = new warp_Object(face.Vertices.Count, face.Indices.Count/3);

                    foreach (Vertex v in face.Vertices)
                    {
                        warp_Vector pos = ConvertVector(v.Position);
                        warp_Vector norm = ConvertVector(v.Normal);

                        if (prim.Shape.SculptTexture == UUID.Zero)
                            norm = norm.reverse();
                        warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y);

                        faceObj.addVertex(vert);
                    }

                    for (int j = 0; j < face.Indices.Count;)
                    {
                        faceObj.addTriangle(
                            face.Indices[j++],
                            face.Indices[j++],
                            face.Indices[j++]);
                    }

                    Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint) i);
                    string materialName;
                    Color4 faceColor = GetFaceColor(teFace);

                    if (m_texturePrims && prim.Scale.LengthSquared() > 48*48)
                    {
                        materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
                    }
                    else
                    {
                        materialName = GetOrCreateMaterial(renderer, faceColor);
                    }

                    faceObj.transform(m);
                    faceObj.setPos(primPos);
                    faceObj.scaleSelf(primScale.x, primScale.y, primScale.z);

                    renderer.Scene.addObject(meshName, faceObj);

                    renderer.SetObjectMaterial(meshName, materialName);
                }
                renderMesh.Faces.Clear();
                renderMesh = null;
            }
            catch (Exception ex)
            {
                MainConsole.Instance.Warn("[Warp3D]: Exception creating prim, " + ex);
            }
        }
Пример #23
0
        private warp_Object CreateTerrain(WarpRenderer renderer, bool textureTerrain)
        {
            ITerrainChannel terrain = m_scene.RequestModuleInterface<ITerrainChannel>();

            float diff = (float) m_scene.RegionInfo.RegionSizeY/(float) Constants.RegionSize;
            warp_Object obj =
                new warp_Object(Constants.RegionSize*Constants.RegionSize,
                                ((Constants.RegionSize - 1)*(Constants.RegionSize - 1)*2));

            for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
            {
                for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
                {
                    warp_Vector pos = ConvertVector(x, y, terrain[(int) x, (int) y]);
                    obj.addVertex(new warp_Vertex(pos, x/(float) (m_scene.RegionInfo.RegionSizeX),
                                                  (((float) m_scene.RegionInfo.RegionSizeX) - y)/
                                                  (m_scene.RegionInfo.RegionSizeX)));
                }
            }

            for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
            {
                for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
                {
                    float newX = x/diff;
                    float newY = y/diff;
                    if (newX < Constants.RegionSize - 1 && newY < Constants.RegionSize - 1)
                    {
                        int v = (int) (newY*Constants.RegionSize + newX);

                        // Normal
                        Vector3 v1 = new Vector3(newX, newY, (terrain[(int) x, (int) y])/Constants.TerrainCompression);
                        Vector3 v2 = new Vector3(newX + 1, newY,
                                                 (terrain[(int) x + 1, (int) y])/Constants.TerrainCompression);
                        Vector3 v3 = new Vector3(newX, newY + 1,
                                                 (terrain[(int) x, (int) (y + 1)])/Constants.TerrainCompression);
                        warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
                        norm = norm.reverse();
                        obj.vertex(v).n = norm;

                        // Triangle 1
                        obj.addTriangle(
                            v,
                            v + 1,
                            v + Constants.RegionSize);

                        // Triangle 2
                        obj.addTriangle(
                            v + Constants.RegionSize + 1,
                            v + Constants.RegionSize,
                            v + 1);
                    }
                }
            }

            renderer.Scene.addObject("Terrain", obj);

            UUID[] textureIDs = new UUID[4];
            float[] startHeights = new float[4];
            float[] heightRanges = new float[4];

            RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;

            textureIDs[0] = regionInfo.TerrainTexture1;
            textureIDs[1] = regionInfo.TerrainTexture2;
            textureIDs[2] = regionInfo.TerrainTexture3;
            textureIDs[3] = regionInfo.TerrainTexture4;

            startHeights[0] = (float) regionInfo.Elevation1SW;
            startHeights[1] = (float) regionInfo.Elevation1NW;
            startHeights[2] = (float) regionInfo.Elevation1SE;
            startHeights[3] = (float) regionInfo.Elevation1NE;

            heightRanges[0] = (float) regionInfo.Elevation2SW;
            heightRanges[1] = (float) regionInfo.Elevation2NW;
            heightRanges[2] = (float) regionInfo.Elevation2SE;
            heightRanges[3] = (float) regionInfo.Elevation2NE;

            uint globalX, globalY;
            Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);

            Bitmap image = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges,
                                              new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain);
            warp_Texture texture = new warp_Texture(image);
            warp_Material material = new warp_Material(texture);
            material.setReflectivity(0); // reduces tile seams a bit thanks lkalif
            renderer.Scene.addMaterial("TerrainColor", material);
            renderer.SetObjectMaterial("Terrain", "TerrainColor");
            return obj;
        }
Пример #24
0
        // Add a terrain to the renderer.
        // Note that we create a 'low resolution' 256x256 vertex terrain rather than trying for
        //    full resolution. This saves a lot of memory especially for very large regions.
        private void CreateTerrain(WarpRenderer renderer, bool textureTerrain)
        {
            ITerrainChannel terrain = m_scene.Heightmap;

            // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
            float diff = (float)m_scene.RegionInfo.RegionSizeX / 256f;

            warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2);

            // Create all the vertices for the terrain
            for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
            {
                for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
                {
                    warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]);
                    obj.addVertex(new warp_Vertex(pos,
                        x / (float)m_scene.RegionInfo.RegionSizeX,
                        (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY));
                }
            }

            // Now that we have all the vertices, make another pass and create
            //     the normals for each of the surface triangles and
            //     create the list of triangle indices.
            for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
            {
                for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
                {
                    float newX = x / diff;
                    float newY = y / diff;
                    if (newX < 255 && newY < 255)
                    {
                        int v = (int)newY * 256 + (int)newX;

                        // Normal for a triangle made up of three adjacent vertices
                        Vector3 v1 = new Vector3(newX, newY, (float)terrain[(int)x, (int)y]);
                        Vector3 v2 = new Vector3(newX + 1, newY, (float)terrain[(int)(x + 1), (int)y]);
                        Vector3 v3 = new Vector3(newX, newY + 1, (float)terrain[(int)x, ((int)(y + 1))]);
                        warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
                        norm = norm.reverse();
                        obj.vertex(v).n = norm;

                        // Make two triangles for each of the squares in the grid of vertices
                        obj.addTriangle(
                            v,
                            v + 1,
                            v + 256);

                        obj.addTriangle(
                            v + 256 + 1,
                            v + 256,
                            v + 1);
                    }
                }
            }

            renderer.Scene.addObject("Terrain", obj);

            UUID[] textureIDs = new UUID[4];
            float[] startHeights = new float[4];
            float[] heightRanges = new float[4];

            OpenSim.Framework.RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;

            textureIDs[0] = regionInfo.TerrainTexture1;
            textureIDs[1] = regionInfo.TerrainTexture2;
            textureIDs[2] = regionInfo.TerrainTexture3;
            textureIDs[3] = regionInfo.TerrainTexture4;

            startHeights[0] = (float)regionInfo.Elevation1SW;
            startHeights[1] = (float)regionInfo.Elevation1NW;
            startHeights[2] = (float)regionInfo.Elevation1SE;
            startHeights[3] = (float)regionInfo.Elevation1NE;

            heightRanges[0] = (float)regionInfo.Elevation2SW;
            heightRanges[1] = (float)regionInfo.Elevation2NW;
            heightRanges[2] = (float)regionInfo.Elevation2SE;
            heightRanges[3] = (float)regionInfo.Elevation2NE;

            uint globalX, globalY;
            Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);

            warp_Texture texture;
            using (
                Bitmap image
                    = TerrainSplat.Splat(
                        terrain, textureIDs, startHeights, heightRanges,
                        new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
            {
                texture = new warp_Texture(image);
            }

            warp_Material material = new warp_Material(texture);
            material.setReflectivity(50);
            renderer.Scene.addMaterial("TerrainColor", material);
			renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif
            renderer.SetObjectMaterial("Terrain", "TerrainColor");
        }
Пример #25
0
        private void CreateTerrain(WarpRenderer renderer, bool textureTerrain)
        {
            ITerrainChannel terrain = m_scene.RequestModuleInterface<ITerrainChannel>();

            warp_Object obj = new warp_Object (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY, (m_scene.RegionInfo.RegionSizeX - 1) * (m_scene.RegionInfo.RegionSizeY - 1) * 2);

            for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y++)
            {
                for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x++)
                {
                    float height = terrain[x, y];

                    warp_Vector pos = ConvertVector(new Vector3(x, y, height));
                    obj.addVertex (new warp_Vertex (pos, (float)x / (m_scene.RegionInfo.RegionSizeX - 1), (float)((m_scene.RegionInfo.RegionSizeX - 1) - y) / (m_scene.RegionInfo.RegionSizeX - 1)));
                }
            }

            for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += 1)
            {
                for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += 1)
                {
                    if (x < m_scene.RegionInfo.RegionSizeX - 1 && y < m_scene.RegionInfo.RegionSizeY - 1)
                    {
                        float v = y * m_scene.RegionInfo.RegionSizeX + x;

                        // Normal
                        warp_Vector norm = new warp_Vector(x, y, terrain.GetNormalizedGroundHeight((int)x, (int)y));
                        norm = norm.reverse();
                        obj.vertex ((int)v).n = norm;

                        // Triangle 1
                        obj.addTriangle(
                            (int)v,
                            (int)v + 1,
                            (int)v + m_scene.RegionInfo.RegionSizeX);

                        // Triangle 2
                        obj.addTriangle(
                            (int)v + m_scene.RegionInfo.RegionSizeX + 1,
                            (int)v + m_scene.RegionInfo.RegionSizeX,
                            (int)v + 1);
                    }
                }
            }

            renderer.Scene.addObject("Terrain", obj);

            UUID[] textureIDs = new UUID[4];
            float[] startHeights = new float[4];
            float[] heightRanges = new float[4];

            RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;

            textureIDs[0] = regionInfo.TerrainTexture1;
            textureIDs[1] = regionInfo.TerrainTexture2;
            textureIDs[2] = regionInfo.TerrainTexture3;
            textureIDs[3] = regionInfo.TerrainTexture4;

            startHeights[0] = (float)regionInfo.Elevation1SW;
            startHeights[1] = (float)regionInfo.Elevation1NW;
            startHeights[2] = (float)regionInfo.Elevation1SE;
            startHeights[3] = (float)regionInfo.Elevation1NE;

            heightRanges[0] = (float)regionInfo.Elevation2SW;
            heightRanges[1] = (float)regionInfo.Elevation2NW;
            heightRanges[2] = (float)regionInfo.Elevation2SE;
            heightRanges[3] = (float)regionInfo.Elevation2NE;

            uint globalX, globalY;
            Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);

            Bitmap image = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges, new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain);
            warp_Texture texture = new warp_Texture(image);
            warp_Material material = new warp_Material(texture);
            material.setReflectivity(50);
            renderer.Scene.addMaterial("TerrainColor", material);
            renderer.SetObjectMaterial("Terrain", "TerrainColor");
        }
Пример #26
0
        private void CreatePrim(WarpRenderer renderer, LLPrimitive prim, IPrimMesher primMesher)
        {
            const float MIN_SIZE = 2f;

            if (prim.Prim.PrimData.PCode != PCode.Prim)
                return;
            if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE)
                return;

            RenderingMesh renderMesh;
            DetailLevel lod = DetailLevel.Medium;

            renderMesh = primMesher.GetRenderingMesh(prim, lod);

            if (renderMesh == null)
                return;

            warp_Vector primPos = ConvertVector(prim.ScenePosition);
            warp_Quaternion primRot = ConvertQuaternion(prim.RelativeRotation);

            warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);

            if (prim.Parent != null)
                m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(prim.Parent.RelativeRotation)));

            warp_Vector primScale = ConvertVector(prim.Scale);

            string primID = prim.ID.ToString();

            // Create the prim faces
            for (int i = 0; i < renderMesh.Faces.Length; i++)
            {
                RenderingMesh.Face face = renderMesh.Faces[i];
                string meshName = primID + "-Face-" + i.ToString();

                warp_Object faceObj = new warp_Object(face.Vertices.Length, face.Indices.Length / 3);

                for (int j = 0; j < face.Vertices.Length; j++)
                {
                    Vertex v = face.Vertices[j];

                    warp_Vector pos = ConvertVector(v.Position);
                    warp_Vector norm = ConvertVector(v.Normal);
                    if (prim.Prim.Sculpt == null || prim.Prim.Sculpt.SculptTexture == UUID.Zero)
                        norm = norm.reverse();
                    warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y);

                    faceObj.addVertex(vert);
                }

                for (int j = 0; j < face.Indices.Length; j += 3)
                {
                    faceObj.addTriangle(
                        face.Indices[j + 0],
                        face.Indices[j + 1],
                        face.Indices[j + 2]);
                }

                Primitive.TextureEntryFace teFace = prim.Prim.Textures.GetFace((uint)i);
                Color4 faceColor = GetFaceColor(teFace);
                string materialName = GetOrCreateMaterial(renderer, faceColor);

                faceObj.transform(m);
                faceObj.setPos(primPos);
                faceObj.scaleSelf(primScale.x, primScale.y, primScale.z);

                renderer.Scene.addObject(meshName, faceObj);

                renderer.SetObjectMaterial(meshName, materialName);
            }
        }
Пример #27
0
        private void CreateTerrain(WarpRenderer renderer, bool textureTerrain)
        {
            ITerrainChannel terrain = m_scene.Heightmap;
            float[] heightmap = terrain.GetFloatsSerialised();

            warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2);

            for (int y = 0; y < 256; y++)
            {
                for (int x = 0; x < 256; x++)
                {
                    int v = y * 256 + x;
                    float height = heightmap[v];

                    warp_Vector pos = ConvertVector(new Vector3(x, y, height));
                    obj.addVertex(new warp_Vertex(pos, (float)x / 255f, (float)(255 - y) / 255f));
                }
            }

            for (int y = 0; y < 256; y++)
            {
                for (int x = 0; x < 256; x++)
                {
                    if (x < 255 && y < 255)
                    {
                        int v = y * 256 + x;

                        // Normal
                        Vector3 v1 = new Vector3(x, y, heightmap[y * 256 + x]);
                        Vector3 v2 = new Vector3(x + 1, y, heightmap[y * 256 + x + 1]);
                        Vector3 v3 = new Vector3(x, y + 1, heightmap[(y + 1) * 256 + x]);
                        warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
                        norm = norm.reverse();
                        obj.vertex(v).n = norm;

                        // Triangle 1
                        obj.addTriangle(
                            v,
                            v + 1,
                            v + 256);

                        // Triangle 2
                        obj.addTriangle(
                            v + 256 + 1,
                            v + 256,
                            v + 1);
                    }
                }
            }

            renderer.Scene.addObject("Terrain", obj);

            UUID[] textureIDs = new UUID[4];
            float[] startHeights = new float[4];
            float[] heightRanges = new float[4];

            RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;

            textureIDs[0] = regionInfo.TerrainTexture1;
            textureIDs[1] = regionInfo.TerrainTexture2;
            textureIDs[2] = regionInfo.TerrainTexture3;
            textureIDs[3] = regionInfo.TerrainTexture4;

            startHeights[0] = (float)regionInfo.Elevation1SW;
            startHeights[1] = (float)regionInfo.Elevation1NW;
            startHeights[2] = (float)regionInfo.Elevation1SE;
            startHeights[3] = (float)regionInfo.Elevation1NE;

            heightRanges[0] = (float)regionInfo.Elevation2SW;
            heightRanges[1] = (float)regionInfo.Elevation2NW;
            heightRanges[2] = (float)regionInfo.Elevation2SE;
            heightRanges[3] = (float)regionInfo.Elevation2NE;

            uint globalX, globalY;
            Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);

            Bitmap image = TerrainSplat.Splat(heightmap, textureIDs, startHeights, heightRanges, new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain);
            warp_Texture texture = new warp_Texture(image);
            warp_Material material = new warp_Material(texture);
            material.setReflectivity(50);
            renderer.Scene.addMaterial("TerrainColor", material);
			renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif
            renderer.SetObjectMaterial("Terrain", "TerrainColor");
        }
Пример #28
0
        private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim,
                bool useTextures)
        {
            const float MIN_SIZE = 2f;

            if ((PCode)prim.Shape.PCode != PCode.Prim)
                return;
            if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE)
                return;

            Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset);
            FacetedMesh renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium);
            if (renderMesh == null)
                return;

            warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
            warp_Quaternion primRot = ConvertQuaternion(prim.RotationOffset);

            warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);

            if (prim.ParentID != 0)
            {
                SceneObjectGroup group = m_scene.SceneGraph.GetGroupByPrim(prim.LocalId);
                if (group != null)
                    m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootPart.RotationOffset)));
            }

            warp_Vector primScale = ConvertVector(prim.Scale);

            string primID = prim.UUID.ToString();

            // Create the prim faces
            // TODO: Implement the useTextures flag behavior
            for (int i = 0; i < renderMesh.Faces.Count; i++)
            {
                Face face = renderMesh.Faces[i];
                string meshName = primID + "-Face-" + i.ToString();

                // Avoid adding duplicate meshes to the scene
                if (renderer.Scene.objectData.ContainsKey(meshName))
                {
                    continue;
                }

                warp_Object faceObj = new warp_Object(face.Vertices.Count, face.Indices.Count / 3);

                for (int j = 0; j < face.Vertices.Count; j++)
                {
                    Vertex v = face.Vertices[j];

                    warp_Vector pos = ConvertVector(v.Position);
                    warp_Vector norm = ConvertVector(v.Normal);
                    
                    if (prim.Shape.SculptTexture == UUID.Zero)
                        norm = norm.reverse();
                    warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y);

                    faceObj.addVertex(vert);
                }

                for (int j = 0; j < face.Indices.Count; j += 3)
                {
                    faceObj.addTriangle(
                        face.Indices[j + 0],
                        face.Indices[j + 1],
                        face.Indices[j + 2]);
                }

                Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
                Color4 faceColor = GetFaceColor(teFace);
                string materialName = GetOrCreateMaterial(renderer, faceColor);

                faceObj.transform(m);
                faceObj.setPos(primPos);
                faceObj.scaleSelf(primScale.x, primScale.y, primScale.z);

                renderer.Scene.addObject(meshName, faceObj);

                renderer.SetObjectMaterial(meshName, materialName);
            }
        }
Пример #29
0
        private void CreateTerrain(IScene scene, WarpRenderer renderer, ITerrain terrain, RegionInfo regionInfo)
        {
            float[] heightmap = (terrain != null) ? terrain.GetHeightmap() : new float[256 * 256];

            warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2);

            for (int y = 0; y < 256; y++)
            {
                for (int x = 0; x < 256; x++)
                {
                    int v = y * 256 + x;
                    float height = heightmap[v];

                    warp_Vector pos = ConvertVector(new Vector3(x, y, height));
                    obj.addVertex(new warp_Vertex(pos, (float)x / 255f, (float)(255 - y) / 255f));
                }
            }

            for (int y = 0; y < 256; y++)
            {
                for (int x = 0; x < 256; x++)
                {
                    if (x < 255 && y < 255)
                    {
                        int v = y * 256 + x;

                        // Normal
                        Vector3 v1 = new Vector3(x, y, heightmap[y * 256 + x]);
                        Vector3 v2 = new Vector3(x + 1, y, heightmap[y * 256 + x + 1]);
                        Vector3 v3 = new Vector3(x, y + 1, heightmap[(y + 1) * 256 + x]);
                        warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
                        norm = norm.reverse();
                        obj.vertex(v).n = norm;

                        // Triangle 1
                        obj.addTriangle(
                            v,
                            v + 1,
                            v + 256);

                        // Triangle 2
                        obj.addTriangle(
                            v + 256 + 1,
                            v + 256,
                            v + 1);
                    }
                }
            }

            renderer.Scene.addObject("Terrain", obj);

            UUID[] textureIDs = new UUID[4];
            float[] startHeights = new float[4];
            float[] heightRanges = new float[4];
            if (regionInfo != null)
            {
                textureIDs[0] = regionInfo.TerrainDetail0;
                textureIDs[1] = regionInfo.TerrainDetail1;
                textureIDs[2] = regionInfo.TerrainDetail2;
                textureIDs[3] = regionInfo.TerrainDetail3;

                startHeights[0] = regionInfo.TerrainStartHeight00;
                startHeights[1] = regionInfo.TerrainStartHeight01;
                startHeights[2] = regionInfo.TerrainStartHeight10;
                startHeights[3] = regionInfo.TerrainStartHeight11;

                heightRanges[0] = regionInfo.TerrainHeightRange00;
                heightRanges[1] = regionInfo.TerrainHeightRange01;
                heightRanges[2] = regionInfo.TerrainHeightRange10;
                heightRanges[3] = regionInfo.TerrainHeightRange11;
            }

            Bitmap image = TerrainSplat.Splat(heightmap, textureIDs, startHeights, heightRanges, scene.MinPosition, m_assetClient);
            warp_Texture texture = new warp_Texture(image);
            warp_Material material = new warp_Material(texture);
            material.setReflectivity(50);
            renderer.Scene.addMaterial("TerrainColor", material);
            renderer.SetObjectMaterial("Terrain", "TerrainColor");
        }