- move TextureAtlas methods out of GeometryBatchFactory
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9044 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
f04654ee20
commit
a265e72759
engine/src
test/jme3test/tools
tools/jme3tools/optimize
@ -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…
x
Reference in New Issue
Block a user