- move TextureAtlas methods out of GeometryBatchFactory

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9044 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
nor..67 13 years ago
parent f04654ee20
commit a265e72759
  1. 4
      engine/src/test/jme3test/tools/TestTextureAtlas.java
  2. 99
      engine/src/tools/jme3tools/optimize/GeometryBatchFactory.java
  3. 124
      engine/src/tools/jme3tools/optimize/TextureAtlas.java

@ -40,7 +40,7 @@ import com.jme3.scene.Geometry;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Quad; import com.jme3.scene.shape.Quad;
import jme3tools.optimize.GeometryBatchFactory; import jme3tools.optimize.TextureAtlas;
public class TestTextureAtlas extends SimpleApplication { public class TestTextureAtlas extends SimpleApplication {
@ -69,7 +69,7 @@ public class TestTextureAtlas extends SimpleApplication {
scene.attachChild(obj4); scene.attachChild(obj4);
scene.attachChild(obj5); scene.attachChild(obj5);
Geometry geom = GeometryBatchFactory.makeAtlasBatch(scene, assetManager, 2048); Geometry geom = TextureAtlas.makeAtlasBatch(scene, assetManager, 2048);
AmbientLight al = new AmbientLight(); AmbientLight al = new AmbientLight();
rootNode.addLight(al); rootNode.addLight(al);

@ -1,7 +1,5 @@
package jme3tools.optimize; package jme3tools.optimize;
import com.jme3.asset.AssetManager;
import com.jme3.material.MatParamTexture;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Transform; import com.jme3.math.Transform;
@ -12,7 +10,6 @@ import com.jme3.scene.VertexBuffer.Format;
import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.VertexBuffer.Usage; import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.scene.mesh.IndexBuffer; import com.jme3.scene.mesh.IndexBuffer;
import com.jme3.texture.Texture;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.IntMap.Entry; import com.jme3.util.IntMap.Entry;
import java.nio.Buffer; import java.nio.Buffer;
@ -20,7 +17,6 @@ import java.nio.FloatBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.*; import java.util.*;
import java.util.logging.Logger; import java.util.logging.Logger;
import jme3tools.optimize.TextureAtlas.TextureAtlasTile;
public class GeometryBatchFactory { public class GeometryBatchFactory {
@ -74,18 +70,6 @@ public class GeometryBatchFactory {
* @param outMesh * @param outMesh
*/ */
public static void mergeGeometries(Collection<Geometry> geometries, Mesh outMesh) { public static void mergeGeometries(Collection<Geometry> geometries, Mesh outMesh) {
mergeGeometries(geometries, outMesh, null);
}
/**
* Merges all geometries in the collection into
* the output mesh. Creates a new material using the TextureAtlas.
*
* @param geometries
* @param outMesh
* @param atlas the TextureAtlas to use
*/
public static void mergeGeometries(Collection<Geometry> geometries, Mesh outMesh, TextureAtlas atlas) {
int[] compsForBuf = new int[VertexBuffer.Type.values().length]; int[] compsForBuf = new int[VertexBuffer.Type.values().length];
Format[] formatForBuf = new Format[compsForBuf.length]; Format[] formatForBuf = new Format[compsForBuf.length];
@ -201,20 +185,6 @@ public class GeometryBatchFactory {
FloatBuffer inPos = (FloatBuffer) inBuf.getData(); FloatBuffer inPos = (FloatBuffer) inBuf.getData();
FloatBuffer outPos = (FloatBuffer) outBuf.getData(); FloatBuffer outPos = (FloatBuffer) outBuf.getData();
doTransformNorms(inPos, globalVertIndex, outPos, worldMatrix); doTransformNorms(inPos, globalVertIndex, outPos, worldMatrix);
} else if (Type.TexCoord.ordinal() == bufType && atlas != null) {
Texture tex = getMaterialTexture(geom, "DiffuseMap");
if (tex == null) {
tex = getMaterialTexture(geom, "ColorMap");
}
if (tex != null) {
TextureAtlasTile tile = atlas.getAtlasTile(tex);
if (tile != null) {
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
tile.transformTextureCoords(inPos, globalVertIndex, outPos);
}
}
} else { } else {
for (int vert = 0; vert < geomVertCount; vert++) { for (int vert = 0; vert < geomVertCount; vert++) {
int curGlobalVertIndex = globalVertIndex + vert; int curGlobalVertIndex = globalVertIndex + vert;
@ -321,74 +291,7 @@ public class GeometryBatchFactory {
return retVal; return retVal;
} }
public static Geometry makeAtlasBatch(Spatial spat, AssetManager mgr, int atlasSize) { public static void gatherGeoms(Spatial scene, List<Geometry> geoms) {
List<Geometry> geometries = new ArrayList<Geometry>();
gatherGeoms(spat, geometries);
//TODO: specular etc. maps, needs to use main atlas for locations
TextureAtlas atlas = new TextureAtlas(atlasSize, atlasSize);
for (Geometry geometry : geometries) {
Texture diffuse = getMaterialTexture(geometry, "DiffuseMap");
Texture normal = getMaterialTexture(geometry, "NormalMap");
Texture specular = getMaterialTexture(geometry, "SpecularMap");
if (diffuse == null) {
diffuse = getMaterialTexture(geometry, "ColorMap");
}
if (diffuse != null && diffuse.getKey() != null) {
String keyName = diffuse.getKey().getName();
if (!atlas.addTexture(diffuse, "DiffuseMap")) {
throw new IllegalStateException("Adding diffuse texture" + keyName + "to atlas failed, atlas full.");
} else {
if (normal != null && normal.getKey() != null) {
atlas.addTexture(diffuse, "NormalMap", keyName);
}
if (specular != null && specular.getKey() != null) {
atlas.addTexture(specular, "SpecularMap", keyName);
}
}
}
}
Geometry geom = new Geometry();
Mesh mesh = new Mesh();
mergeGeometries(geometries, mesh, atlas);
mesh.updateCounts();
mesh.updateBound();
geom.setMesh(mesh);
Material mat = new Material(mgr, "Common/MatDefs/Light/Lighting.j3md");
mat.getAdditionalRenderState().setAlphaTest(true);
Texture diffuseMap = atlas.getAtlasTexture("DiffuseMap");
Texture normalMap = atlas.getAtlasTexture("NormalMap");
Texture specularMap = atlas.getAtlasTexture("SpecularMap");
if (diffuseMap != null) {
mat.setTexture("DiffuseMap", diffuseMap);
}
if (normalMap != null) {
mat.setTexture("NormalMap", normalMap);
}
if (specularMap != null) {
mat.setTexture("SpecularMap", specularMap);
}
mat.setFloat("Shininess", 16.0f);
geom.setMaterial(mat);
return geom;
}
private static Texture getMaterialTexture(Geometry geometry, String mapName) {
Material mat = geometry.getMaterial();
if (mat == null || mat.getParam(mapName) == null || !(mat.getParam(mapName) instanceof MatParamTexture)) {
return null;
}
MatParamTexture param = (MatParamTexture) mat.getParam(mapName);
Texture texture = param.getTextureValue();
if (texture == null) {
return null;
}
return texture;
}
private static void gatherGeoms(Spatial scene, List<Geometry> geoms) {
if (scene instanceof Node) { if (scene instanceof Node) {
Node node = (Node) scene; Node node = (Node) scene;
for (Spatial child : node.getChildren()) { for (Spatial child : node.getChildren()) {

@ -32,7 +32,17 @@
package jme3tools.optimize; package jme3tools.optimize;
import com.jme3.asset.AssetKey; import com.jme3.asset.AssetKey;
import com.jme3.asset.AssetManager;
import com.jme3.material.MatParamTexture;
import com.jme3.material.Material;
import com.jme3.math.Matrix4f;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.mesh.IndexBuffer;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.Image.Format; import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
@ -40,7 +50,9 @@ import com.jme3.texture.Texture2D;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@ -248,6 +260,118 @@ public class TextureAtlas {
return null; return null;
} }
/**
* Creates one geometry out of the given root spatial and merges all single
* textures into one texture of the given size.
* @param spat The root spatial of the scene to batch
* @param mgr An assetmanager that can be used to create the material
* @param atlasSize A size for the atlas texture, it has to be large enough to hold all single textures
* @return
*/
public static Geometry makeAtlasBatch(Spatial spat, AssetManager mgr, int atlasSize) {
List<Geometry> geometries = new ArrayList<Geometry>();
GeometryBatchFactory.gatherGeoms(spat, geometries);
//TODO: specular etc. maps, needs to use main atlas for locations
TextureAtlas atlas = new TextureAtlas(atlasSize, atlasSize);
for (Geometry geometry : geometries) {
Texture diffuse = getMaterialTexture(geometry, "DiffuseMap");
Texture normal = getMaterialTexture(geometry, "NormalMap");
Texture specular = getMaterialTexture(geometry, "SpecularMap");
if (diffuse == null) {
diffuse = getMaterialTexture(geometry, "ColorMap");
}
if (diffuse != null && diffuse.getKey() != null) {
String keyName = diffuse.getKey().getName();
if (!atlas.addTexture(diffuse, "DiffuseMap")) {
throw new IllegalStateException("Adding diffuse texture" + keyName + "to atlas failed, atlas full.");
} else {
if (normal != null && normal.getKey() != null) {
atlas.addTexture(diffuse, "NormalMap", keyName);
}
if (specular != null && specular.getKey() != null) {
atlas.addTexture(specular, "SpecularMap", keyName);
}
}
}
}
Geometry geom = new Geometry();
Mesh mesh = new Mesh();
GeometryBatchFactory.mergeGeometries(geometries, mesh);
applyAtlasCoords(geometries, mesh, atlas);
mesh.updateCounts();
mesh.updateBound();
geom.setMesh(mesh);
Material mat = new Material(mgr, "Common/MatDefs/Light/Lighting.j3md");
mat.getAdditionalRenderState().setAlphaTest(true);
Texture diffuseMap = atlas.getAtlasTexture("DiffuseMap");
Texture normalMap = atlas.getAtlasTexture("NormalMap");
Texture specularMap = atlas.getAtlasTexture("SpecularMap");
if (diffuseMap != null) {
mat.setTexture("DiffuseMap", diffuseMap);
}
if (normalMap != null) {
mat.setTexture("NormalMap", normalMap);
}
if (specularMap != null) {
mat.setTexture("SpecularMap", specularMap);
}
mat.setFloat("Shininess", 16.0f);
geom.setMaterial(mat);
return geom;
}
private static void applyAtlasCoords(List<Geometry> geometries, Mesh outMesh, TextureAtlas atlas) {
int globalVertIndex = 0;
for (Geometry geom : geometries) {
Mesh inMesh = geom.getMesh();
geom.computeWorldMatrix();
int geomVertCount = inMesh.getVertexCount();
VertexBuffer inBuf = inMesh.getBuffer(Type.TexCoord);
VertexBuffer outBuf = outMesh.getBuffer(Type.TexCoord);
if (inBuf == null || outBuf == null) {
continue;
}
Texture tex = getMaterialTexture(geom, "DiffuseMap");
if (tex == null) {
tex = getMaterialTexture(geom, "ColorMap");
}
if (tex != null) {
TextureAtlasTile tile = atlas.getAtlasTile(tex);
if (tile != null) {
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
tile.transformTextureCoords(inPos, globalVertIndex, outPos);
}
}
globalVertIndex += geomVertCount;
}
}
private static Texture getMaterialTexture(Geometry geometry, String mapName) {
Material mat = geometry.getMaterial();
if (mat == null || mat.getParam(mapName) == null || !(mat.getParam(mapName) instanceof MatParamTexture)) {
return null;
}
MatParamTexture param = (MatParamTexture) mat.getParam(mapName);
Texture texture = param.getTextureValue();
if (texture == null) {
return null;
}
return texture;
}
private class Node { private class Node {
public TextureAtlasTile location; public TextureAtlasTile location;

Loading…
Cancel
Save