Terrain Code

Coordinator
Mar 30, 2010 at 1:11 PM
This code looks like it reads the record correctly. 

For 1 to resolution^2

                    Color3           luxel color

 

Does not appear to be in the record

 

/*  
 *  
 * Copyright (c) 2007 John Wells 
 * Copyright (c) 2010 Photonic Games 
 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, 
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
Software is furnished to do so, subject to the following conditions: 
 
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GameLevel.ContentPipeline.Leadwerks14
{
    public sealed class Terrain
    {
        public Byte flags;
        public Vector3 position;
        public float width;
        public float height;
        public string terrainName;
        public string[] levelNames;
        public Int32 resolution;
        public Int32 sectors;
        public Int32 detailLevels;
        public float lightmapResolution;
        public Int32 layerCount;


        public Terrain(BinaryReader reader, string[] names)
        {
            flags = reader.ReadByte();
            position = Leadwerks14Importer.ReadVector3(reader);
            width = reader.ReadSingle();
            height = reader.ReadSingle();
            //terrainName = reader.ReadString();  
            terrainName = names[reader.ReadInt32() - 1];
            resolution = reader.ReadInt32();
            sectors = reader.ReadInt32();
            detailLevels = reader.ReadInt32();
            lightmapResolution = reader.ReadSingle();
            layerCount = reader.ReadInt32();


            //for (int index = 0; index < (resolution) * (resolution); index++)
            //{
             //   Leadwerks14Importer.ReadColor(reader);
            //}

            for (int index = 0; index < (resolution + 1) * (resolution + 1); index++)
            {
                reader.ReadSingle();
            }

            levelNames = new String[layerCount];

            for (Int32 index = 0; index < layerCount; index++)
            {
                
                levelNames[index] = names[reader.ReadInt32()-1];
                reader.ReadInt32();
                if (index > 1)
                {
                    for (int index2 = 0; index < (resolution + 1) * (resolution + 1); index2++)
                    {
                        reader.ReadByte();
                    }
                }
            }
        }

    }
}


Coordinator
Mar 30, 2010 at 1:44 PM

 

Here is an updated version since the one above does not handle layers (And I can't figure out how to edit a previous post).

 

/*  
 *  
 * Copyright (c) 2007 John Wells 
 * Copyright (c) 2010 Photonic Games 
 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, 
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
Software is furnished to do so, subject to the following conditions: 
 
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GameLevel.ContentPipeline.Leadwerks14
{
    public sealed class Terrain
    {
        public class Layer
        {
            public String layerName;
            public int material;
            public byte[] alpha;
        }

        public Byte flags;
        public Vector3 position;
        public float width;
        public float height;
        public string terrainName;
        public Int32 resolution;
        public Int32 sectors;
        public Int32 detailLevels;
        public float lightmapResolution;
        public Int32 layerCount;

        public Layer[] layers;
        public float[] heightMap;

        public Terrain(BinaryReader reader, string[] names)
        {
            
            flags = reader.ReadByte();
            position = Leadwerks14Importer.ReadVector3(reader);
            width = reader.ReadSingle();
            height = reader.ReadSingle();
            //terrainName = reader.ReadString();  
            terrainName = names[reader.ReadInt32() - 1];
            resolution = reader.ReadInt32();
            sectors = reader.ReadInt32();
            detailLevels = reader.ReadInt32();
            lightmapResolution = reader.ReadSingle();
            layerCount = reader.ReadInt32();


            //for (int index = 0; index < (resolution) * (resolution); index++)
            //{
             //   Leadwerks14Importer.ReadColor(reader);
            //}

            heightMap = new float[(resolution + 1) * (resolution + 1)];

            for (int index = 0; index < (resolution + 1) * (resolution + 1); index++)
            {
                heightMap[index] = reader.ReadSingle();
            }

            layers = new Layer[layerCount];

            for (Int32 index = 0; index < layerCount; index++)
            {
                layers[index] = new Layer();
                layers[index].layerName = names[reader.ReadInt32()-1];
                layers[index].material = reader.ReadInt32();

                layers[index].alpha = new Byte[resolution * resolution];

                if (index > 1)
                {
                    for (int index2 = 0; index2 < (resolution) * (resolution); index2++)
                    {
                        layers[index].alpha[index2] = reader.ReadByte();
                    }
                }


                // Have no idea what this is ......
                if (index == 1)
                {
                    for (int index2 = 0; index2 < (resolution) * (resolution); index2++)
                    {
                        reader.ReadByte();
                    }
                }
            }
        }
    }
}


Mar 31, 2010 at 3:46 AM
Edited Mar 31, 2010 at 3:56 AM

Alright, so where gonna migrate this dicussion over to here. Alright first of all, the fixed the lightmap issues

 

Updated code to support lightmap reading:

 

/*  
 *  
 * Copyright (c) 2007 John Wells 
 * Copyright (c) 2010 Photonic Games 
 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, 
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
Software is furnished to do so, subject to the following conditions: 
 
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GameLevel.ContentPipeline.Leadwerks14
{
    public sealed class Terrain
    {
        public class Layer
        {
            public String layerName;
            public int material;
            public byte[] alpha;
        }

        public Byte flags;
        public Vector3 position;
        public float width;
        public float height;
        public string terrainName;
        public Int32 resolution;
        public Int32 sectors;
        public Int32 detailLevels;
        public float lightmapResolution;
        public Int32 layerCount;

        public Layer[] layers;
        public float[] heightMap;

        public Terrain(BinaryReader reader, string[] names)
        {

            flags = reader.ReadByte();
            position = Leadwerks14Importer.ReadVector3(reader);
            width = reader.ReadSingle();
            height = reader.ReadSingle();
            //terrainName = reader.ReadString();  
            terrainName = names[reader.ReadInt32() - 1];
            resolution = reader.ReadInt32();
            sectors = reader.ReadInt32();
            detailLevels = reader.ReadInt32();
            lightmapResolution = reader.ReadSingle();
            layerCount = reader.ReadInt32();


            //for (int index = 0; index < (resolution) * (resolution); index++)
            //{
            //   Leadwerks14Importer.ReadColor(reader);
            //}

            if (flags > 0)
            {
                for (int index = 0; index < (resolution) * (resolution); index++)
                {
                    Leadwerks14Importer.ReadColor(reader);
                }
            }

            heightMap = new float[(resolution + 1) * (resolution + 1)];

            for (int index = 0; index < (resolution + 1) * (resolution + 1); index++)
            {
                heightMap[index] = reader.ReadSingle();
            }

            layers = new Layer[layerCount];

            for (Int32 index = 0; index < layerCount; index++)
            {
                layers[index] = new Layer();
                layers[index].layerName = names[reader.ReadInt32() - 1];
                layers[index].material = reader.ReadInt32();

                layers[index].alpha = new Byte[resolution * resolution];

                if (index > 1)
                {
                    for (int index2 = 0; index2 < (resolution) * (resolution); index2++)
                    {
                        layers[index].alpha[index2] = reader.ReadByte();
                    }
                }


                // Have no idea what this is ......
                if (index == 1)
                {
                    for (int index2 = 0; index2 < (resolution) * (resolution); index2++)
                    {
                        reader.ReadByte();
                    }
                }
            }
        }
    }
}

 

Alright, the next part to accomplish is the writing part. Im not really sure how to go about this, and could use some help. The first thing i did was create a new class in the Serialization folder under the contentpipeline project called TerrainWriter.cs.

 

Code in it:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;

using GameLevel;
using GameLevel.Serialization;

namespace GameLevel.ContentPipeline.Serialization
{
    [ContentTypeWriter]
    internal sealed class TerrainWriter : /*Not sure what i put here*/ContentTypeWriter<GameLevel.ContentPipeline.Leadwerks14.Terrain>
    {
        protected override void Write(ContentWriter output, GameLevel.ContentPipeline.Leadwerks14.Terrain value)
        {
/*Not sure about this*/
            output.Write(value.flags);
            output.Write(value.position);
            output.Write(value.width);
            output.Write(value.height);
            output.Write(value.terrainName);
            output.Write(value.resolution);
            output.Write(value.sectors);
            output.Write(value.detailLevels);
            output.Write(value.lightmapResolution);
            output.Write(value.layerCount);
        }

        public override string GetRuntimeReader(TargetPlatform targetPlatform)
        {
/* Dont know what goes here either */
            throw new NotImplementedException();
        }

    }
}

Also for this part
internal sealed class TerrainWriter : /*Not sure what i put here*/ContentTypeWriter<GameLevel.ContentPipeline.Leadwerks14.Terrain>

Should i create a new class under the game level project, and put that classname in the <>? Or just use the class under leakwerks14(AKA the file reader class, the one above in the first and second post)


Hope you can help me with this, and get writing finished!

 

Coordinator
Mar 31, 2010 at 12:22 PM

You don't want to write out exactly what was read. Look at the heightmap sample and see how it converts the heghtmap to a model and then writes that out. This is what I do for the brushes too.

 

Also you need to convert the lightmap and alpha layers to textures before writing them out. Then it is just a matter of reading the models and textures and  drawing them in the game code.

Mar 31, 2010 at 3:41 PM
Edited Apr 2, 2010 at 3:25 AM

Ohh ok i see. So basically i want to use the data i read, to construct heightmap data using a heightmap processor, then right that data to the file(terrain model). Then in the Gamelevel project i should read that data and load the terrain model?

Also ive been looking everywhere, and cant seem to find the heightmap sample that you are talking about? Could you please link me or tell me where to find it?

Is this the one? http://creators.xna.com/en-us/sample/collision3dheightmap

Or http://creators.xna.com/en-US/sample/generatedgeometry

Also exactly where in the code, is the .XNB file created?

Lastly where should i add the method that processes the terrain and builds it.

Thanks in advance!

EDIT:

Ok i went ahead and tried to make my own code. I used a meshbuilder... im not sure if you are supposed for this case, but i just pretty much copied the code from the heightmap processor project.

 

private void BuildTerrain()
{
if(this._content.Terrains.Count != 0)
{
foreach(Terrain terrain in this._content.Terrains)
{
MeshBuilder builder = MeshBuilder.StartMesh("terrain");

for (int y = 0; y < terrain.height; y++)
{
for (int x = 0; x < terrain.width; x++)
{
Vector3 position;

position.X = (x - terrain.width / 2);
position.Y = 0; //DONT KNOW WHAT GOES HERE... Heightmap processor has...position.Y = (heightfield.GetPixel(x, y) - 1) ;
position.Z = (y - terrain.height / 2);

builder.CreatePosition(position);
}
}

//TODO: Add materials here
int texCoordId = builder.CreateVertexChannel<Vector2>(VertexChannelNames.TextureCoordinate(0));

for (int y = 0; y < terrain.height - 1; y++)
{
for (int x = 0; x < terrain.width - 1; x++)
{
AddVertex(builder, texCoordId, (int)terrain.width, x, y);
AddVertex(builder, texCoordId, (int)terrain.width, x + 1, y);
AddVertex(builder, texCoordId, (int)terrain.width, x + 1, y + 1);

AddVertex(builder, texCoordId, (int)terrain.width, x, y);
AddVertex(builder, texCoordId, (int)terrain.width, x + 1, y + 1);
AddVertex(builder, texCoordId, (int)terrain.width, x, y + 1);

}

}

MeshContent terrainMesh = builder.FinishMesh();
ModelContent model = _context.Convert<MeshContent, ModelContent>(terrainMesh, "ModelProcessor");
}
}

}

static void AddVertex(MeshBuilder builder, int texCoordId, int w, int x, int y)
{
builder.SetVertexChannelData(texCoordId, new Vector2(x, y));

builder.AddTriangleVertex(x + y * w);
}

 

I added this at the end of Leadwerks14LevelProcessor. Then after that, i added a call for the method, in the same file up at the top

 

// These calls must happen in this order to process the .3dw file
this.LoadSurfaces();
this.BuildEntities();
this.BuildModels();
this.BuildHeadNode();
this.BuildCollisonBoxes();
this.BuildTerrain();


I hit the build button, and it sat there for a long time. I then got the following error.

Error    15    Building content threw OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.Collections.Generic.List`1.set_Capacity(Int32 value)
   at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)
   at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
   at Microsoft.Xna.Framework.Content.Pipeline.Graphics.VertexContent.InsertRange(Int32 index, IEnumerable`1 positionIndexCollection)
   at Microsoft.Xna.Framework.Content.Pipeline.Graphics.VertexContent.Insert(Int32 index, Int32 positionIndex)
   at Microsoft.Xna.Framework.Content.Pipeline.Graphics.VertexContent.Add(Int32 positionIndex)
   at Microsoft.Xna.Framework.Content.Pipeline.Graphics.MeshBuilder.AddTriangleVertex(Int32 indexIntoVertexCollection)
   at GameLevel.ContentPipeline.Leadwerks14.Leadwerks14LevelProcessor.AddVertex(MeshBuilder builder, Int32 texCoordId, Int32 w, Int32 x, Int32 y) in C:\Documents and Settings\Matt\Desktop\3dws\3dws.ContentPipeline\Leadwerks14\Leadwerks14LevelProcessor.cs:line 797
   at GameLevel.ContentPipeline.Leadwerks14.Leadwerks14LevelProcessor.BuildTerrain() in C:\Documents and Settings\Matt\Desktop\3dws\3dws.ContentPipeline\Leadwerks14\Leadwerks14LevelProcessor.cs:line 780
   at GameLevel.ContentPipeline.Leadwerks14.Leadwerks14LevelProcessor.Process(Leadwerks14Content input, ContentProcessorContext context) in C:\Documents and Settings\Matt\Desktop\3dws\3dws.ContentPipeline\Leadwerks14\Leadwerks14LevelProcessor.cs:line 72
   at Microsoft.Xna.Framework.Content.Pipeline.ContentProcessor`2.Microsoft.Xna.Framework.Content.Pipeline.IContentProcessor.Process(Object input, ContentProcessorContext context)
   at Microsoft.Xna.Framework.Content.Pipeline.BuildCoordinator.BuildAssetWorker(BuildItem item)
   at Microsoft.Xna.Framework.Content.Pipeline.BuildCoordinator.BuildAsset(BuildItem item)
   at Microsoft.Xna.Framework.Content.Pipeline.BuildCoordinator.RunTheBuild()
   at Microsoft.Xna.Framework.Content.Pipeline.Tasks.BuildContent.RemoteProxy.RunTheBuild(BuildCoordinatorSettings settings, TimestampCache timestampCache, ITaskItem[] sourceAssets, String[]& outputContent, String[]& rebuiltContent, String[]& intermediates, Dictionary`2& dependencyTimestamps, KeyValuePair`2[]& warnings)    C:\Documents and Settings\Matt\Desktop\3dws\3dws.testlevel\Content\terrain.3dw    Game