- 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;
|
||||
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.material.MatParamTexture;
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.math.Matrix4f;
|
||||
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.Usage;
|
||||
import com.jme3.scene.mesh.IndexBuffer;
|
||||
import com.jme3.texture.Texture;
|
||||
import com.jme3.util.BufferUtils;
|
||||
import com.jme3.util.IntMap.Entry;
|
||||
import com.jme3.util.TangentBinormalGenerator;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import jme3tools.optimize.TextureAtlas.TextureAtlasTile;
|
||||
|
||||
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) {
|
||||
Vector3f pos = new Vector3f();
|
||||
|
||||
@ -61,12 +70,24 @@ public class GeometryBatchFactory {
|
||||
|
||||
/**
|
||||
* 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 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];
|
||||
Format[] formatForBuf = new Format[compsForBuf.length];
|
||||
|
||||
@ -182,6 +203,20 @@ public class GeometryBatchFactory {
|
||||
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
|
||||
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
|
||||
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 {
|
||||
for (int vert = 0; vert < geomVertCount; vert++) {
|
||||
int curGlobalVertIndex = globalVertIndex + vert;
|
||||
@ -288,6 +323,76 @@ public class GeometryBatchFactory {
|
||||
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) {
|
||||
if (scene instanceof Node) {
|
||||
Node node = (Node) scene;
|
||||
|
@ -182,7 +182,7 @@ public class TextureAtlas {
|
||||
Texture2D tex = new Texture2D(new Image(format, atlasWidth, atlasHeight, BufferUtils.createByteBuffer(image)));
|
||||
tex.setMagFilter(Texture.MagFilter.Bilinear);
|
||||
tex.setMinFilter(Texture.MinFilter.BilinearNearestMipMap);
|
||||
tex.setWrap(Texture.WrapMode.Repeat);
|
||||
tex.setWrap(Texture.WrapMode.Clamp);
|
||||
return tex;
|
||||
}
|
||||
return null;
|
||||
@ -267,6 +267,12 @@ public class TextureAtlas {
|
||||
float h = (float) getHeight() / (float) atlasHeight;
|
||||
Vector2f location = new Vector2f(x, y);
|
||||
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));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user