texture loading from model files
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-04-29 19:32:00 -04:00
parent 32d9725f1e
commit 7f557d40c0
8 changed files with 158 additions and 25 deletions

View File

@ -21,6 +21,28 @@
"path" : "Models/foliage/flowers/Flower_3_Group.gltf"
}
}
},
{
"id" : "mushroom1",
"tokens" : [
"FLAMMABLE"
],
"hitboxes" : [
{
"type": "hurt",
"offset": [0, 0.6, 0],
"radius": 0.35
}
],
"healthSystem" : {
"maxHealth" : 5,
"onDamageIFrames" : 0
},
"graphicsTemplate": {
"model": {
"path" : "Models/foliage/mushroom1.glb"
}
}
}
],
"files" : [

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

View File

@ -1599,6 +1599,7 @@ Refactor ProceduralChunkGenerator
NoiseVoxelGen work to make elevation values align with voxel values that are generated
Non-procedural voxel generation fix
Flower foliage item
Texture loading from model files (ie can load texture path from model file)
@ -1725,9 +1726,6 @@ Light Manager
- Eventually support spot lights?
- Point shadows ???
gltf Support
- Texture loading from gltf file
Security
- FileUtils sanitation function check if requested file is in game root dir

View File

@ -125,7 +125,8 @@ public class AssetManager {
Globals.profiler.beginCpuSample("AssetManager.loadAssetsInQueue - Load textures");
for(String currentPath : texturesInQueue){
texturesInQueue.remove(currentPath);
texturesLoadedIntoMemory.put(currentPath, new Texture(Globals.renderingEngine.getOpenGLState(), currentPath));
Texture tex = new Texture(Globals.renderingEngine.getOpenGLState(), currentPath);
texturesLoadedIntoMemory.put(currentPath, tex);
}
Globals.profiler.endCpuSample();
//audio from disk

View File

@ -1,14 +1,26 @@
package electrosphere.renderer.model;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.texture.Texture;
import electrosphere.util.FileUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.assimp.AIMaterial;
import org.lwjgl.assimp.AIScene;
import org.lwjgl.assimp.AIString;
import org.lwjgl.assimp.AITexture;
import org.lwjgl.assimp.Assimp;
import org.lwjgl.opengl.GL40;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import java.io.File;
import java.nio.IntBuffer;
import java.nio.file.Path;
/**
* A material
*/
@ -31,7 +43,6 @@ public class Material {
* A material that contains textures
*/
public Material(){
}
/**
@ -42,21 +53,104 @@ public class Material {
this.diffuse = diffuse;
}
//basically useless because blender doesn't support exporting mats with fbx
public static Material load_material_from_aimaterial(AIMaterial input){
/**
* Loads materials from the ai material object
* @param path The path to the file we're loading materials from
* @param input The input scene
* @param input The input ai material
* @return The resulting engine material
*/
public static Material load_material_from_aimaterial(String path, AIScene scene, AIMaterial input){
Material rVal = new Material();
// if(input.mNumProperties() > 0){
// PointerBuffer property_buffer = input.mProperties();
// while(property_buffer.hasRemaining()){
// AIMaterialProperty new_property = AIMaterialProperty.create(property_buffer.get());
// // System.out.println("Property: " + new_property.mKey().dataString());
// }
// }
AIString aiPathString = AIString.calloc();
//read props
//read textures
PointerBuffer texturePtrBuff = scene.mTextures();
String[] texPaths = new String[scene.mNumTextures()];
for(int i = 0; i < scene.mNumTextures(); i++){
AITexture tex = AITexture.create(texturePtrBuff.get());
texPaths[i] = tex.mFilename().dataString();
}
//discover diffuse
int textureCount = Assimp.aiGetMaterialTextureCount(input, Assimp.aiTextureType_DIFFUSE);
if(textureCount > 0){
//for the time being, only load the first diffuse
int textureIndex = 0;
int retCode = Assimp.aiGetMaterialTexture(input, Assimp.aiTextureType_DIFFUSE, textureIndex, aiPathString, (IntBuffer)null, null, null, null, null, null);
if(retCode != Assimp.aiReturn_SUCCESS){
throw new Error("Failed to read diffuse! " + textureCount + " " + Assimp.aiGetErrorString());
}
String texturePath = aiPathString.dataString();
if(texturePath == null || texturePath.length() <= 0){
throw new Error("Texture path is empty " + texturePath);
}
if(texturePath.length() == 2 && texturePath.startsWith("*")){
//older versions of Assimp require you to read the INDEX of the texture from the material, then look up that texture in the scene itself
//format looks like "*<index>" ie "*0"
int indexInLoadedTexturePaths = Integer.parseInt(texturePath.substring(1));
if(indexInLoadedTexturePaths >= texPaths.length){
throw new Error("Index discovered is outside the array's length " + indexInLoadedTexturePaths + " " + texPaths.length);
}
String resolved = Material.resolveTexturePath(path, texPaths[indexInLoadedTexturePaths]);
if(resolved != null && resolved.length() > 0){
rVal.usesFetch = true;
rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
}
} else {
throw new Error("Probably got an actual texture path, haven't written code to handle this.. " + texturePath);
}
}
//free mem
aiPathString.free();
return rVal;
}
/**
* Resolves the filepath of the texture
* @param path The path of the ai scene itself
* @param filename The name of the file
* @return The full path to load
*/
private static String resolveTexturePath(String path, String filename){
File fileObj = FileUtils.getAssetFile(path);
File parentDir = fileObj.getParentFile();
File[] contents = parentDir.listFiles();
File discovered = null;
for(File child : contents){
String name = child.getName();
String nameNoExt = child.getName().replaceFirst("[.][^.]+$", "");
if(name.equals(filename) || nameNoExt.equals(filename)){
discovered = child;
}
}
if(discovered == null){
LoggerInterface.loggerRenderer.WARNING("Failed to find texture " + filename + " for model " + path);
return null;
} else {
Path relative = new File("./assets").toPath().relativize(discovered.toPath());
return relative.toString().replace("\\","/");
}
}
/**
* Gets the path for the diffuse of the material
* @return The path for the diffuse texture
*/
public String get_diffuse(){
return diffuse;
}
/**
* Gets the path for the specular of the material
* @return The path for the specular texture
*/
public String get_specular(){
return specular;
}

View File

@ -101,6 +101,19 @@ public class Model {
if(modelMetadata != null){
globalTransform = modelMetadata.getGlobalTransform();
}
//
//Load materials
//
if(scene.mNumMaterials() > 0){
rVal.materials = new ArrayList<Material>();
PointerBuffer material_buffer = scene.mMaterials();
while(material_buffer.hasRemaining()){
rVal.materials.add(Material.load_material_from_aimaterial(path,scene,AIMaterial.create(material_buffer.get())));
}
}
//
//load meshes
@ -120,6 +133,16 @@ public class Model {
if(currentMesh.getBoundingSphere().r > rVal.boundingSphere.r){
rVal.boundingSphere.r = currentMesh.getBoundingSphere().r;
}
//conditionally add material
int materialIndex = aiMesh.mMaterialIndex();
if(materialIndex < rVal.materials.size()){
Material mat = rVal.materials.get(materialIndex);
//only assign if the diffuse is actually set (ie we've actually loaded it properly)
if(mat.get_diffuse() != null){
currentMesh.setMaterial(rVal.materials.get(materialIndex));
}
}
}
//
@ -196,17 +219,6 @@ public class Model {
rVal.animMap.put(newAnim.name,newAnim);
}
//
//Load materials
//
if(scene.mNumMaterials() > 0){
rVal.materials = new ArrayList<Material>();
PointerBuffer material_buffer = scene.mMaterials();
while(material_buffer.hasRemaining()){
rVal.materials.add(Material.load_material_from_aimaterial(AIMaterial.create(material_buffer.get())));
}
}
return rVal;
}

View File

@ -232,6 +232,12 @@ public class Texture {
*/
public Texture(OpenGLState openGlState, String path){
LoggerInterface.loggerRenderer.DEBUG("Create texture " + path);
if(path == null){
throw new Error("Path is null");
}
if(path.length() == 0){
throw new Error("Path is empty");
}
this.path = path;
if(!Globals.HEADLESS){
LoggerInterface.loggerRenderer.DEBUG("Setup texture object");