It has been implemented by David Yazel first then by William Denniss (see TerrainTest1 and TerrainTest2). What more do we need ?
(Personnally I do use my own terrain code).
It has been implemented by David Yazel first then by William Denniss (see TerrainTest1 and TerrainTest2). What more do we need ?
(Personnally I do use my own terrain code).
[quote="<MagicSpark.org [ BlueSky ]>,post:1,topic:28352"]
It has been implemented by David Yazel first then by William Denniss (see TerrainTest1 and TerrainTest2). What more do we need ?
(Personnally I do use my own terrain code).
[/quote]
I haven’t use any terrain code so far. But over the time again and again people have demanded to have an understandable terrain code implementation in Xith, which is reusable. I cannot say, if we already have it. But if we do, it’s just fine.
So you use your own terrain implementation. Whould you share your code and commit it to xith?
I will take a look at the terrain code tomorrow. Blue, why did you make an own terrain implementation? Does it have any advantages over the existing one or where you just interested in making an own?
Well I repeat I don’t know exactly what you mean by terrain code. I didn’t need terrain generation and I figured out it would take me more time to understand David Yazel implementation than to roll my own.
Here are the two interesting classes (which are completely pre-alpha so don’t rant please) :
TerrainAttributes.java : serialized/deserialized to XML with XStream (http://xstream.codehaus.org/)
package org.stratagem.flavorable;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.HashMap;
import javax.vecmath.Color3f;
import javax.vecmath.Point2f;
import javax.vecmath.Point3f;
import javax.vecmath.Tuple3f;
import javax.vecmath.Vector2f;
import org.stratagem.options.Options;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.XppDriver;
/**
* TerrainAttributes are all the things which differentiates
* types of projectiles. These are loaded from XML files.
* To create an XML skeleton file, see the
* ClassCreator utility.
*/
public class TerrainAttributes {
private static final float BORDER = 5f;
private static HashMap<String, TerrainAttributes> cache = new HashMap<String, TerrainAttributes> ();
public static TerrainAttributes get(String fileName) {
if(!cache.containsKey(fileName)) {
try {
cache.put(fileName, (TerrainAttributes)(new XStream(new XppDriver()).fromXML(new FileReader("flavors/"+
Options.get().flavor+"/terrains/"+fileName))));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
return cache.get(fileName);
}
public String name = "Terrain"; // The name of the terrain
public Vector2f cellSize = new Vector2f(1f, 1f); // The size of one cell
public float[][] height = new float[5][5]; // Height map (array of lines)
// Texture files, which can be found in "flavor/textures"
public String ground = "terrain.png";
public String background = "background.png";
public int groundRepeatCount = 1; // The count the ground texture should be repeated
public Point3f sunPosition = new Point3f(5f, 5f, 20f); // The position of the sun
public Color3f sunColor = new Color3f(1f, 1f, 1f); // The color of the sun
public float fogDepth = 50f; // The depth of the fog (the distance of the camera at which you can see)
// List of sound zones (files can be found in "flavor/sounds")
public SoundZone[] soundZones = new SoundZone[]{new SoundZone(new Point2f(2f, 2f), new Point2f(8f, 3f), "mySound.ogg")};
// List of obstacles (files can be found in "flavor/models")
public Obstacle[] obstacles = new Obstacle[]{new Obstacle(new Point2f(5f, 5f), "tree.cfg")};
public float getSizeX() {
return height[0].length * cellSize.x;
}
public float getSizeY() {
return height.length * cellSize.y;
}
public float lowerLimitX() {
return BORDER;
}
public float upperLimitX() {
return getSizeX() - BORDER;
}
public float lowerLimitY() {
return BORDER;
}
public float upperLimitY() {
return getSizeY() - BORDER;
}
public void evaluateZ(Tuple3f pos) {
pos.z = getZ(pos.x, pos.y);
}
public float getZ(float x, float y) {
/*
System.out.println(x+"\t"+y + "\t : original pos");
System.out.println((x / cellSize.x)+"\t"+(y / cellSize.y)+"\t : scaled pos");
System.out.println((int)(x / cellSize.x)+"\t"+(int)(y / cellSize.y)+"\t : inted pos");
*/
return getZ((int)(x / cellSize.x), (int)(y / cellSize.y));
}
public int getDimX() {
return height[0].length;
}
public int getDimY() {
return height.length;
}
public float getZ(int x, int y) {
float z = 0f;
try {
//FIXME test value
z = height[x][y] * 3f;
} catch (ArrayIndexOutOfBoundsException e) {
}
return z;
}
}
TexturedTerrainDisplayer
package org.stratagem.gfx;
import javax.vecmath.Point3f;
import javax.vecmath.TexCoord2f;
import org.stratagem.flavorable.TerrainAttributes;
import org.stratagem.options.Options;
import org.xith3d.geometry.Sphere;
import org.xith3d.scenegraph.Transform;
import com.xith3d.loaders.texture.TextureLoader;
import com.xith3d.scenegraph.Appearance;
import com.xith3d.scenegraph.GeometryArray;
import com.xith3d.scenegraph.Group;
import com.xith3d.scenegraph.PolygonAttributes;
import com.xith3d.scenegraph.Shape3D;
import com.xith3d.scenegraph.TriangleArray;
public class TexturedTerrainDisplayer extends TerrainDisplayer {
private int repeatCount;
private Shape3D terrainShape;
private Group debugGroup;
public TexturedTerrainDisplayer(TerrainAttributes terrain, int repeatCount) {
super(terrain);
this.repeatCount = repeatCount;
terrainShape = new Shape3D();
this.addChild(terrainShape);
update();
}
@Override
public void update() {
// Convenience variables
int dimX = terrain.getDimX();
int dimY = terrain.getDimY();
float cSizeX = terrain.cellSize.x;
float cSizeY = terrain.cellSize.y;
// 6 because two triangles per cell, an dimX * dimY cell
int vertexCount = dimX * dimY * 6;
Point3f[] coords = new Point3f[vertexCount];
TexCoord2f[] texCoords = new TexCoord2f[vertexCount];
int coordIndex = 0;
int texIndex = 0;
float sizeX = dimX * cSizeX / repeatCount;
float sizeY = dimY * cSizeY / repeatCount;
for(int x = 0; x < dimX; x++) {
for(int y = 0; y < dimY; y++) {
coords[coordIndex++] = new Point3f(x * cSizeX, y * cSizeY, getZ(x, y));
coords[coordIndex++] = new Point3f((x+1) * cSizeX, y * cSizeY, getZ(x+1, y));
coords[coordIndex++] = new Point3f(x * cSizeX, (y+1) * cSizeY, getZ(x, y+1));
coords[coordIndex++] = new Point3f(x * cSizeX, (y+1) * cSizeY, getZ(x, y+1));
coords[coordIndex++] = new Point3f((x+1) * cSizeX,(y+1) * cSizeY, getZ(x+1, y+1));
coords[coordIndex++] = new Point3f((x+1) * cSizeX, y * cSizeY, getZ(x+1, y));
texCoords[texIndex++] = new TexCoord2f((x / sizeX ) * repeatCount, (y / sizeY) * repeatCount);
texCoords[texIndex++] = new TexCoord2f((x / sizeX + 1) * repeatCount, (y / sizeY) * repeatCount);
texCoords[texIndex++] = new TexCoord2f((x / sizeX ) * repeatCount, (y / sizeY + 1) * repeatCount);
texCoords[texIndex++] = new TexCoord2f((x / sizeX ) * repeatCount, (y / sizeY + 1) * repeatCount);
texCoords[texIndex++] = new TexCoord2f((x / sizeX + 1) * repeatCount, (y / sizeY + 1) * repeatCount);
texCoords[texIndex++] = new TexCoord2f((x / sizeX + 1) * repeatCount, (y / sizeY) * repeatCount);
}
}
TriangleArray geom = new TriangleArray(vertexCount, GeometryArray.COORDINATES | GeometryArray.TEXTURE_COORDINATE_2);
geom.setCoordinates(0, coords);
geom.setTextureCoordinates(0, 0, texCoords);
terrainShape.setGeometry(geom);
Appearance app = new Appearance();
app.setTexture(TextureLoader.getInstance().getTexture("flavors/"+Options.get().flavor+"/textures/"+terrain.ground));
terrainShape.setAppearance(app);
app.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0f));
if(Options.DEBUG_TERRAIN) {
if(debugGroup == null) {
debugGroup = new Group();
this.addChild(debugGroup);
} else {
debugGroup.removeAllChildren();
}
for(int x = 0; x < dimX; x++) {
for(int y = 0; y < dimY; y++) {
debugGroup.addChild(new Transform().add(new Sphere(5, 5, GeometryArray.COLOR_3, 1f))
.setTranslation(new Point3f(x * cSizeX, y * cSizeY, terrain.getZ(x * cSizeX, y * cSizeY))));
}
}
} else {
if(debugGroup != null) {
debugGroup.detach();
debugGroup.removeAllChildren();
debugGroup = null;
}
}
}
}
What really suck hard is height approximation. But I’m gonna fix it right now.
I took a quick look at the code and it seems, that David already had a lot good stuff in there, like height data abstraction, chunked LOD and (as it seems) file paging support.
So I think the best option would be to big fix and clean his version, and document it along with a getting started guide.
Yes, but i’m a bit short on CPU time (I have to handle 1000 units simultaneously) so LOD is maybe too expensive.
[quote="<MagicSpark.org [ BlueSky ]>,post:6,topic:28352"]
but i’m a bit short on CPU time
[/quote]
I am aiming for a LOD that is easy on CPU. Let’s see how good Davids code is in this respect. I wouldn’t want to write a terrain renderer from scratch, if I don’t have to.
[quote="<MagicSpark.org [ BlueSky ]>,post:6,topic:28352"]
I have to handle 1000 units simultaneously
[/quote]
That’s not so much… have you benchmarked your code yet?
[quote="<MagicSpark.org [ BlueSky ]>,post:6,topic:28352"]
I have to handle 1000 units simultaneously
[/quote]
That’s not so much… have you benchmarked your code yet?
[/quote]
It’s that much when each unit has 300 polygons and is fully animated… and you want to make your game run smooth on a low-end computer (Pentium 500Mhz, 128 RAM, Geforce 2 MX).
Bench :
Athlon XP 2200+, 512 Mo RAM PC3200, Geforce 4MX 440SE 64 Mo
The last time I ran it with 1000+ units I had a low 1-2 FPS.
BUT it’s not optimized at all :