Asset manager queueing + cube voxel meshing
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
316364ad5a
commit
1b1876643d
@ -1,3 +1,3 @@
|
|||||||
#maven.buildNumber.plugin properties file
|
#maven.buildNumber.plugin properties file
|
||||||
#Sat Nov 23 11:28:50 EST 2024
|
#Sat Nov 23 20:49:19 EST 2024
|
||||||
buildNumber=401
|
buildNumber=403
|
||||||
|
|||||||
@ -1140,6 +1140,10 @@ Move text files to documentation pages
|
|||||||
1000th commit milestone!
|
1000th commit milestone!
|
||||||
Pine tree collidables
|
Pine tree collidables
|
||||||
Fix human animation bad data
|
Fix human animation bad data
|
||||||
|
Fix script entity spawn utils not spawning on max cursor distance
|
||||||
|
Block mesh generation
|
||||||
|
Add asset manager support for queueing models asynchronously w/ promised path
|
||||||
|
Add promised path support to queued textures
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|||||||
151
src/main/java/electrosphere/client/block/BlockChunkData.java
Normal file
151
src/main/java/electrosphere/client/block/BlockChunkData.java
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package electrosphere.client.block;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores data about a chunk of blocks
|
||||||
|
*/
|
||||||
|
public class BlockChunkData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of blocks in each dimension of a chunk
|
||||||
|
*/
|
||||||
|
public static final int CHUNK_DATA_WIDTH = 64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of blocks to place within each unit of distance
|
||||||
|
*/
|
||||||
|
public static final int BLOCKS_PER_UNIT_DISTANCE = CHUNK_DATA_WIDTH / ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount to scale block size by
|
||||||
|
*/
|
||||||
|
public static final float BLOCK_SIZE_MULTIPLIER = 1.0f / BLOCKS_PER_UNIT_DISTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of block at a given position
|
||||||
|
*/
|
||||||
|
short[] type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata about a block
|
||||||
|
* first 4 bits are the rotation of the block)
|
||||||
|
*/
|
||||||
|
short[] metadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public BlockChunkData(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public static BlockChunkData allocate(){
|
||||||
|
BlockChunkData rVal = new BlockChunkData();
|
||||||
|
rVal.setType(new short[CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH]);
|
||||||
|
rVal.setMetadata(new short[CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH]);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type data for the chunk
|
||||||
|
* @return The type data
|
||||||
|
*/
|
||||||
|
public short[] getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type data for the chunk
|
||||||
|
* @param type The type data
|
||||||
|
*/
|
||||||
|
public void setType(short[] type) {
|
||||||
|
if(type.length != CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH){
|
||||||
|
throw new Error("Set type with invalid length! " + type.length);
|
||||||
|
}
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata for the chunk
|
||||||
|
* @return The metadata
|
||||||
|
*/
|
||||||
|
public short[] getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the metadata for the chunk
|
||||||
|
* @param metadata The metadata
|
||||||
|
*/
|
||||||
|
public void setMetadata(short[] metadata) {
|
||||||
|
if(metadata.length != CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH){
|
||||||
|
throw new Error("Set metadata with invalid length! " + metadata.length);
|
||||||
|
}
|
||||||
|
this.metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type at a given position
|
||||||
|
* @param x The x position
|
||||||
|
* @param y The y position
|
||||||
|
* @param z The z position
|
||||||
|
* @return The type at that position
|
||||||
|
*/
|
||||||
|
public short getType(int x, int y, int z){
|
||||||
|
return this.type[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a specific block's type
|
||||||
|
* @param x The x position
|
||||||
|
* @param y The y position
|
||||||
|
* @param z The z position
|
||||||
|
* @param type The type
|
||||||
|
*/
|
||||||
|
public void setType(int x, int y, int z, short type){
|
||||||
|
this.type[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a specific block's type
|
||||||
|
* @param x The x position
|
||||||
|
* @param y The y position
|
||||||
|
* @param z The z position
|
||||||
|
* @param type The type
|
||||||
|
*/
|
||||||
|
public void setType(int x, int y, int z, int type){
|
||||||
|
this.type[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = (short)type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata at a given position
|
||||||
|
* @param x The x position
|
||||||
|
* @param y The y position
|
||||||
|
* @param z The z position
|
||||||
|
* @return The metadata at that position
|
||||||
|
*/
|
||||||
|
public short getMetadata(int x, int y, int z){
|
||||||
|
return this.metadata[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given location is empty
|
||||||
|
* @param x The x position
|
||||||
|
* @param y The y position
|
||||||
|
* @param z The z position
|
||||||
|
* @return true if empty, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isEmpty(int x, int y, int z){
|
||||||
|
boolean empty = this.getType(x,y,z) == 0;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -41,10 +41,11 @@ public class ScriptLevelEditorUtils {
|
|||||||
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
||||||
CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity
|
CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity
|
||||||
Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
||||||
if(cursorPos != null){
|
if(cursorPos == null){
|
||||||
|
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
|
||||||
|
}
|
||||||
cursorPos = cursorPos.add(cursorVerticalOffset);
|
cursorPos = cursorPos.add(cursorVerticalOffset);
|
||||||
CreatureUtils.serverSpawnBasicCreature(realm, cursorPos, Globals.selectedSpawntype.getId(), null);
|
CreatureUtils.serverSpawnBasicCreature(realm, cursorPos, Globals.selectedSpawntype.getId(), null);
|
||||||
}
|
|
||||||
} else if(Globals.selectedSpawntype instanceof Item){
|
} else if(Globals.selectedSpawntype instanceof Item){
|
||||||
LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!");
|
LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!");
|
||||||
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
|
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
|
||||||
@ -52,10 +53,11 @@ public class ScriptLevelEditorUtils {
|
|||||||
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
||||||
CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity
|
CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity
|
||||||
Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
||||||
if(cursorPos != null){
|
if(cursorPos == null){
|
||||||
|
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
|
||||||
|
}
|
||||||
cursorPos = cursorPos.add(cursorVerticalOffset);
|
cursorPos = cursorPos.add(cursorVerticalOffset);
|
||||||
ItemUtils.serverSpawnBasicItem(realm, cursorPos, Globals.selectedSpawntype.getId());
|
ItemUtils.serverSpawnBasicItem(realm, cursorPos, Globals.selectedSpawntype.getId());
|
||||||
}
|
|
||||||
} else if(Globals.selectedSpawntype instanceof FoliageType){
|
} else if(Globals.selectedSpawntype instanceof FoliageType){
|
||||||
LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!");
|
LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!");
|
||||||
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
|
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
|
||||||
@ -63,10 +65,11 @@ public class ScriptLevelEditorUtils {
|
|||||||
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
||||||
CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity
|
CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity
|
||||||
Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
||||||
if(cursorPos != null){
|
if(cursorPos == null){
|
||||||
|
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
|
||||||
|
}
|
||||||
cursorPos = cursorPos.add(cursorVerticalOffset);
|
cursorPos = cursorPos.add(cursorVerticalOffset);
|
||||||
FoliageUtils.serverSpawnTreeFoliage(realm, cursorPos, Globals.selectedSpawntype.getId(), new Random().nextLong());
|
FoliageUtils.serverSpawnTreeFoliage(realm, cursorPos, Globals.selectedSpawntype.getId(), new Random().nextLong());
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!");
|
LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!");
|
||||||
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
|
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
|
||||||
@ -74,13 +77,14 @@ public class ScriptLevelEditorUtils {
|
|||||||
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
||||||
CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity
|
CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity
|
||||||
Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
||||||
if(cursorPos != null){
|
if(cursorPos == null){
|
||||||
|
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
|
||||||
|
}
|
||||||
cursorPos = cursorPos.add(cursorVerticalOffset);
|
cursorPos = cursorPos.add(cursorVerticalOffset);
|
||||||
CommonEntityUtils.serverSpawnBasicObject(realm, cursorPos, Globals.selectedSpawntype.getId());
|
CommonEntityUtils.serverSpawnBasicObject(realm, cursorPos, Globals.selectedSpawntype.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspects the entity that the player's cursor is hovering over
|
* Inspects the entity that the player's cursor is hovering over
|
||||||
|
|||||||
@ -76,7 +76,7 @@ public class AssetManager {
|
|||||||
|
|
||||||
//assets queued to be loaded
|
//assets queued to be loaded
|
||||||
ReentrantLock queuedAssetLock = new ReentrantLock();
|
ReentrantLock queuedAssetLock = new ReentrantLock();
|
||||||
List<QueuedAsset> queuedAssets = new LinkedList<QueuedAsset>();
|
List<QueuedAsset<?>> queuedAssets = new LinkedList<QueuedAsset<?>>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -160,8 +160,13 @@ public class AssetManager {
|
|||||||
//queued assets
|
//queued assets
|
||||||
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load queued assets");
|
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load queued assets");
|
||||||
queuedAssetLock.lock();
|
queuedAssetLock.lock();
|
||||||
for(QueuedAsset queuedAsset : queuedAssets){
|
for(QueuedAsset<?> queuedAsset : queuedAssets){
|
||||||
queuedAsset.load();
|
queuedAsset.load();
|
||||||
|
if(queuedAsset.get() instanceof Model){
|
||||||
|
this.modelsLoadedIntoMemory.put(queuedAsset.getPromisedPath(),(Model)queuedAsset.get());
|
||||||
|
} else if(queuedAsset.get() instanceof Model){
|
||||||
|
this.texturesLoadedIntoMemory.put(queuedAsset.getPromisedPath(),(Texture)queuedAsset.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
queuedAssets.clear();
|
queuedAssets.clear();
|
||||||
queuedAssetLock.unlock();
|
queuedAssetLock.unlock();
|
||||||
@ -606,10 +611,18 @@ public class AssetManager {
|
|||||||
* Queues an asset to be loaded on the main thread
|
* Queues an asset to be loaded on the main thread
|
||||||
* @param asset the asset
|
* @param asset the asset
|
||||||
*/
|
*/
|
||||||
public void queuedAsset(QueuedAsset asset){
|
public String queuedAsset(QueuedAsset<?> asset){
|
||||||
queuedAssetLock.lock();
|
queuedAssetLock.lock();
|
||||||
this.queuedAssets.add(asset);
|
this.queuedAssets.add(asset);
|
||||||
|
|
||||||
|
//promise a specific string for this asset
|
||||||
|
UUID newUUID = UUID.randomUUID();
|
||||||
|
String promisedPath = newUUID.toString();
|
||||||
|
asset.setPromisedPath(promisedPath);
|
||||||
|
|
||||||
queuedAssetLock.unlock();
|
queuedAssetLock.unlock();
|
||||||
|
|
||||||
|
return promisedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package electrosphere.engine.assetmanager.queue;
|
|||||||
/**
|
/**
|
||||||
* An asset that has its data ready to be buffered to gpu
|
* An asset that has its data ready to be buffered to gpu
|
||||||
*/
|
*/
|
||||||
public interface QueuedAsset {
|
public interface QueuedAsset<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the asset
|
* Loads the asset
|
||||||
@ -16,4 +16,22 @@ public interface QueuedAsset {
|
|||||||
*/
|
*/
|
||||||
public boolean hasLoaded();
|
public boolean hasLoaded();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the asset
|
||||||
|
* @return The asset
|
||||||
|
*/
|
||||||
|
public T get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the path the asset manager promises this asset will be stored at
|
||||||
|
* @return The promised path
|
||||||
|
*/
|
||||||
|
public String getPromisedPath();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the path the asset manager promises this asset will be stored at
|
||||||
|
* @param promisedPath The path
|
||||||
|
*/
|
||||||
|
public void setPromisedPath(String promisedPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,80 @@
|
|||||||
|
package electrosphere.engine.assetmanager.queue;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
import electrosphere.renderer.model.Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A model that is queued to be loaded
|
||||||
|
*/
|
||||||
|
public class QueuedModel implements QueuedAsset<Model> {
|
||||||
|
|
||||||
|
//true if loaded
|
||||||
|
boolean hasLoaded = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model that will be loaded
|
||||||
|
*/
|
||||||
|
Model model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The runnable to invoke to actually load the model
|
||||||
|
*/
|
||||||
|
Callable<Model> loadFunc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path promised
|
||||||
|
*/
|
||||||
|
String promisedPath;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the queued texture object
|
||||||
|
* @param image the image to load to gpu
|
||||||
|
*/
|
||||||
|
public QueuedModel(Callable<Model> loadFunc){
|
||||||
|
this.loadFunc = loadFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load() {
|
||||||
|
if(loadFunc != null){
|
||||||
|
try {
|
||||||
|
this.model = loadFunc.call();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LoggerInterface.loggerEngine.ERROR(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasLoaded() {
|
||||||
|
return hasLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPromisedPath(){
|
||||||
|
return promisedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the model from this queued item
|
||||||
|
* @return The model
|
||||||
|
*/
|
||||||
|
public Model getModel(){
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPromisedPath(String promisedPath) {
|
||||||
|
this.promisedPath = promisedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Model get(){
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -9,7 +9,7 @@ import electrosphere.renderer.texture.Texture;
|
|||||||
/**
|
/**
|
||||||
* A texture queued to be sent to the gpu
|
* A texture queued to be sent to the gpu
|
||||||
*/
|
*/
|
||||||
public class QueuedTexture implements QueuedAsset {
|
public class QueuedTexture implements QueuedAsset<Texture> {
|
||||||
|
|
||||||
//true if loaded
|
//true if loaded
|
||||||
boolean hasLoaded = false;
|
boolean hasLoaded = false;
|
||||||
@ -35,6 +35,11 @@ public class QueuedTexture implements QueuedAsset {
|
|||||||
*/
|
*/
|
||||||
int height = -1;
|
int height = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path the asset manager promises this texture will be stored at
|
||||||
|
*/
|
||||||
|
String promisedPath;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the queued texture object
|
* Creates the queued texture object
|
||||||
@ -104,6 +109,19 @@ public class QueuedTexture implements QueuedAsset {
|
|||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPromisedPath(String promisedPath) {
|
||||||
|
this.promisedPath = promisedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPromisedPath(){
|
||||||
|
return this.promisedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Texture get(){
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import electrosphere.client.block.BlockChunkData;
|
||||||
import electrosphere.client.entity.camera.CameraEntityUtils;
|
import electrosphere.client.entity.camera.CameraEntityUtils;
|
||||||
import electrosphere.client.entity.crosshair.Crosshair;
|
import electrosphere.client.entity.crosshair.Crosshair;
|
||||||
import electrosphere.client.fluid.cells.FluidCellManager;
|
import electrosphere.client.fluid.cells.FluidCellManager;
|
||||||
@ -18,6 +19,7 @@ import electrosphere.client.ui.menu.mainmenu.MenuCharacterCreation;
|
|||||||
import electrosphere.controls.ControlHandler;
|
import electrosphere.controls.ControlHandler;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.engine.assetmanager.AssetDataStrings;
|
import electrosphere.engine.assetmanager.AssetDataStrings;
|
||||||
|
import electrosphere.engine.assetmanager.queue.QueuedModel;
|
||||||
import electrosphere.engine.signal.Signal.SignalType;
|
import electrosphere.engine.signal.Signal.SignalType;
|
||||||
import electrosphere.engine.threads.LabeledThread.ThreadLabel;
|
import electrosphere.engine.threads.LabeledThread.ThreadLabel;
|
||||||
import electrosphere.entity.DrawableUtils;
|
import electrosphere.entity.DrawableUtils;
|
||||||
@ -29,6 +31,8 @@ import electrosphere.net.NetUtils;
|
|||||||
import electrosphere.net.client.ClientNetworking;
|
import electrosphere.net.client.ClientNetworking;
|
||||||
import electrosphere.renderer.actor.Actor;
|
import electrosphere.renderer.actor.Actor;
|
||||||
import electrosphere.renderer.actor.ActorTextureMask;
|
import electrosphere.renderer.actor.ActorTextureMask;
|
||||||
|
import electrosphere.renderer.meshgen.BlockMeshgen;
|
||||||
|
import electrosphere.renderer.meshgen.BlockMeshgen.BlockMeshData;
|
||||||
|
|
||||||
public class ClientLoading {
|
public class ClientLoading {
|
||||||
|
|
||||||
@ -272,6 +276,23 @@ public class ClientLoading {
|
|||||||
cursorActor.addTextureMask(new ActorTextureMask("sphere", Arrays.asList(new String[]{"Textures/transparent_red.png"})));
|
cursorActor.addTextureMask(new ActorTextureMask("sphere", Arrays.asList(new String[]{"Textures/transparent_red.png"})));
|
||||||
DrawableUtils.makeEntityTransparent(Globals.playerCursor);
|
DrawableUtils.makeEntityTransparent(Globals.playerCursor);
|
||||||
EntityUtils.getScale(Globals.playerCursor).set(0.2f);
|
EntityUtils.getScale(Globals.playerCursor).set(0.2f);
|
||||||
|
|
||||||
|
//block test
|
||||||
|
// Entity blockEntity = EntityCreationUtils.createClientSpatialEntity();
|
||||||
|
// BlockChunkData blockChunkData = BlockChunkData.allocate();
|
||||||
|
// blockChunkData.setType(0, 0, 0, 1);
|
||||||
|
// blockChunkData.setType(1, 0, 0, 1);
|
||||||
|
// blockChunkData.setType(0, 1, 0, 1);
|
||||||
|
// blockChunkData.setType(1, 1, 0, 1);
|
||||||
|
// blockChunkData.setType(0, 0, 1, 1);
|
||||||
|
// blockChunkData.setType(1, 0, 1, 1);
|
||||||
|
// blockChunkData.setType(0, 1, 1, 1);
|
||||||
|
// blockChunkData.setType(1, 1, 1, 1);
|
||||||
|
// BlockMeshData meshData = BlockMeshgen.rasterize(blockChunkData);
|
||||||
|
// String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> {
|
||||||
|
// return BlockMeshgen.generateBlockModel(meshData);
|
||||||
|
// }));
|
||||||
|
// EntityCreationUtils.makeEntityDrawablePreexistingModel(blockEntity, modelPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final int MAX_DRAW_CELL_WAIT = 1000;
|
static final int MAX_DRAW_CELL_WAIT = 1000;
|
||||||
|
|||||||
518
src/main/java/electrosphere/renderer/meshgen/BlockMeshgen.java
Normal file
518
src/main/java/electrosphere/renderer/meshgen/BlockMeshgen.java
Normal file
@ -0,0 +1,518 @@
|
|||||||
|
package electrosphere.renderer.meshgen;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joml.Vector2f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.opengl.GL40;
|
||||||
|
|
||||||
|
import electrosphere.client.block.BlockChunkData;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.renderer.model.Mesh;
|
||||||
|
import electrosphere.renderer.model.Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a model for a block
|
||||||
|
*/
|
||||||
|
public class BlockMeshgen {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The indices to draw faces on cubes
|
||||||
|
*/
|
||||||
|
static final int[] CUBE_INDICES = new int[]{
|
||||||
|
//Top
|
||||||
|
2, 6, 7,
|
||||||
|
2, 3, 7,
|
||||||
|
|
||||||
|
//Bottom
|
||||||
|
0, 4, 5,
|
||||||
|
0, 1, 5,
|
||||||
|
|
||||||
|
//Left
|
||||||
|
0, 2, 6,
|
||||||
|
0, 4, 6,
|
||||||
|
|
||||||
|
//Right
|
||||||
|
1, 3, 7,
|
||||||
|
1, 5, 7,
|
||||||
|
|
||||||
|
//Front
|
||||||
|
0, 2, 3,
|
||||||
|
0, 1, 3,
|
||||||
|
|
||||||
|
//Back
|
||||||
|
4, 6, 7,
|
||||||
|
4, 5, 7
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the quad meshes for the provided chunk data
|
||||||
|
* @param quadMeshes The quad mesh list to fill
|
||||||
|
* @param chunkData The chunk data
|
||||||
|
*/
|
||||||
|
protected static void fillQuadMeshes(List<QuadMesh> quadMeshes, BlockChunkData chunkData){
|
||||||
|
for(int z = 0; z < BlockChunkData.CHUNK_DATA_WIDTH; z++){
|
||||||
|
for(int x = 0; x < BlockChunkData.CHUNK_DATA_WIDTH; x++){
|
||||||
|
QuadMesh currentQuad = null;
|
||||||
|
for(int y = 0; y < BlockChunkData.CHUNK_DATA_WIDTH; y++){
|
||||||
|
if(chunkData.isEmpty(x, y, z)){
|
||||||
|
if(currentQuad == null){
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
currentQuad.h = y - currentQuad.y;
|
||||||
|
//check if should merge with previous quad
|
||||||
|
for(QuadMesh prevMesh : quadMeshes){
|
||||||
|
if(prevMesh.x + prevMesh.w == currentQuad.x && prevMesh.y == currentQuad.y && prevMesh.h == currentQuad.h){
|
||||||
|
prevMesh.w = prevMesh.w + 1;
|
||||||
|
currentQuad = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(currentQuad != null){
|
||||||
|
quadMeshes.add(currentQuad);
|
||||||
|
}
|
||||||
|
currentQuad = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(currentQuad == null){
|
||||||
|
currentQuad = new QuadMesh();
|
||||||
|
currentQuad.x = x;
|
||||||
|
currentQuad.y = y;
|
||||||
|
currentQuad.z = z;
|
||||||
|
currentQuad.w = 1;
|
||||||
|
currentQuad.h = 1;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Meshes a box
|
||||||
|
* @param verts The list of verts to store into
|
||||||
|
* @param normals The list of normals to store into
|
||||||
|
* @param uvs The list of uvs to store into
|
||||||
|
* @param indices The list of indices to store into
|
||||||
|
* @param quad The quad
|
||||||
|
* @param depth The depth of the box
|
||||||
|
*/
|
||||||
|
protected static void meshifyBox(List<Vector3f> verts, List<Vector3f> normals, List<Vector2f> uvs, List<Integer> indices, QuadMesh quad, int depth){
|
||||||
|
//
|
||||||
|
//face 1
|
||||||
|
//
|
||||||
|
|
||||||
|
//verts
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y, quad.z).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y, quad.z).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y + quad.h, quad.z).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y + quad.h, quad.z).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
//indices
|
||||||
|
indices.add(0);
|
||||||
|
indices.add(2);
|
||||||
|
indices.add(3);
|
||||||
|
indices.add(0);
|
||||||
|
indices.add(1);
|
||||||
|
indices.add(3);
|
||||||
|
//normals
|
||||||
|
normals.add(new Vector3f(0,0,-1));
|
||||||
|
normals.add(new Vector3f(0,0,-1));
|
||||||
|
normals.add(new Vector3f(0,0,-1));
|
||||||
|
normals.add(new Vector3f(0,0,-1));
|
||||||
|
//uvs
|
||||||
|
uvs.add(new Vector2f( 0, 0));
|
||||||
|
uvs.add(new Vector2f(quad.w, 0));
|
||||||
|
uvs.add(new Vector2f( 0, quad.h));
|
||||||
|
uvs.add(new Vector2f(quad.w, quad.h));
|
||||||
|
|
||||||
|
//
|
||||||
|
//face 2
|
||||||
|
//
|
||||||
|
|
||||||
|
//verts
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y, quad.z ).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y + quad.h, quad.z ).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y + quad.h, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
//indices
|
||||||
|
indices.add(4);
|
||||||
|
indices.add(6);
|
||||||
|
indices.add(7);
|
||||||
|
indices.add(4);
|
||||||
|
indices.add(5);
|
||||||
|
indices.add(7);
|
||||||
|
//normals
|
||||||
|
normals.add(new Vector3f(-1,0,0));
|
||||||
|
normals.add(new Vector3f(-1,0,0));
|
||||||
|
normals.add(new Vector3f(-1,0,0));
|
||||||
|
normals.add(new Vector3f(-1,0,0));
|
||||||
|
//uvs
|
||||||
|
uvs.add(new Vector2f( 0, 0));
|
||||||
|
uvs.add(new Vector2f(depth, 0));
|
||||||
|
uvs.add(new Vector2f( 0, quad.h));
|
||||||
|
uvs.add(new Vector2f(depth, quad.h));
|
||||||
|
|
||||||
|
//
|
||||||
|
//face 3
|
||||||
|
//
|
||||||
|
|
||||||
|
//verts
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y, quad.z ).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y, quad.z ).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
//indices
|
||||||
|
indices.add( 8);
|
||||||
|
indices.add(10);
|
||||||
|
indices.add(11);
|
||||||
|
indices.add( 8);
|
||||||
|
indices.add( 9);
|
||||||
|
indices.add(11);
|
||||||
|
//normals
|
||||||
|
normals.add(new Vector3f(0,-1,0));
|
||||||
|
normals.add(new Vector3f(0,-1,0));
|
||||||
|
normals.add(new Vector3f(0,-1,0));
|
||||||
|
normals.add(new Vector3f(0,-1,0));
|
||||||
|
//uvs
|
||||||
|
uvs.add(new Vector2f( 0, 0));
|
||||||
|
uvs.add(new Vector2f(depth, 0));
|
||||||
|
uvs.add(new Vector2f( 0, quad.w));
|
||||||
|
uvs.add(new Vector2f(depth, quad.w));
|
||||||
|
|
||||||
|
//
|
||||||
|
//face 4
|
||||||
|
//
|
||||||
|
|
||||||
|
//verts
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y + quad.h, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y + quad.h, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
//indices
|
||||||
|
indices.add(12);
|
||||||
|
indices.add(14);
|
||||||
|
indices.add(15);
|
||||||
|
indices.add(12);
|
||||||
|
indices.add(13);
|
||||||
|
indices.add(15);
|
||||||
|
//normals
|
||||||
|
normals.add(new Vector3f(0,0,1));
|
||||||
|
normals.add(new Vector3f(0,0,1));
|
||||||
|
normals.add(new Vector3f(0,0,1));
|
||||||
|
normals.add(new Vector3f(0,0,1));
|
||||||
|
//uvs
|
||||||
|
uvs.add(new Vector2f( 0, 0));
|
||||||
|
uvs.add(new Vector2f(quad.w, 0));
|
||||||
|
uvs.add(new Vector2f( 0, quad.h));
|
||||||
|
uvs.add(new Vector2f(quad.w, quad.h));
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//face 5
|
||||||
|
//
|
||||||
|
|
||||||
|
//verts
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y, quad.z ).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y + quad.h, quad.z ).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y + quad.h, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
//indices
|
||||||
|
indices.add(16);
|
||||||
|
indices.add(18);
|
||||||
|
indices.add(19);
|
||||||
|
indices.add(16);
|
||||||
|
indices.add(17);
|
||||||
|
indices.add(19);
|
||||||
|
//normals
|
||||||
|
normals.add(new Vector3f(1,0,0));
|
||||||
|
normals.add(new Vector3f(1,0,0));
|
||||||
|
normals.add(new Vector3f(1,0,0));
|
||||||
|
normals.add(new Vector3f(1,0,0));
|
||||||
|
//uvs
|
||||||
|
uvs.add(new Vector2f( 0, 0));
|
||||||
|
uvs.add(new Vector2f(depth, 0));
|
||||||
|
uvs.add(new Vector2f( 0, quad.h));
|
||||||
|
uvs.add(new Vector2f(depth, quad.h));
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//face 6
|
||||||
|
//
|
||||||
|
|
||||||
|
//verts
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y + quad.h, quad.z ).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x, quad.y + quad.h, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y + quad.h, quad.z ).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
verts.add(new Vector3f(quad.x + quad.w, quad.y + quad.h, quad.z + depth).mul(BlockChunkData.BLOCK_SIZE_MULTIPLIER));
|
||||||
|
//indices
|
||||||
|
indices.add(20);
|
||||||
|
indices.add(22);
|
||||||
|
indices.add(23);
|
||||||
|
indices.add(20);
|
||||||
|
indices.add(21);
|
||||||
|
indices.add(23);
|
||||||
|
//normals
|
||||||
|
normals.add(new Vector3f(0,1,0));
|
||||||
|
normals.add(new Vector3f(0,1,0));
|
||||||
|
normals.add(new Vector3f(0,1,0));
|
||||||
|
normals.add(new Vector3f(0,1,0));
|
||||||
|
//uvs
|
||||||
|
uvs.add(new Vector2f( 0, 0));
|
||||||
|
uvs.add(new Vector2f(depth, 0));
|
||||||
|
uvs.add(new Vector2f( 0, quad.w));
|
||||||
|
uvs.add(new Vector2f(depth, quad.w));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rasterizes a block chunk data into mesh data
|
||||||
|
* @param chunkData The block chunk data
|
||||||
|
* @return The mesh data
|
||||||
|
*/
|
||||||
|
public static BlockMeshData rasterize(BlockChunkData chunkData){
|
||||||
|
BlockMeshData rVal = new BlockMeshData();
|
||||||
|
|
||||||
|
//calculate quad meshes
|
||||||
|
List<QuadMesh> quadMeshes = new LinkedList<QuadMesh>();
|
||||||
|
BlockMeshgen.fillQuadMeshes(quadMeshes, chunkData);
|
||||||
|
|
||||||
|
//allocate lists to store mesh data in
|
||||||
|
List<Vector3f> verts = new LinkedList<Vector3f>();
|
||||||
|
List<Vector3f> normals = new LinkedList<Vector3f>();
|
||||||
|
List<Vector2f> uvs = new LinkedList<Vector2f>();
|
||||||
|
List<Integer> indices = new LinkedList<Integer>();
|
||||||
|
|
||||||
|
//sort
|
||||||
|
Collections.sort(quadMeshes);
|
||||||
|
|
||||||
|
//generate volumes
|
||||||
|
QuadMesh quad1 = null;
|
||||||
|
QuadMesh quad2 = null;
|
||||||
|
int zEnd = 0;
|
||||||
|
for(int i = 0; i < quadMeshes.size(); i++){
|
||||||
|
quad1 = quadMeshes.get(i);
|
||||||
|
zEnd = 1;
|
||||||
|
for(int j = i + 1; j < quadMeshes.size(); j++){
|
||||||
|
quad2 = quadMeshes.get(j);
|
||||||
|
if(quad1.x == quad2.x && quad1.y == quad2.y && quad1.w == quad2.w && quad1.h == quad2.h && quad1.z + zEnd == quad2.z){
|
||||||
|
zEnd++;
|
||||||
|
} else {
|
||||||
|
BlockMeshgen.meshifyBox(verts,normals,uvs,indices,quad1,zEnd);
|
||||||
|
quad1 = quad2;
|
||||||
|
zEnd = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = i + zEnd;
|
||||||
|
}
|
||||||
|
if(quad1 != null){
|
||||||
|
BlockMeshgen.meshifyBox(verts,normals,uvs,indices,quad1,zEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//store in flat arrays
|
||||||
|
//
|
||||||
|
|
||||||
|
//verts
|
||||||
|
rVal.vertices = new float[verts.size() * 3];
|
||||||
|
for(int i = 0; i < verts.size(); i++){
|
||||||
|
Vector3f currentVert = verts.get(i);
|
||||||
|
rVal.vertices[3 * i + 0] = currentVert.x;
|
||||||
|
rVal.vertices[3 * i + 1] = currentVert.y;
|
||||||
|
rVal.vertices[3 * i + 2] = currentVert.z;
|
||||||
|
}
|
||||||
|
rVal.vertBuffer = BufferUtils.createFloatBuffer(rVal.vertices.length);
|
||||||
|
rVal.vertBuffer.put(rVal.vertices);
|
||||||
|
|
||||||
|
//faces
|
||||||
|
rVal.faceElements = new int[indices.size()];
|
||||||
|
for(int i = 0; i < indices.size(); i++){
|
||||||
|
rVal.faceElements[i] = indices.get(i);
|
||||||
|
}
|
||||||
|
rVal.faceBuffer = BufferUtils.createIntBuffer(rVal.faceElements.length);
|
||||||
|
rVal.faceBuffer.put(rVal.faceElements);
|
||||||
|
|
||||||
|
//normals
|
||||||
|
rVal.normals = new float[normals.size() * 3];
|
||||||
|
for(int i = 0; i < normals.size(); i++){
|
||||||
|
Vector3f currentNormal = normals.get(i);
|
||||||
|
rVal.normals[3 * i + 0] = currentNormal.x;
|
||||||
|
rVal.normals[3 * i + 1] = currentNormal.y;
|
||||||
|
rVal.normals[3 * i + 2] = currentNormal.z;
|
||||||
|
}
|
||||||
|
rVal.normalBuffer = BufferUtils.createFloatBuffer(rVal.normals.length);
|
||||||
|
rVal.normalBuffer.put(rVal.normals);
|
||||||
|
|
||||||
|
//uvs
|
||||||
|
rVal.uvs = new float[uvs.size() * 2];
|
||||||
|
for(int i = 0; i < uvs.size(); i++){
|
||||||
|
Vector2f currentUV = uvs.get(i);
|
||||||
|
rVal.uvs[2 * i + 0] = currentUV.x;
|
||||||
|
rVal.uvs[2 * i + 1] = currentUV.y;
|
||||||
|
}
|
||||||
|
rVal.uvBuffer = BufferUtils.createFloatBuffer(rVal.uvs.length);
|
||||||
|
rVal.uvBuffer.put(rVal.uvs);
|
||||||
|
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a mesh based on a block mesh data object
|
||||||
|
* @param data The block mesh data object
|
||||||
|
* @return The mesh
|
||||||
|
*/
|
||||||
|
protected static Mesh generateBlockMesh(BlockMeshData meshData){
|
||||||
|
Mesh mesh = new Mesh("blockChunk");
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// VAO
|
||||||
|
//
|
||||||
|
mesh.generateVAO();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FloatBuffer vertexArrayBufferData = meshData.vertBuffer;
|
||||||
|
FloatBuffer normalArrayBufferData = meshData.normalBuffer;
|
||||||
|
FloatBuffer textureArrayBufferData = meshData.uvBuffer;
|
||||||
|
IntBuffer elementArrayBufferData = meshData.faceBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Buffer data to GPU
|
||||||
|
//
|
||||||
|
int elementCount = meshData.faceElements.length;
|
||||||
|
try {
|
||||||
|
//actually buffer vertices
|
||||||
|
if(vertexArrayBufferData.position() > 0){
|
||||||
|
vertexArrayBufferData.flip();
|
||||||
|
mesh.bufferVertices(vertexArrayBufferData, 3);
|
||||||
|
}
|
||||||
|
//actually buffer normals
|
||||||
|
if(normalArrayBufferData != null && normalArrayBufferData.position() > 0){
|
||||||
|
normalArrayBufferData.flip();
|
||||||
|
mesh.bufferNormals(normalArrayBufferData, 3);
|
||||||
|
}
|
||||||
|
//actually buffer UVs
|
||||||
|
if(textureArrayBufferData != null && textureArrayBufferData.position() > 0){
|
||||||
|
textureArrayBufferData.flip();
|
||||||
|
mesh.bufferTextureCoords(textureArrayBufferData, 2);
|
||||||
|
}
|
||||||
|
//buffer element indices
|
||||||
|
if(elementArrayBufferData.position() > 0){
|
||||||
|
elementArrayBufferData.flip();
|
||||||
|
mesh.bufferFaces(elementArrayBufferData, elementCount);
|
||||||
|
}
|
||||||
|
} catch (NullPointerException ex){
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
//bounding sphere logic
|
||||||
|
int distance = BlockChunkData.CHUNK_DATA_WIDTH / 2;
|
||||||
|
mesh.updateBoundingSphere(
|
||||||
|
distance,
|
||||||
|
distance,
|
||||||
|
distance,
|
||||||
|
(float)Math.sqrt(
|
||||||
|
distance * distance +
|
||||||
|
distance * distance +
|
||||||
|
distance * distance
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GL40.glBindVertexArray(0);
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the model for the block mesh
|
||||||
|
* @param chunkData The mesh data
|
||||||
|
* @return The model object
|
||||||
|
*/
|
||||||
|
public static Model generateBlockModel(BlockMeshData meshData){
|
||||||
|
Model rVal = new Model();
|
||||||
|
Mesh m = BlockMeshgen.generateBlockMesh(meshData);
|
||||||
|
|
||||||
|
//construct the material for the chunk
|
||||||
|
// Material groundMat = new Material();
|
||||||
|
// groundMat.setTexturePointer(Globals.defaultMeshShader);
|
||||||
|
// groundMat.setNormalTexturePointer(atlas.getNormal().getTexturePointer());
|
||||||
|
// m.setMaterial(groundMat);
|
||||||
|
|
||||||
|
//shader logic
|
||||||
|
m.setShader(Globals.defaultMeshShader);
|
||||||
|
m.setParent(rVal);
|
||||||
|
|
||||||
|
rVal.getMeshes().add(m);
|
||||||
|
rVal.setBoundingSphere(m.getBoundingSphere());
|
||||||
|
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The final rasterization data that is emitted
|
||||||
|
*/
|
||||||
|
public static class BlockMeshData {
|
||||||
|
//the verts
|
||||||
|
float[] vertices;
|
||||||
|
//normals
|
||||||
|
float[] normals;
|
||||||
|
//faces
|
||||||
|
int[] faceElements;
|
||||||
|
//UVs
|
||||||
|
float[] uvs;
|
||||||
|
|
||||||
|
FloatBuffer vertBuffer;
|
||||||
|
FloatBuffer normalBuffer;
|
||||||
|
IntBuffer faceBuffer;
|
||||||
|
FloatBuffer uvBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intermediary structure used during rasterization
|
||||||
|
*/
|
||||||
|
public static class QuadMesh implements Comparable<QuadMesh> {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
int w;
|
||||||
|
int h;
|
||||||
|
public QuadMesh(){}
|
||||||
|
public QuadMesh(int x, int y, int z, int w, int h){
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.w = w;
|
||||||
|
this.h = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(QuadMesh other) {
|
||||||
|
if(this.y != other.y){
|
||||||
|
return this.y - other.y;
|
||||||
|
}
|
||||||
|
if(this.x != other.x){
|
||||||
|
return this.x - other.x;
|
||||||
|
}
|
||||||
|
if(this.w != other.w){
|
||||||
|
return this.w - other.w;
|
||||||
|
}
|
||||||
|
return this.h - other.h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
1097
src/test/java/electrosphere/renderer/meshgen/BlockMeshgenTests.java
Normal file
1097
src/test/java/electrosphere/renderer/meshgen/BlockMeshgenTests.java
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user