diff --git a/assets/Shaders/terrain2/terrain2.fs b/assets/Shaders/terrain2/terrain2.fs new file mode 100644 index 00000000..1e59f1a4 --- /dev/null +++ b/assets/Shaders/terrain2/terrain2.fs @@ -0,0 +1,208 @@ +#version 330 core + +#define NR_POINT_LIGHTS 10 + +out vec4 FragColor; + + +layout (std140) uniform Lights { + // this is how many because we have to align + // bytes it SHOULD in multiples of 16, this + // take it where it ACTUALLY is + // + //refer: https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL + // + // base alignment aligned offset + //direct light + vec3 dLDirection; // 16 0 + vec3 dLAmbient; // 16 16 + vec3 dLDiffuse; // 16 32 + vec3 dLSpecular; // 16 48 + + //point light + vec3 pLposition[NR_POINT_LIGHTS]; // 16*10 64 + float pLconstant[NR_POINT_LIGHTS]; // 16*10 224 + float pLlinear[NR_POINT_LIGHTS]; // 16*10 384 + float pLquadratic[NR_POINT_LIGHTS]; // 16*10 544 + vec3 pLambient[NR_POINT_LIGHTS]; // 16*10 704 + vec3 pLdiffuse[NR_POINT_LIGHTS]; // 16*10 864 + vec3 pLspecular[NR_POINT_LIGHTS]; // 16*10 1024 + + //for a total size of 1184 + +}; + +struct Material { + sampler2D diffuse; + sampler2D specular; + float shininess; +}; + +in vec3 FragPos; +in vec3 Normal; +in vec2 texPlane1; +in vec2 texPlane2; +in vec2 texPlane3; +in vec4 FragPosLightSpace; + + +uniform vec3 viewPos; +// uniform DirLight dirLight; +// uniform PointLight pointLights[NR_POINT_LIGHTS]; +// uniform SpotLight spotLight; +uniform Material material; + +//texture stuff +// uniform sampler2D ourTexture; +uniform int hasTransparency; +// uniform sampler2D specularTexture; + +//light depth map +uniform sampler2D shadowMap; + + +// function prototypes +// vec3 CalcDirLight(vec3 normal, vec3 viewDir); +// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir); +// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir); +float calcLightIntensityTotal(vec3 normal); +float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal); +vec3 getColor(vec2 texPlane1, vec2 texPlane2, vec2 texPlane3, vec3 normal, Material material); + +void main(){ + vec3 norm = normalize(Normal); + vec3 viewDir = normalize(viewPos - FragPos); + + //grab light intensity + float lightIntensity = calcLightIntensityTotal(norm); + + //get color of base texture + vec3 textureColor = getColor(texPlane1, texPlane2, texPlane3, norm, material); + + //shadow + float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm); + + //calculate final color + vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4); + // vec3 lightAmount = CalcDirLight(norm, viewDir); + // for(int i = 0; i < NR_POINT_LIGHTS; i++){ + // lightAmount += CalcPointLight(i, norm, FragPos, viewDir); + // } + + //this final calculation is for transparency + FragColor = vec4(finalColor, 1); +} + + +vec3 getColor(vec2 texPlane1, vec2 texPlane2, vec2 texPlane3, vec3 normal, Material material){ + + vec3 weights = abs(normal); + + vec3 albedoX = texture(material.diffuse, texPlane1).rgb; + vec3 albedoY = texture(material.diffuse, texPlane2).rgb; + vec3 albedoZ = texture(material.diffuse, texPlane3).rgb; + + + return (albedoX * weights.x + albedoY * weights.y + albedoZ * weights.z); +} + +// +float calcLightIntensityAmbient(){ + //calculate average of ambient light + float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0; + return avg; +} + +// +float calcLightIntensityDir(vec3 normal){ + vec3 lightDir = normalize(-dLDirection); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + + return diff; +} + +// +float calcLightIntensityTotal(vec3 normal){ + //ambient intensity + float ambientLightIntensity = calcLightIntensityAmbient(); + + //get direct intensity + float directLightIntensity = calcLightIntensityDir(normal); + + //sum + float total = ambientLightIntensity + directLightIntensity; + return total; +} + +// +vec3 getTotalLightColor(vec3 normal){ + //get the direct light color adjusted for intensity + vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal); + + //sum light colors + vec3 totalLightColor = diffuseLightColor; + return totalLightColor; +} + +vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){ + vec3 lightDir = normalize(pLposition[i] - fragPos); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + // vec3 reflectDir = reflect(-lightDir, normal); + // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // attenuation + float distance = length(pLposition[i] - fragPos); + float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance)); + // combine results + vec3 ambient = pLambient[i]; + vec3 diffuse = pLdiffuse[i] * diff; + ambient *= attenuation; + diffuse *= attenuation; + // specular *= attenuation; + vec3 specular = vec3(0,0,0); + + vec3 finalValue = (ambient + diffuse + specular); + finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0)); + + return finalValue; +} + + +float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){ + + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + + //transform to NDC + projCoords = projCoords * 0.5 + 0.5; + + //get closest depth from light's POV + float closestDepth = texture(shadowMap, projCoords.xy).r; + + //get depth of current fragment + float currentDepth = projCoords.z; + + //calculate bias + float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); + + //calculate shadow value + float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; + + if(projCoords.z > 1.0){ + shadow = 0.0; + } + + //calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping + //ie the fragment is already facing away from the light source + float dotprod = dot(normalize(lightDir),normalize(normal)); + + if(dotprod > 0.0){ + shadow = 0.0; + } + + // shadow = currentDepth; + + return shadow; +} \ No newline at end of file diff --git a/assets/Shaders/terrain2/terrain2.vs b/assets/Shaders/terrain2/terrain2.vs new file mode 100644 index 00000000..25f6219c --- /dev/null +++ b/assets/Shaders/terrain2/terrain2.vs @@ -0,0 +1,62 @@ +//Vertex Shader +#version 330 core + +//defines +#define TEXTURE_MAP_SCALE 3.0 + + +//input buffers +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 4) in vec2 aTex; + + +//coordinate space transformation matrices +uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; +uniform mat4 lightSpaceMatrix; + + + +//output buffers +out vec3 Normal; +out vec3 FragPos; +out vec2 texPlane1; +out vec2 texPlane2; +out vec2 texPlane3; +out vec4 FragPosLightSpace; + + + + +void main() { + //normalize posiiton and normal + vec4 FinalVertex = vec4(aPos, 1.0); + vec4 FinalNormal = vec4(aNormal, 1.0); + + + //push frag, normal, and texture positions to fragment shader + FragPos = vec3(model * FinalVertex); + Normal = mat3(transpose(inverse(model))) * aNormal; + + //reference https://catlikecoding.com/unity/tutorials/advanced-rendering/triplanar-mapping/ + texPlane1 = aPos.zy * TEXTURE_MAP_SCALE; + texPlane2 = aPos.xz * TEXTURE_MAP_SCALE; + texPlane3 = aPos.xy * TEXTURE_MAP_SCALE; + + //flip first coordinate if the normal is negative + //this minimizes texture flipping + texPlane1.x = texPlane1.x * sign(Normal.x); + texPlane2.x = texPlane2.x * sign(Normal.y); + texPlane3.x = texPlane3.x * sign(Normal.z); + + + //shadow map stuff + FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0); + + + //set final position with opengl space + gl_Position = projection * view * model * FinalVertex; +} diff --git a/assets/Textures/leavesStylized1.png b/assets/Textures/leavesStylized1.png new file mode 100644 index 00000000..d2d9589e Binary files /dev/null and b/assets/Textures/leavesStylized1.png differ diff --git a/src/main/java/electrosphere/engine/Globals.java b/src/main/java/electrosphere/engine/Globals.java index 82c48a7e..a173e96e 100644 --- a/src/main/java/electrosphere/engine/Globals.java +++ b/src/main/java/electrosphere/engine/Globals.java @@ -45,6 +45,8 @@ import electrosphere.renderer.ShaderProgram; import electrosphere.renderer.light.PointLight; import electrosphere.renderer.light.SpotLight; import electrosphere.renderer.loading.ModelPretransforms; +import electrosphere.renderer.meshgen.TerrainChunkModelGeneration; +import electrosphere.renderer.meshgen.TreeModelGeneration; import electrosphere.renderer.shader.ShaderOptionMap; import electrosphere.renderer.texture.TextureMap; import electrosphere.renderer.ui.ElementManager; @@ -408,8 +410,11 @@ public class Globals { defaultMeshShader = ShaderProgram.smart_assemble_shader(false,true); //init terrain shader program terrainShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain/terrain.vs", "/Shaders/terrain/terrain.fs"); + TerrainChunkModelGeneration.terrainChunkShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain2/terrain2.vs", "/Shaders/terrain2/terrain2.fs"); //init skybox assetManager.registerModelToSpecificString(RenderUtils.createSkyboxModel(null), AssetDataStrings.ASSET_STRING_SKYBOX_BASIC); + //init leaves + assetManager.registerModelToSpecificString(TreeModelGeneration.generateLeavesModel(), AssetDataStrings.LEAVES_MODEL); //init models assetManager.addModelPathToQueue("Models/unitsphere.fbx"); assetManager.addModelPathToQueue("Models/unitsphere_1.fbx"); diff --git a/src/main/java/electrosphere/engine/LoadingThread.java b/src/main/java/electrosphere/engine/LoadingThread.java index 429924f8..d58379c3 100644 --- a/src/main/java/electrosphere/engine/LoadingThread.java +++ b/src/main/java/electrosphere/engine/LoadingThread.java @@ -13,6 +13,7 @@ import org.joml.Vector3f; import electrosphere.auth.AuthenticationManager; import electrosphere.controls.ControlHandler; +import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.Scene; @@ -44,6 +45,8 @@ import electrosphere.net.NetUtils; import electrosphere.net.client.ClientNetworking; import electrosphere.net.server.Server; import electrosphere.net.server.player.Player; +import electrosphere.renderer.Model; +import electrosphere.renderer.meshgen.TreeModelGeneration; import electrosphere.renderer.ui.Window; import electrosphere.server.ai.creature.adventurer.SeekTown; import electrosphere.server.datacell.DataCellManager; @@ -775,12 +778,17 @@ public class LoadingThread extends Thread { // myCube.putData(EntityDataStrings.DRAW_TRANSPARENT_PASS, true); // EntityUtils.getPosition(myCube).set(3,1,3); - SceneLoader loader = new SceneLoader(); - loader.serverInstantiateSceneFile("Scenes/testscene1/testscene1.json"); + // SceneLoader loader = new SceneLoader(); + // loader.serverInstantiateSceneFile("Scenes/testscene1/testscene1.json"); Entity chunk = TerrainChunk.createTerrainChunkEntity(); + Entity leaves = EntityUtils.spawnDrawableEntity(AssetDataStrings.LEAVES_MODEL); + EntityUtils.repositionEntity(leaves, new Vector3d(1,0,1)); + leaves.putData(EntityDataStrings.DRAW_SOLID_PASS, true); + leaves.putData(EntityDataStrings.DRAW_TRANSPARENT_PASS, true); + // Globals.entityManager.registerBehaviorTree(new BehaviorTree() { // int i = 0; // public void simulate(){ diff --git a/src/main/java/electrosphere/engine/assetmanager/AssetDataStrings.java b/src/main/java/electrosphere/engine/assetmanager/AssetDataStrings.java index f7a458d9..4bb302f3 100644 --- a/src/main/java/electrosphere/engine/assetmanager/AssetDataStrings.java +++ b/src/main/java/electrosphere/engine/assetmanager/AssetDataStrings.java @@ -8,4 +8,5 @@ public class AssetDataStrings { public static final String ASSET_STRING_BITMAP_FONT_MESH_NAME = "quad"; public static final String ASSET_STRING_SKYBOX_BASIC = "skyboxBasic"; public static final String BITMAP_CHARACTER_MODEL = "bitmapCharacterModel"; + public static final String LEAVES_MODEL = "leaves"; } diff --git a/src/main/java/electrosphere/entity/types/terrain/TerrainChunk.java b/src/main/java/electrosphere/entity/types/terrain/TerrainChunk.java index a778c3f9..24cecd13 100644 --- a/src/main/java/electrosphere/entity/types/terrain/TerrainChunk.java +++ b/src/main/java/electrosphere/entity/types/terrain/TerrainChunk.java @@ -5,6 +5,7 @@ import org.joml.Vector3f; import electrosphere.engine.Globals; import electrosphere.entity.Entity; +import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.game.client.terrain.manager.ClientTerrainManager; import electrosphere.game.collision.PhysicsUtils; @@ -20,9 +21,9 @@ public class TerrainChunk { //plane 1 { //row 1 - {-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,}, + {1.0f,1.0f,-1.0f,-1.0f,-1.0f,}, //row 2 - {-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,}, + {-1.0f,1.0f,-1.0f,-1.0f,-1.0f,}, //row 3 {-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,}, //row 4 @@ -158,6 +159,8 @@ public class TerrainChunk { Entity rVal = EntityUtils.spawnDrawableEntityWithPreexistingModel(modelPath); PhysicsUtils.attachTerrainChunkRigidBody(rVal, data); + rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true); + EntityUtils.repositionEntity(rVal, new Vector3d(1,-1,1)); return rVal; diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index 18af5670..791dc052 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -1356,7 +1356,7 @@ public class RenderingEngine { public static void incrementOutputFramebuffer(){ outputFramebuffer++; - if(outputFramebuffer > 7){ + if(outputFramebuffer > 8){ outputFramebuffer = 0; } } diff --git a/src/main/java/electrosphere/renderer/meshgen/TerrainChunkModelGeneration.java b/src/main/java/electrosphere/renderer/meshgen/TerrainChunkModelGeneration.java index bdff47c6..c2625c1e 100644 --- a/src/main/java/electrosphere/renderer/meshgen/TerrainChunkModelGeneration.java +++ b/src/main/java/electrosphere/renderer/meshgen/TerrainChunkModelGeneration.java @@ -8,9 +8,9 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.vecmath.Vector2f; import org.joml.Matrix4f; +import org.joml.Vector2f; import org.joml.Vector3f; import org.lwjgl.BufferUtils; @@ -24,6 +24,7 @@ import electrosphere.entity.types.terrain.TerrainChunkData; import electrosphere.renderer.Material; import electrosphere.renderer.Mesh; import electrosphere.renderer.Model; +import electrosphere.renderer.ShaderProgram; public class TerrainChunkModelGeneration { @@ -365,6 +366,26 @@ public class TerrainChunkModelGeneration { } } + + + + + + + public static ShaderProgram terrainChunkShaderProgram = null; + + + + + + + + + + + + + protected static int polygonize( GridCell grid, double isolevel, @@ -618,20 +639,33 @@ public class TerrainChunkModelGeneration { } float[] temp = new float[3]; + int i = 0; for(Vector3f normal : normals){ + Vector3f vert = verts.get(i); + float absX = Math.abs(normal.x); float absY = Math.abs(normal.y); float absZ = Math.abs(normal.z); - if(absX >= absZ && absX >= absY){ - temp[0] = normal.z / 2.0f + 0.5f; - temp[1] = normal.y / 2.0f + 0.5f; - } else if(absZ >= absX && absZ >= absY){ - temp[0] = normal.x / 2.0f + 0.5f; - temp[1] = normal.y / 2.0f + 0.5f; - } else if(absY >= absX && absY >= absZ){ - temp[0] = normal.x / 2.0f + 0.5f; - temp[1] = normal.z / 2.0f + 0.5f; - } + + float uvX = vert.z * absX + vert.x * absY + vert.x * absZ; + float uvY = vert.y * absX + vert.z * absY + vert.y * absZ; + temp[0] = uvX; + temp[1] = uvY; + + // if(absX >= absZ && absX >= absY){ + // temp[0] = normal.z / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ)); + // temp[1] = normal.y / 2.0f + 0.5f + vert.x * (absY / (absX + absY)) + vert.y * (absX / (absX + absY)); + // } else if(absZ >= absX && absZ >= absY){ + // temp[0] = normal.x / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ)); + // temp[1] = normal.y / 2.0f + 0.5f + vert.z * (absY / (absZ + absY)) + vert.y * (absZ / (absZ + absY)); + // } else if(absY >= absX && absY >= absZ){ + // temp[0] = normal.x / 2.0f + 0.5f + vert.y * (absX / (absX + absY)) + vert.x * (absY / (absX + absY)); + // temp[1] = normal.z / 2.0f + 0.5f + vert.y * (absZ / (absZ + absY)) + vert.z * (absY / (absZ + absY)); + // } else { + // temp[0] = vert.x / 1.5f + vert.z / 1.5f; + // temp[1] = vert.y / 1.5f + vert.z / 1.5f; + // } + i++; UVs.add(temp[0]); UVs.add(temp[1]); } @@ -758,7 +792,7 @@ public class TerrainChunkModelGeneration { groundMat.set_specular("/Textures/Ground/Dirt1.png"); m.setMaterial(groundMat); - m.setShader(Globals.defaultMeshShader); + m.setShader(TerrainChunkModelGeneration.terrainChunkShaderProgram); m.parent = rVal; rVal.meshes.add(m); diff --git a/src/main/java/electrosphere/renderer/meshgen/TreeModelGeneration.java b/src/main/java/electrosphere/renderer/meshgen/TreeModelGeneration.java new file mode 100644 index 00000000..76c5589f --- /dev/null +++ b/src/main/java/electrosphere/renderer/meshgen/TreeModelGeneration.java @@ -0,0 +1,194 @@ +package electrosphere.renderer.meshgen; + +import electrosphere.engine.Globals; +import electrosphere.renderer.Material; +import electrosphere.renderer.Mesh; +import electrosphere.renderer.Model; + +import static org.lwjgl.opengl.GL30.glBindVertexArray; +import static org.lwjgl.opengl.GL30.glGenVertexArrays; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; + +import org.lwjgl.BufferUtils; + +public class TreeModelGeneration { + + protected static Mesh generateLeafMesh(){ + + Mesh mesh = new Mesh(); + + + mesh.mesh = null; + + // + // VAO + // + mesh.vertexArrayObject = glGenVertexArrays(); + glBindVertexArray(mesh.vertexArrayObject); + + + + float[] vertices = new float[]{ + 0.5f, 0.5f, 0, + 0.5f, -0.5f, 0, + -0.5f, -0.5f, 0, + -0.5f, 0.5f, 0, + + + 0, 0.5f, 0.5f, + 0, -0.5f, 0.5f, + 0, -0.5f, -0.5f, + 0, 0.5f, -0.5f, + + + 0.5f, 0, 0.5f, + 0.5f, 0, -0.5f, + -0.5f, 0, -0.5f, + -0.5f, 0, 0.5f + }; + + float[] normals = new float[]{ + 0.707f, 0.707f, 0, + 0.707f, -0.707f, 0, + -0.707f, -0.707f, 0, + -0.707f, 0.707f, 0, + + 0, 0.707f, 0.707f, + 0, -0.707f, 0.707f, + 0, -0.707f, -0.707f, + 0, 0.707f, -0.707f, + + 0.707f, 0, 0.707f, + 0.707f, 0, -0.707f, + -0.707f, 0, -0.707f, + -0.707f, 0, 0.707f, + }; + + int[] elements = new int[]{ + 0, 1, 2, + 0, 2, 3, + 4, 5, 6, + 4, 6, 7, + 8, 9, 10, + 8, 10, 11 + }; + + float[] uvs = new float[]{ + 1, 1, + 1, 0, + 0, 0, + 0, 1, + + 1, 1, + 0, 1, + 0, 0, + 1, 0, + + 1, 1, + 1, 0, + 0, 0, + 0, 1, + }; + + + + + // + //Buffer data to GPU + // + + try { + mesh.vertexCount = vertices.length / 3; + FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(mesh.vertexCount * 3); + VertexArrayBufferData.put(vertices); + VertexArrayBufferData.flip(); + mesh.buffer_vertices(VertexArrayBufferData, 3); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + + + // + // FACES + // + mesh.faceCount = elements.length / 3; + mesh.elementCount = elements.length; + try { + IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(mesh.elementCount); + elementArrayBufferData.put(elements); + elementArrayBufferData.flip(); + mesh.buffer_faces(elementArrayBufferData); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + + + + // + // NORMALS + // + try { + mesh.normalCount = normals.length / 3; + FloatBuffer NormalArrayBufferData; + if(mesh.normalCount > 0){ + NormalArrayBufferData = BufferUtils.createFloatBuffer(mesh.normalCount * 3); + NormalArrayBufferData.put(normals); + NormalArrayBufferData.flip(); + mesh.buffer_normals(NormalArrayBufferData, 3); + } + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + // + // TEXTURE COORDINATES + // + try { + mesh.textureCoordCount = uvs.length / 2; + FloatBuffer TextureArrayBufferData; + if(mesh.textureCoordCount > 0){ + TextureArrayBufferData = BufferUtils.createFloatBuffer(mesh.textureCoordCount * 2); + TextureArrayBufferData.put(uvs); + TextureArrayBufferData.flip(); + mesh.buffer_texture_coords(TextureArrayBufferData, 2); + } + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + + + + glBindVertexArray(0); + mesh.nodeID = "leaves"; + return mesh; + } + + + + public static Model generateLeavesModel(){ + Model rVal = new Model(); + rVal.meshes = new ArrayList(); + Mesh m = generateLeafMesh(); + + + Material groundMat = new Material(); + groundMat.set_diffuse("/Textures/leavesStylized1.png"); + groundMat.set_specular("/Textures/leavesStylized1.png"); + Globals.assetManager.addTexturePathtoQueue("/Textures/leavesStylized1.png"); + m.setMaterial(groundMat); + + m.setShader(Globals.defaultMeshShader); + m.parent = rVal; + + rVal.meshes.add(m); + + return rVal; + } + +}