- add test for TextureAtlas
- add GeometryBatchFactory method to create atlased/batched model git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9030 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
81b2e7ca51
commit
58a08eb570
71
engine/src/test/jme3test/tools/TestTextureAtlas.java
Normal file
71
engine/src/test/jme3test/tools/TestTextureAtlas.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jme3test.tools;
|
||||||
|
|
||||||
|
import jme3test.model.shape.*;
|
||||||
|
import com.jme3.app.SimpleApplication;
|
||||||
|
import com.jme3.asset.plugins.ZipLocator;
|
||||||
|
import com.jme3.light.AmbientLight;
|
||||||
|
import com.jme3.light.DirectionalLight;
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import jme3tools.optimize.GeometryBatchFactory;
|
||||||
|
|
||||||
|
public class TestTextureAtlas extends SimpleApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args){
|
||||||
|
TestTextureAtlas app = new TestTextureAtlas();
|
||||||
|
app.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleInitApp() {
|
||||||
|
assetManager.registerLocator("wildhouse.zip", ZipLocator.class.getName());
|
||||||
|
Spatial scene = assetManager.loadModel("main.scene");
|
||||||
|
|
||||||
|
Geometry geom = GeometryBatchFactory.makeAtlasBatch(scene, assetManager, 4096);
|
||||||
|
|
||||||
|
AmbientLight al = new AmbientLight();
|
||||||
|
scene.addLight(al);
|
||||||
|
|
||||||
|
DirectionalLight sun = new DirectionalLight();
|
||||||
|
sun.setDirection(new Vector3f(0.69077975f, -0.6277887f, -0.35875428f).normalizeLocal());
|
||||||
|
sun.setColor(ColorRGBA.White.clone().multLocal(2));
|
||||||
|
scene.addLight(sun);
|
||||||
|
|
||||||
|
rootNode.attachChild(geom);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
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;
|
||||||
@ -10,15 +12,22 @@ 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 com.jme3.util.TangentBinormalGenerator;
|
||||||
import java.nio.Buffer;
|
import java.nio.Buffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import jme3tools.optimize.TextureAtlas.TextureAtlasTile;
|
||||||
|
|
||||||
public class GeometryBatchFactory {
|
public class GeometryBatchFactory {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(GeometryBatchFactory.class.getName());
|
||||||
|
|
||||||
private static void doTransformVerts(FloatBuffer inBuf, int offset, FloatBuffer outBuf, Matrix4f transform) {
|
private static void doTransformVerts(FloatBuffer inBuf, int offset, FloatBuffer outBuf, Matrix4f transform) {
|
||||||
Vector3f pos = new Vector3f();
|
Vector3f pos = new Vector3f();
|
||||||
|
|
||||||
@ -61,12 +70,24 @@ public class GeometryBatchFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges all geometries in the collection into
|
* Merges all geometries in the collection into
|
||||||
* the output mesh. Does not take into account materials.
|
* the output mesh. Creates a new material using the TextureAtlas.
|
||||||
*
|
*
|
||||||
* @param geometries
|
* @param geometries
|
||||||
* @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];
|
||||||
|
|
||||||
@ -161,7 +182,7 @@ public class GeometryBatchFactory {
|
|||||||
if (inBuf == null || outBuf == null) {
|
if (inBuf == null || outBuf == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Type.Index.ordinal() == bufType) {
|
if (Type.Index.ordinal() == bufType) {
|
||||||
int components = compsForBuf[bufType];
|
int components = compsForBuf[bufType];
|
||||||
|
|
||||||
@ -182,6 +203,20 @@ 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 && tex.getKey() != null) {
|
||||||
|
TextureAtlasTile tile = atlas.getAtlasTile(tex.getKey().getName());
|
||||||
|
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;
|
||||||
@ -288,6 +323,76 @@ public class GeometryBatchFactory {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Geometry makeAtlasBatch(Spatial spat, AssetManager mgr, int atlasSize) {
|
||||||
|
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")) {
|
||||||
|
logger.log(Level.WARNING, "Adding diffuse texture {0} to atlas failed, atlas full?", keyName);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
TangentBinormalGenerator.generate(mesh);
|
||||||
|
mesh.updateCounts();
|
||||||
|
mesh.updateBound();
|
||||||
|
geom.setMesh(mesh);
|
||||||
|
// geom.setMesh(new Box(1,1,1));
|
||||||
|
|
||||||
|
// Material mat = new Material(mgr, "Common/MatDefs/Light/Lighting.j3md");
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
Material mat = new Material(mgr, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
|
mat.setTexture("ColorMap", atlas.getAtlasTexture("DiffuseMap"));
|
||||||
|
|
||||||
|
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) {
|
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;
|
||||||
@ -335,7 +440,7 @@ public class GeometryBatchFactory {
|
|||||||
|
|
||||||
// Since the scene is returned unaltered the transform must be reset
|
// Since the scene is returned unaltered the transform must be reset
|
||||||
scene.setLocalTransform(Transform.IDENTITY);
|
scene.setLocalTransform(Transform.IDENTITY);
|
||||||
|
|
||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ public class TextureAtlas {
|
|||||||
Texture2D tex = new Texture2D(new Image(format, atlasWidth, atlasHeight, BufferUtils.createByteBuffer(image)));
|
Texture2D tex = new Texture2D(new Image(format, atlasWidth, atlasHeight, BufferUtils.createByteBuffer(image)));
|
||||||
tex.setMagFilter(Texture.MagFilter.Bilinear);
|
tex.setMagFilter(Texture.MagFilter.Bilinear);
|
||||||
tex.setMinFilter(Texture.MinFilter.BilinearNearestMipMap);
|
tex.setMinFilter(Texture.MinFilter.BilinearNearestMipMap);
|
||||||
tex.setWrap(Texture.WrapMode.Repeat);
|
tex.setWrap(Texture.WrapMode.Clamp);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -267,6 +267,12 @@ public class TextureAtlas {
|
|||||||
float h = (float) getHeight() / (float) atlasHeight;
|
float h = (float) getHeight() / (float) atlasHeight;
|
||||||
Vector2f location = new Vector2f(x, y);
|
Vector2f location = new Vector2f(x, y);
|
||||||
Vector2f scale = new Vector2f(w, h);
|
Vector2f scale = new Vector2f(w, h);
|
||||||
|
// if (previousLocation.x > 1) {
|
||||||
|
// previousLocation.x = previousLocation.x - (int) previousLocation.x;
|
||||||
|
// }
|
||||||
|
// if (previousLocation.y > 1) {
|
||||||
|
// previousLocation.y = previousLocation.y - (int) previousLocation.y;
|
||||||
|
// }
|
||||||
return location.addLocal(previousLocation.multLocal(scale));
|
return location.addLocal(previousLocation.multLocal(scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user