tree model debug menu
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-09-23 00:26:01 -04:00
parent cd0452a77c
commit 63f0f3338c
18 changed files with 879 additions and 304 deletions

View File

@ -29,49 +29,6 @@
"growthModel": {
"growthRate" : 0.001
},
"treeModel": {
"limbScalarFalloffFactor": 0.3,
"minimumLimbScalar": 0.25,
"maximumLimbDispersion": 0.5,
"minimumLimbDispersion": 0.3,
"minimumNumberForks": 3,
"maximumNumberForks": 5,
"branchHeight": 3,
"centralTrunk": false,
"maximumTrunkSegments": 4,
"maximumBranchSegments": 3,
"maxBranchSegmentFalloffFactor": 1,
"minimumSegmentToSpawnLeaves": 2,
"minBranchHeightToStartSpawningLeaves": 1.5,
"maxBranchHeightToStartSpawningLeaves": 3.01,
"leafIncrement": 0.5,
"minLeavesToSpawnPerPoint": 3,
"maxLeavesToSpawnPerPoint": 5,
"leafDistanceFromCenter": 1.2,
"peelVariance": 0.2,
"peelMinimum": 0.1,
"swaySigmoidFactor": 2,
"minimumSwayTime": 500,
"swayTimeVariance": 500,
"yawVariance": 0.2,
"yawMinimum": 0.1,
"minimumScalarToGenerateSwayTree": 0.5,
"maximumScalarToGenerateSwayTree": 1.0,
"physicsCutoff": 3,
"physicsBody": {
"type" : "CYLINDER",
"dimension1" : 0.5,
"dimension2" : 3,
"dimension3" : 0.5,
"rotX": 0,
"rotY": 0,
"rotZ": 0,
"rotW": 1,
"offsetX" : 0,
"offsetY" : 1.5,
"offsetZ" : 0
}
},
"ambientAudio": {
"responseWindAudioFilePath": "Audio/ambienceWind1SeamlessMono.ogg",
"responseWindLoops": true,
@ -79,7 +36,53 @@
"gainMultiplier": 0.9,
"emitterSpatialOffset": [0,3,0]
},
"modelPath" : "Models/foliage/proceduralTree2/proceduralTree2v2.fbx"
"graphicsTemplate": {
"proceduralModel": {
"treeModel": {
"limbScalarFalloffFactor": 0.3,
"minimumLimbScalar": 0.25,
"maximumLimbDispersion": 0.5,
"minimumLimbDispersion": 0.3,
"minimumNumberForks": 3,
"maximumNumberForks": 5,
"branchHeight": 3,
"centralTrunk": false,
"maximumTrunkSegments": 4,
"maximumBranchSegments": 3,
"maxBranchSegmentFalloffFactor": 1,
"minimumSegmentToSpawnLeaves": 2,
"minBranchHeightToStartSpawningLeaves": 1.5,
"maxBranchHeightToStartSpawningLeaves": 3.01,
"leafIncrement": 0.5,
"minLeavesToSpawnPerPoint": 3,
"maxLeavesToSpawnPerPoint": 5,
"leafDistanceFromCenter": 1.2,
"peelVariance": 0.2,
"peelMinimum": 0.1,
"swaySigmoidFactor": 2,
"minimumSwayTime": 500,
"swayTimeVariance": 500,
"yawVariance": 0.2,
"yawMinimum": 0.1,
"minimumScalarToGenerateSwayTree": 0.5,
"maximumScalarToGenerateSwayTree": 1.0,
"physicsCutoff": 3,
"physicsBody": {
"type" : "CYLINDER",
"dimension1" : 0.5,
"dimension2" : 3,
"dimension3" : 0.5,
"rotX": 0,
"rotY": 0,
"rotZ": 0,
"rotW": 1,
"offsetX" : 0,
"offsetY" : 1.5,
"offsetZ" : 0
}
}
}
}
}
]

View File

@ -1,39 +1,73 @@
#version 330 core
#version 450 core
//colorshift.fs
#define NR_POINT_LIGHTS 10
/**
Bind points for different SSBOs
*/
#define CLUSTER_SSBO_BIND_POINT 1
#define POINT_LIGHT_SSBO_BIND_POINT 2
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
#define SMALL_EPSILON 0.0001
/**
Maximum number of point lights
*/
#define MAX_POINT_LIGHTS 512
/**
Maximum number of lights per cluster
*/
#define MAX_LIGHTS_PER_CLUSTER 100
/**
transparency
*/
#define SMALL_EPSILON 0.001
/**
The direct global light
*/
struct DirectLight {
vec3 direction;
vec3 color;
};
/**
A point light
*/
struct PointLight {
vec4 position;
vec4 color;
float constant;
float linear;
float quadratic;
float radius;
};
/**
A light cluster
*/
struct Cluster {
vec4 minPoint;
vec4 maxPoint;
uint count;
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
};
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
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
Cluster clusters[];
};
//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
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
PointLight pointLight[];
};
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
DirectLight directLight;
};
struct Material {
@ -43,6 +77,7 @@ struct Material {
};
in vec3 FragPos;
in vec3 ViewFragPos;
in vec3 Normal;
in vec2 TexCoord;
in vec4 FragPosLightSpace;
@ -63,11 +98,19 @@ uniform int hasTransparency;
//light depth map
uniform sampler2D shadowMap;
/**
Used for light cluster calculation
*/
uniform float zNear;
uniform float zFar;
uniform uvec3 gridSize;
uniform uvec2 screenDimensions;
uniform mat4 view;
// 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);
uint findCluster(vec3 FragPos, float zNear, float zFar);
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
float calcLightIntensityTotal(vec3 normal);
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
@ -77,7 +120,7 @@ void main(){
vec3 viewDir = normalize(viewPos - FragPos);
//grab light intensity
float lightIntensity = calcLightIntensityTotal(norm);
vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
if(texture(material.diffuse, TexCoord).a < SMALL_EPSILON){
discard;
@ -92,10 +135,25 @@ void main(){
);
//shadow
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm);
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
//
//point light calculations
uint clusterIndex = findCluster(ViewFragPos, zNear, zFar);
uint pointLightCount = clusters[clusterIndex].count;
for(int i = 0; i < pointLightCount; i++){
uint pointLightIndex = clusters[clusterIndex].lightIndices[i];
PointLight pointLight = pointLight[pointLightIndex];
lightIntensity = lightIntensity + CalcPointLight(pointLight, norm, FragPos, viewDir);
}
//error checking on light clusters
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
FragColor = vec4(1.0f,0.0f,0.0f,1);
return;
}
//calculate final color
vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4);
vec3 finalColor = textureColor * lightIntensity;
// vec3 lightAmount = CalcDirLight(norm, viewDir);
// for(int i = 0; i < NR_POINT_LIGHTS; i++){
// lightAmount += CalcPointLight(i, norm, FragPos, viewDir);
@ -127,13 +185,13 @@ void main(){
//
float calcLightIntensityAmbient(){
//calculate average of ambient light
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0;
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
return avg;
}
//
float calcLightIntensityDir(vec3 normal){
vec3 lightDir = normalize(-dLDirection);
vec3 lightDir = normalize(-directLight.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
@ -156,63 +214,53 @@ float calcLightIntensityTotal(vec3 normal){
//
vec3 getTotalLightColor(vec3 normal){
//get the direct light color adjusted for intensity
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal);
vec3 diffuseLightColor = directLight.color * 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);
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
vec3 lightDir = normalize(pointLight.position.xyz - 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));
float distance = length(pointLight.position.xyz - fragPos);
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
if(distance > pointLight.radius){
attenuation = 0;
}
// combine results
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
ambient *= attenuation;
diffuse *= attenuation;
ambient = ambient * attenuation;
diffuse = 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));
vec3 finalValue = vec3(0);
if(distance < pointLight.radius){
finalValue = (ambient + diffuse + specular);
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
}
return finalValue;
}
// // calculates the color when using a point light.
// 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];// * vec4(texture(material.diffuse, TexCoord)).xyz;
// vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
// // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
// 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;
// }
/**
Finds the light cluster this fragment belongs to
*/
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
vec2 tileSize = screenDimensions / gridSize.xy;
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
}
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){

View File

@ -26,6 +26,7 @@ uniform mat4 lightSpaceMatrix;
//output buffers
out vec3 Normal;
out vec3 FragPos;
out vec3 ViewFragPos;
out vec2 TexCoord;
out vec4 FragPosLightSpace;
out vec3 colorShiftValue;
@ -49,6 +50,7 @@ void main() {
//push frag, normal, and texture positions to fragment shader
FragPos = vec3(model * FinalVertex);
ViewFragPos = vec3(view * model * FinalVertex);
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoord = aTex;

View File

@ -1,37 +1,68 @@
#version 330 core
#version 450 core
//proceduraltree.fs
#define NR_POINT_LIGHTS 10
/**
Bind points for different SSBOs
*/
#define CLUSTER_SSBO_BIND_POINT 1
#define POINT_LIGHT_SSBO_BIND_POINT 2
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
/**
Maximum number of point lights
*/
#define MAX_POINT_LIGHTS 512
/**
Maximum number of lights per cluster
*/
#define MAX_LIGHTS_PER_CLUSTER 100
/**
The direct global light
*/
struct DirectLight {
vec3 direction;
vec3 color;
};
/**
A point light
*/
struct PointLight {
vec4 position;
vec4 color;
float constant;
float linear;
float quadratic;
float radius;
};
/**
A light cluster
*/
struct Cluster {
vec4 minPoint;
vec4 maxPoint;
uint count;
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
};
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
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
Cluster clusters[];
};
//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
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
PointLight pointLight[];
};
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
DirectLight directLight;
};
struct Material {
@ -41,6 +72,7 @@ struct Material {
};
in vec3 FragPos;
in vec3 ViewFragPos;
in vec3 Normal;
in vec2 TexCoord;
in vec4 FragPosLightSpace;
@ -60,11 +92,19 @@ uniform int hasTransparency;
//light depth map
uniform sampler2D shadowMap;
/**
Used for light cluster calculation
*/
uniform float zNear;
uniform float zFar;
uniform uvec3 gridSize;
uniform uvec2 screenDimensions;
uniform mat4 view;
// 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);
uint findCluster(vec3 FragPos, float zNear, float zFar);
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
float calcLightIntensityTotal(vec3 normal);
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
@ -73,16 +113,31 @@ void main(){
vec3 viewDir = normalize(viewPos - FragPos);
//grab light intensity
float lightIntensity = calcLightIntensityTotal(norm);
vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
//get color of base texture
vec3 textureColor = texture(material.diffuse, TexCoord).rgb;
//shadow
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm);
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
//
//point light calculations
uint clusterIndex = findCluster(ViewFragPos, zNear, zFar);
uint pointLightCount = clusters[clusterIndex].count;
for(int i = 0; i < pointLightCount; i++){
uint pointLightIndex = clusters[clusterIndex].lightIndices[i];
PointLight pointLight = pointLight[pointLightIndex];
lightIntensity = lightIntensity + CalcPointLight(pointLight, norm, FragPos, viewDir);
}
//error checking on light clusters
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
FragColor = vec4(1.0f,0.0f,0.0f,1);
return;
}
//calculate final color
vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4);
vec3 finalColor = textureColor * lightIntensity;
// vec3 lightAmount = CalcDirLight(norm, viewDir);
// for(int i = 0; i < NR_POINT_LIGHTS; i++){
// lightAmount += CalcPointLight(i, norm, FragPos, viewDir);
@ -114,13 +169,13 @@ void main(){
//
float calcLightIntensityAmbient(){
//calculate average of ambient light
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0;
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
return avg;
}
//
float calcLightIntensityDir(vec3 normal){
vec3 lightDir = normalize(-dLDirection);
vec3 lightDir = normalize(-directLight.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
@ -143,63 +198,53 @@ float calcLightIntensityTotal(vec3 normal){
//
vec3 getTotalLightColor(vec3 normal){
//get the direct light color adjusted for intensity
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal);
vec3 diffuseLightColor = directLight.color * 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);
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
vec3 lightDir = normalize(pointLight.position.xyz - 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));
float distance = length(pointLight.position.xyz - fragPos);
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
if(distance > pointLight.radius){
attenuation = 0;
}
// combine results
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
ambient *= attenuation;
diffuse *= attenuation;
ambient = ambient * attenuation;
diffuse = 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));
vec3 finalValue = vec3(0);
if(distance < pointLight.radius){
finalValue = (ambient + diffuse + specular);
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
}
return finalValue;
}
// // calculates the color when using a point light.
// 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];// * vec4(texture(material.diffuse, TexCoord)).xyz;
// vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
// // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
// 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;
// }
/**
Finds the light cluster this fragment belongs to
*/
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
vec2 tileSize = screenDimensions / gridSize.xy;
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
}
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){

View File

@ -30,6 +30,7 @@ uniform mat4 lightSpaceMatrix;
//output buffers
out vec3 Normal;
out vec3 FragPos;
out vec3 ViewFragPos;
out vec2 TexCoord;
out vec4 FragPosLightSpace;
@ -61,6 +62,7 @@ void main() {
//push frag, normal, and texture positions to fragment shader
FragPos = vec3(model * FinalVertex);
ViewFragPos = vec3(view * model * FinalVertex);
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoord = aTex;

View File

@ -837,6 +837,7 @@ Fix static friction coeff causing player to slide on shallow slopes
- Turns out it needed auto disabling logic
Change timescale for test
Refactor graphics entity definitions to be under dedicated object
Tree model debug menu
# TODO

View File

@ -3,6 +3,7 @@ package electrosphere.client.ui.menu.debug;
import org.ode4j.ode.DBody;
import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.client.ui.menu.debug.entity.ImGuiEntityMacros;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;

View File

@ -3,6 +3,7 @@ package electrosphere.client.ui.menu.debug;
import java.util.HashMap;
import java.util.Map;
import electrosphere.client.ui.menu.debug.entity.ImGuiEntityMacros;
import electrosphere.controls.ControlHandler.ControlsState;
import electrosphere.engine.Globals;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot;

View File

@ -0,0 +1,135 @@
package electrosphere.client.ui.menu.debug.entity;
import java.util.Set;
import java.util.Random;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.entity.types.tree.ProceduralTree;
import electrosphere.game.data.common.CommonEntityType;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorAnimationMask;
import electrosphere.renderer.actor.ActorMeshMask;
import electrosphere.renderer.anim.AnimChannel;
import electrosphere.renderer.anim.Animation;
import electrosphere.renderer.model.Bone;
import electrosphere.renderer.model.Mesh;
import electrosphere.renderer.model.Model;
import imgui.ImGui;
/**
* The actor tab on the entity detail view
*/
public class ImGuiEntityActorTab {
/**
* Client scene entity view
*/
protected static void drawActorView(boolean show, Entity detailViewEntity){
if(show && ImGui.collapsingHeader("Actor Details")){
ImGui.indent();
if(detailViewEntity != null && EntityUtils.getActor(detailViewEntity) != null){
Actor actor = EntityUtils.getActor(detailViewEntity);
CommonEntityType commonEntityData = CommonEntityUtils.getCommonData(detailViewEntity);
//procedural model
if(commonEntityData.getGraphicsTemplate().getProceduralModel() != null && ImGui.collapsingHeader("Procedural Model")){
if(ImGui.button("Regenerate")){
if(commonEntityData.getGraphicsTemplate().getProceduralModel().getTreeModel() != null){
ProceduralTree.setProceduralActor(
detailViewEntity,
commonEntityData.getGraphicsTemplate().getProceduralModel().getTreeModel(),
new Random()
);
}
}
}
//mesh mask
if(ImGui.collapsingHeader("Mesh Mask")){
ActorMeshMask meshMask = actor.getMeshMask();
ImGui.text("To Draw Meshes:");
for(Mesh mesh : meshMask.getToDrawMeshes()){
ImGui.text(mesh.getMeshName());
}
ImGui.text("Blocked Meshes:");
for(String blocked : meshMask.getBlockedMeshes()){
ImGui.text(blocked);
}
}
//animation queue
if(ImGui.collapsingHeader("Animation Queue")){
Set<ActorAnimationMask> animationQueue = actor.getAnimationQueue();
for(ActorAnimationMask mask : animationQueue){
ImGui.text(mask.getAnimationName() + " - " + mask.getPriority());
ImGui.text(mask.getDuration() + " " + mask.getTime());
}
}
//bone values
if(ImGui.collapsingHeader("Bone Values")){
for(Bone bone : actor.getBoneValues()){
ImGui.text(bone.boneID);
ImGui.text("Position: " + actor.getBonePosition(bone.boneID));
ImGui.text("Rotation: " + actor.getBoneRotation(bone.boneID));
ImGui.text(bone.getFinalTransform() + "");
}
}
//Draws all the bones in the world
if(ImGui.button("Draw Bones")){
Globals.renderingEngine.getDebugContentPipeline().getDebugBonesPipeline().setEntity(detailViewEntity);
}
//Browsable list of all animations with their data
if(ImGui.collapsingHeader("Animation Channel Data")){
Model model = Globals.assetManager.fetchModel(actor.getModelPath());
ImGui.indent();
for(Animation animation : model.getAnimations()){
if(ImGui.collapsingHeader(animation.name)){
if(ImGui.button("Play")){
actor.playAnimation(animation.name, AnimationPriorities.getValue(AnimationPriorities.MODIFIER_MAX));
}
for(AnimChannel channel : animation.channels){
ImGui.pushID(channel.getNodeID());
if(ImGui.button("Fully describe")){
channel.fullDescribeChannel();
}
ImGui.text("=" + channel.getNodeID() + "=");
ImGui.text("" + channel.getCurrentPosition());
ImGui.text("" + channel.getCurrentRotation());
ImGui.text("" + channel.getCurrentScale());
ImGui.popID();
}
}
}
ImGui.unindent();
}
//print data macros
if(ImGui.collapsingHeader("Print Data")){
//print bone values
if(ImGui.button("Print current bone values")){
for(Bone bone : actor.getBoneValues()){
LoggerInterface.loggerRenderer.DEBUG(bone.boneID);
LoggerInterface.loggerRenderer.DEBUG("" + bone.getFinalTransform());
}
}
//print animation keys
if(ImGui.button("Print animation keys")){
Model model = Globals.assetManager.fetchModel(actor.getModelPath());
model.describeAllAnimations();
}
}
}
ImGui.unindent();
}
}
}

View File

@ -0,0 +1,253 @@
package electrosphere.client.ui.menu.debug.entity;
import java.util.Random;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.state.attach.AttachUtils;
import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.entity.types.tree.ProceduralTree;
import electrosphere.game.data.common.CommonEntityType;
import electrosphere.game.data.foliage.type.TreeModel;
import electrosphere.game.data.graphics.ProceduralModel;
import electrosphere.renderer.actor.instance.InstancedActor;
import imgui.ImGui;
/**
* The actor tab on the entity detail view
*/
public class ImGuiEntityInstancedActorTab {
/**
* Client scene entity view
*/
protected static void drawInstancedActorView(boolean show, Entity detailViewEntity){
if(show && ImGui.collapsingHeader("Instanced Actor Details")){
ImGui.indent();
float[] limbScalarFalloffFactor = new float[1];
float[] minimumLimbScalar = new float[1];
float[] maximumLimbDispersion = new float[1];
float[] minimumLimbDispersion = new float[1];
int[] minimumNumberForks = new int[1];
int[] maximumNumberForks = new int[1];
int[] maximumTrunkSegments = new int[1];
int[] maximumBranchSegments = new int[1];
float[] maxBranchSegmentFalloffFactor = new float[1];
int[] minimumSegmentToSpawnLeaves = new int[1];
float[] minBranchHeightToStartSpawningLeaves = new float[1];
float[] maxBranchHeightToStartSpawningLeaves = new float[1];
float[] leafIncrement = new float[1];
int[] minLeavesToSpawnPerPoint = new int[1];
int[] maxLeavesToSpawnPerPoint = new int[1];
float[] leafDistanceFromCenter = new float[1];
float[] peelVariance = new float[1];
float[] peelMinimum = new float[1];
float[] swaySigmoidFactor = new float[1];
int[] minimumSwayTime = new int[1];
int[] swayTimeVariance = new int[1];
float[] yawVariance = new float[1];
float[] yawMinimum = new float[1];
float[] minimumScalarToGenerateSwayTree = new float[1];
float[] maximumScalarToGenerateSwayTree = new float[1];
if(detailViewEntity != null && InstancedActor.getInstancedActor(detailViewEntity) != null){
// InstancedActor actor = InstancedActor.getInstancedActor(detailViewEntity);
CommonEntityType commonEntityData = CommonEntityUtils.getCommonData(detailViewEntity);
//procedural model
if(commonEntityData.getGraphicsTemplate().getProceduralModel() != null && ImGui.collapsingHeader("Procedural Model")){
ProceduralModel proceduralModel = commonEntityData.getGraphicsTemplate().getProceduralModel();
if(ImGui.button("Regenerate")){
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
if(proceduralModel.getTreeModel() != null && ImGui.collapsingHeader("Tree Model")){
TreeModel treeModel = proceduralModel.getTreeModel();
maximumTrunkSegments[0] = treeModel.getMaximumTrunkSegments();
if(ImGui.sliderInt("maximumTrunkSegments", maximumTrunkSegments, 1, 8)){
treeModel.setMaximumTrunkSegments(maximumTrunkSegments[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
if(ImGui.collapsingHeader("Branches")){
limbScalarFalloffFactor[0] = treeModel.getLimbScalarFalloffFactor();
if(ImGui.sliderFloat("limbScalarFalloffFactor", limbScalarFalloffFactor, 0.01f, 1f)){
treeModel.setLimbScalarFalloffFactor(limbScalarFalloffFactor[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
minimumLimbScalar[0] = treeModel.getMinimumLimbScalar();
if(ImGui.sliderFloat("minimumLimbScalar", minimumLimbScalar, 0.01f, 1f)){
treeModel.setLimbScalarFalloffFactor(minimumLimbScalar[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
maximumLimbDispersion[0] = treeModel.getMaximumLimbDispersion();
if(ImGui.sliderFloat("maximumLimbDispersion", maximumLimbDispersion, 0.01f, 1f)){
treeModel.setMaximumLimbDispersion(maximumLimbDispersion[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
minimumLimbDispersion[0] = treeModel.getMinimumLimbDispersion();
if(ImGui.sliderFloat("minimumLimbDispersion", minimumLimbDispersion, 0.01f, 1f)){
treeModel.setMinimumLimbDispersion(minimumLimbDispersion[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
minimumNumberForks[0] = treeModel.getMinimumNumberForks();
if(ImGui.sliderInt("minimumNumberForks", minimumNumberForks, 1, 8)){
treeModel.setMinimumNumberForks(minimumNumberForks[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
maximumNumberForks[0] = treeModel.getMaximumNumberForks();
if(ImGui.sliderInt("maximumNumberForks", maximumNumberForks, 1, 8)){
treeModel.setMaximumNumberForks(maximumNumberForks[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
maximumBranchSegments[0] = treeModel.getMaximumBranchSegments();
if(ImGui.sliderInt("maximumBranchSegments", maximumBranchSegments, 1, 8)){
treeModel.setMaximumBranchSegments(maximumBranchSegments[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
maxBranchSegmentFalloffFactor[0] = treeModel.getMaxBranchSegmentFalloffFactor();
if(ImGui.sliderFloat("maxBranchSegmentFalloffFactor", maxBranchSegmentFalloffFactor, 0.01f, 1f)){
treeModel.setMaxBranchSegmentFalloffFactor(maxBranchSegmentFalloffFactor[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
}
if(ImGui.collapsingHeader("Branch Sway")){
peelVariance[0] = (float)treeModel.getPeelVariance();
if(ImGui.sliderFloat("peelVariance", peelVariance, 0.01f, 3f)){
treeModel.setPeelVariance(peelVariance[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
peelMinimum[0] = (float)treeModel.getPeelMinimum();
if(ImGui.sliderFloat("peelMinimum", peelMinimum, 0.01f, 3f)){
treeModel.setPeelMinimum(peelMinimum[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
swaySigmoidFactor[0] = (float)treeModel.getSwaySigmoidFactor();
if(ImGui.sliderFloat("swaySigmoidFactor", swaySigmoidFactor, 0.01f, 3f)){
treeModel.setSwaySigmoidFactor(swaySigmoidFactor[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
minimumSwayTime[0] = treeModel.getMinimumSwayTime();
if(ImGui.sliderInt("minimumSwayTime", minimumSwayTime, 1, 1000)){
treeModel.setMinimumSwayTime(minimumSwayTime[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
swayTimeVariance[0] = treeModel.getSwayTimeVariance();
if(ImGui.sliderInt("swayTimeVariance", swayTimeVariance, 1, 1000)){
treeModel.setSwayTimeVariance(swayTimeVariance[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
yawVariance[0] = (float)treeModel.getYawVariance();
if(ImGui.sliderFloat("yawVariance", yawVariance, 0.01f, 3f)){
treeModel.setYawVariance(yawVariance[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
yawMinimum[0] = (float)treeModel.getYawMinimum();
if(ImGui.sliderFloat("yawMinimum", yawMinimum, 0.01f, 3f)){
treeModel.setYawMinimum(yawMinimum[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
minimumScalarToGenerateSwayTree[0] = (float)treeModel.getMinimumScalarToGenerateSwayTree();
if(ImGui.sliderFloat("minimumScalarToGenerateSwayTree", minimumScalarToGenerateSwayTree, 0.01f, 3f)){
treeModel.setMinimumScalarToGenerateSwayTree(minimumScalarToGenerateSwayTree[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
maximumScalarToGenerateSwayTree[0] = (float)treeModel.getMaximumScalarToGenerateSwayTree();
if(ImGui.sliderFloat("maximumScalarToGenerateSwayTree", maximumScalarToGenerateSwayTree, 0.01f, 3f)){
treeModel.setMaximumScalarToGenerateSwayTree(maximumScalarToGenerateSwayTree[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
}
if(ImGui.collapsingHeader("Leaves")){
minimumSegmentToSpawnLeaves[0] = treeModel.getMinimumSegmentToSpawnLeaves();
if(ImGui.sliderInt("minimumSegmentToSpawnLeaves", minimumSegmentToSpawnLeaves, 1, 8)){
treeModel.setMinimumSegmentToSpawnLeaves(minimumSegmentToSpawnLeaves[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
minBranchHeightToStartSpawningLeaves[0] = treeModel.getMinBranchHeightToStartSpawningLeaves();
if(ImGui.sliderFloat("minBranchHeightToStartSpawningLeaves", minBranchHeightToStartSpawningLeaves, 0.01f, 5f)){
treeModel.setMinBranchHeightToStartSpawningLeaves(minBranchHeightToStartSpawningLeaves[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
maxBranchHeightToStartSpawningLeaves[0] = treeModel.getMaxBranchHeightToStartSpawningLeaves();
if(ImGui.sliderFloat("maxBranchHeightToStartSpawningLeaves", maxBranchHeightToStartSpawningLeaves, 0.01f, 5f)){
treeModel.setMaxBranchHeightToStartSpawningLeaves(maxBranchHeightToStartSpawningLeaves[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
leafIncrement[0] = treeModel.getLeafIncrement();
if(ImGui.sliderFloat("leafIncrement", leafIncrement, 0.01f, 1f)){
treeModel.setLeafIncrement(leafIncrement[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
minLeavesToSpawnPerPoint[0] = treeModel.getMinLeavesToSpawnPerPoint();
if(ImGui.sliderInt("minLeavesToSpawnPerPoint", minLeavesToSpawnPerPoint, 1, 8)){
treeModel.setMinLeavesToSpawnPerPoint(minLeavesToSpawnPerPoint[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
maxLeavesToSpawnPerPoint[0] = treeModel.getMaxLeavesToSpawnPerPoint();
if(ImGui.sliderInt("maxLeavesToSpawnPerPoint", maxLeavesToSpawnPerPoint, 1, 8)){
treeModel.setMaxLeavesToSpawnPerPoint(maxLeavesToSpawnPerPoint[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
leafDistanceFromCenter[0] = treeModel.getLeafDistanceFromCenter();
if(ImGui.sliderFloat("leafDistanceFromCenter", leafDistanceFromCenter, 0.01f, 3f)){
treeModel.setLeafDistanceFromCenter(leafDistanceFromCenter[0]);
ImGuiEntityInstancedActorTab.regenerateModel(detailViewEntity,proceduralModel);
}
}
}
}
}
ImGui.unindent();
}
}
/**
* Regenerates the procedural model for the entity
* @param detailViewEntity The entity
* @param proceduralModel The procedural model
*/
private static void regenerateModel(Entity detailViewEntity, ProceduralModel proceduralModel){
if(proceduralModel.getTreeModel() != null){
for(Entity child : AttachUtils.getChildrenList(detailViewEntity)){
ClientEntityUtils.destroyEntity(child);
}
AttachUtils.getChildrenList(detailViewEntity).clear();
ProceduralTree.setProceduralActor(
detailViewEntity,
proceduralModel.getTreeModel(),
new Random()
);
}
}
}

View File

@ -1,4 +1,4 @@
package electrosphere.client.ui.menu.debug;
package electrosphere.client.ui.menu.debug.entity;
import java.util.LinkedList;
import java.util.List;
@ -23,13 +23,11 @@ import electrosphere.entity.types.foliage.FoliageUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorAnimationMask;
import electrosphere.renderer.actor.ActorMeshMask;
import electrosphere.renderer.actor.instance.InstancedActor;
import electrosphere.renderer.anim.AnimChannel;
import electrosphere.renderer.anim.Animation;
import electrosphere.renderer.model.Bone;
import electrosphere.renderer.model.Mesh;
import electrosphere.renderer.model.Model;
import electrosphere.renderer.ui.imgui.ImGuiWindow;
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
@ -44,8 +42,10 @@ import imgui.ImGui;
public class ImGuiEntityMacros {
//window for selecting entities to view
protected static ImGuiWindow clientEntityListWindow;
private static boolean filterToCreatures = true; //filters the entity list to just creatures
public static ImGuiWindow clientEntityListWindow;
private static boolean filterBasic = true; //filters out entities we probably wouldn't want to see (particles, terrain meshes, foliage cells, etc)
private static boolean filterToCreatures = false; //filters the entity list to just creatures
private static boolean filterToFoliage = false; //filters the entity list to just foliage
//window for viewing details about an entity
protected static ImGuiWindow clientEntityDetailWindow;
@ -54,6 +54,7 @@ public class ImGuiEntityMacros {
//tree node values
private static boolean showDataTab = false; //show all data names stored in the entity
private static boolean showActorTab = false; //show the actor tab
private static boolean showInstancedActorTab = false; //show the instanced actor tab
private static boolean showPoseActorTab = false; //show the pose actor tab
private static boolean showEquipStateTab = false; //actor details
private static boolean showFirstPersonTab = false; //first person tab
@ -64,7 +65,7 @@ public class ImGuiEntityMacros {
/**
* Creates the windows in this file
*/
protected static void createClientEntityWindows(){
public static void createClientEntityWindows(){
createClientEntityDetailWindow();
createClientEntitySelectionWindow();
}
@ -79,14 +80,23 @@ public class ImGuiEntityMacros {
public void exec() {
//audio engine details
ImGui.text("Client Entities");
if(ImGui.checkbox("Filter Basic", filterBasic)){
filterBasic = !filterBasic;
}
if(ImGui.checkbox("Filter to Creatures", filterToCreatures)){
filterToCreatures = !filterToCreatures;
}
if(ImGui.checkbox("Filter to Foliage", filterToFoliage)){
filterToFoliage = !filterToFoliage;
}
for(Entity entity : Globals.clientSceneWrapper.getScene().getEntityList()){
//filters
if(filterToCreatures && !CreatureUtils.isCreature(entity)){
continue;
}
if(filterToFoliage && !FoliageUtils.isFoliage(entity)){
continue;
}
ImGui.beginGroup();
ImGui.pushID(entity.getId());
ImGui.text("Id: " + entity.getId() + " (" + getEntityName(entity) + ")");
@ -119,6 +129,9 @@ public class ImGuiEntityMacros {
if(EntityUtils.getActor(detailViewEntity) != null && ImGui.checkbox("Actor Details", showActorTab)){
showActorTab = !showActorTab;
}
if(InstancedActor.getInstancedActor(detailViewEntity) != null && ImGui.checkbox("Instanced Actor Details", showInstancedActorTab)){
showInstancedActorTab = !showInstancedActorTab;
}
if(EntityUtils.getPoseActor(detailViewEntity) != null && ImGui.checkbox("Pose Actor Details", showPoseActorTab)){
showPoseActorTab = !showPoseActorTab;
}
@ -143,7 +156,8 @@ public class ImGuiEntityMacros {
ImGui.treePop();
}
ImGui.nextColumn();
drawActorView();
ImGuiEntityActorTab.drawActorView(showActorTab,detailViewEntity);
ImGuiEntityInstancedActorTab.drawInstancedActorView(showInstancedActorTab, detailViewEntity);
drawPoseActor();
drawEquipState();
drawFirstPersonView();
@ -161,7 +175,7 @@ public class ImGuiEntityMacros {
* Shows the entity window for a specific entity
* @param entity The entity
*/
protected static void showEntity(Entity entity){
public static void showEntity(Entity entity){
detailViewEntity = entity;
clientEntityDetailWindow.setOpen(true);
}
@ -179,98 +193,6 @@ public class ImGuiEntityMacros {
}
}
/**
* Client scene entity view
*/
protected static void drawActorView(){
if(showActorTab && ImGui.collapsingHeader("Actor Details")){
ImGui.indent();
if(detailViewEntity != null && EntityUtils.getActor(detailViewEntity) != null){
Actor actor = EntityUtils.getActor(detailViewEntity);
//mesh mask
if(ImGui.collapsingHeader("Mesh Mask")){
ActorMeshMask meshMask = actor.getMeshMask();
ImGui.text("To Draw Meshes:");
for(Mesh mesh : meshMask.getToDrawMeshes()){
ImGui.text(mesh.getMeshName());
}
ImGui.text("Blocked Meshes:");
for(String blocked : meshMask.getBlockedMeshes()){
ImGui.text(blocked);
}
}
//animation queue
if(ImGui.collapsingHeader("Animation Queue")){
Set<ActorAnimationMask> animationQueue = actor.getAnimationQueue();
for(ActorAnimationMask mask : animationQueue){
ImGui.text(mask.getAnimationName() + " - " + mask.getPriority());
ImGui.text(mask.getDuration() + " " + mask.getTime());
}
}
//bone values
if(ImGui.collapsingHeader("Bone Values")){
for(Bone bone : actor.getBoneValues()){
ImGui.text(bone.boneID);
ImGui.text("Position: " + actor.getBonePosition(bone.boneID));
ImGui.text("Rotation: " + actor.getBoneRotation(bone.boneID));
ImGui.text(bone.getFinalTransform() + "");
}
}
//Draws all the bones in the world
if(ImGui.button("Draw Bones")){
Globals.renderingEngine.getDebugContentPipeline().getDebugBonesPipeline().setEntity(detailViewEntity);
}
//Browsable list of all animations with their data
if(ImGui.collapsingHeader("Animation Channel Data")){
Model model = Globals.assetManager.fetchModel(actor.getModelPath());
ImGui.indent();
for(Animation animation : model.getAnimations()){
if(ImGui.collapsingHeader(animation.name)){
if(ImGui.button("Play")){
actor.playAnimation(animation.name, AnimationPriorities.getValue(AnimationPriorities.MODIFIER_MAX));
}
for(AnimChannel channel : animation.channels){
ImGui.pushID(channel.getNodeID());
if(ImGui.button("Fully describe")){
channel.fullDescribeChannel();
}
ImGui.text("=" + channel.getNodeID() + "=");
ImGui.text("" + channel.getCurrentPosition());
ImGui.text("" + channel.getCurrentRotation());
ImGui.text("" + channel.getCurrentScale());
ImGui.popID();
}
}
}
ImGui.unindent();
}
//print data macros
if(ImGui.collapsingHeader("Print Data")){
//print bone values
if(ImGui.button("Print current bone values")){
for(Bone bone : actor.getBoneValues()){
LoggerInterface.loggerRenderer.DEBUG(bone.boneID);
LoggerInterface.loggerRenderer.DEBUG("" + bone.getFinalTransform());
}
}
//print animation keys
if(ImGui.button("Print animation keys")){
Model model = Globals.assetManager.fetchModel(actor.getModelPath());
model.describeAllAnimations();
}
}
}
ImGui.unindent();
}
}
/**
* Draws pose actor
*/

View File

@ -1,9 +1,12 @@
package electrosphere.entity;
import java.util.List;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import electrosphere.engine.Globals;
import electrosphere.entity.state.attach.AttachUtils;
import electrosphere.entity.types.collision.CollisionObjUtils;
/**
@ -28,6 +31,16 @@ public class ClientEntityUtils {
* @param entity the entity to destroy
*/
public static void destroyEntity(Entity entity){
//
//destroy the child entities, too
if(AttachUtils.hasChildren(entity)){
List<Entity> children = AttachUtils.getChildrenList(entity);
for(Entity child : children){
ClientEntityUtils.destroyEntity(child);
}
}
//check for client-specific stuff
Globals.renderingEngine.getLightManager().destroyPointLight(entity);

View File

@ -42,6 +42,7 @@ public class EntityDataStrings {
*/
public static final String ENTITY_TYPE = "entityType"; //ie "creature", "foliage", "terrain", etc
public static final String ENTITY_SUBTYPE = "entitySubtype"; //ie "human", "woodenCrate", etc
public static final String COMMON_DATA = "commonData";
/*
Terrain Entity

View File

@ -99,6 +99,7 @@ public class CommonEntityUtils {
//Set typing stuff
//
CommonEntityUtils.setTyping(entity,rawType);
CommonEntityUtils.setCommonData(entity,rawType);
//tracks whether to generate a drawable or not
boolean generateDrawable = true;
@ -392,6 +393,7 @@ public class CommonEntityUtils {
//
CommonEntityUtils.setTyping(entity,rawType);
CommonEntityUtils.serverAttachToTag(entity,rawType);
CommonEntityUtils.setCommonData(entity,rawType);
//tracks whether to generate a drawable or not
boolean generateDrawable = true;
@ -815,6 +817,24 @@ public class CommonEntityUtils {
entity.putData(EntityDataStrings.ENTITY_TYPE, type);
}
/**
* Gets the common data on the entity
* @param entity The entity
* @return The common data
*/
public static CommonEntityType getCommonData(Entity entity){
return (CommonEntityType)entity.getData(EntityDataStrings.COMMON_DATA);
}
/**
* Sets the common data on the entity
* @param entity The entity
* @param data The common data
*/
public static void setCommonData(Entity entity, CommonEntityType data){
entity.putData(EntityDataStrings.COMMON_DATA, data);
}
/**
* Gets the subtype of this entity
* @param entity The entity

View File

@ -35,7 +35,7 @@ public class FoliageUtils {
public static Entity clientSpawnBasicFoliage(String type, long seed){
FoliageType rawType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
Entity rVal;
if(rawType.getTreeModel()!=null){
if(rawType.getGraphicsTemplate().getProceduralModel().getTreeModel()!=null){
rVal = ProceduralTree.clientGenerateProceduralTree(type, 0);
} else {
rVal = EntityCreationUtils.createClientSpatialEntity();
@ -52,6 +52,9 @@ public class FoliageUtils {
//Foliage specific transforms
//
//
rVal.putData(EntityDataStrings.FOLIAGE_TYPE, rawType);
rVal.putData(EntityDataStrings.FOLIAGE_SEED, seed);
rVal.putData(EntityDataStrings.FOLIAGE_IS_SEEDED, true);
//audio
if(rawType.getAmbientAudio()!=null){
@ -74,7 +77,7 @@ public class FoliageUtils {
public static Entity serverSpawnTreeFoliage(Realm realm, Vector3d position, String type, long seed){
FoliageType rawType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
Entity rVal;
if(rawType.getTreeModel()!=null){
if(rawType.getGraphicsTemplate().getProceduralModel().getTreeModel()!=null){
rVal = ProceduralTree.serverGenerateProceduralTree(realm, position, rawType, seed);
} else {
rVal = EntityCreationUtils.createServerEntity(realm, position);

View File

@ -22,6 +22,7 @@ import electrosphere.collision.CollisionBodyCreation;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings;
@ -101,10 +102,22 @@ public class ProceduralTree {
//call recursive branching routine to generate branches from trunk + leaf blobs
FoliageType foliageType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
TreeModel treeModel = foliageType.getTreeModel();
TreeModel treeModel = foliageType.getGraphicsTemplate().getProceduralModel().getTreeModel();
//generate trunk
Entity trunkChild = EntityCreationUtils.createClientSpatialEntity();
setProceduralActor(trunkChild, treeModel, treeRandom);
return trunkChild;
}
/**
* Sets the procedural actor for the tree
* @param trunkChild The entity
* @param treeModel The tree model params
* @param treeRandom The random
*/
public static void setProceduralActor(Entity trunkChild, TreeModel treeModel, Random treeRandom){
InstancedActor instancedActor = InstancedEntityUtils.makeEntityInstancedWithModelTransform(trunkChild, branchInstanceTemplate, modelMatrixAttribute);
instancedActor.setAttribute(boneMatrixAttribute, new Matrix4f().identity());
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
@ -150,7 +163,7 @@ public class ProceduralTree {
true
);
return trunkChild;
ClientEntityUtils.initiallyPositionEntity(trunkChild, EntityUtils.getPosition(trunkChild), EntityUtils.getRotation(trunkChild));
}
private static List<Entity> clientGenerateBranchesAlt(
@ -371,7 +384,7 @@ public class ProceduralTree {
*/
public static Entity serverGenerateProceduralTree(Realm realm, Vector3d position, FoliageType foliageType, long seed){
//call recursive branching routine to generate branches from trunk + leaf blobs
TreeModel treeModel = foliageType.getTreeModel();
TreeModel treeModel = foliageType.getGraphicsTemplate().getProceduralModel().getTreeModel();
//generate trunk
Entity trunkChild = EntityCreationUtils.createServerEntity(realm,position);

View File

@ -18,7 +18,6 @@ import electrosphere.game.data.creature.type.movement.MovementSystem;
import electrosphere.game.data.creature.type.rotator.RotatorSystem;
import electrosphere.game.data.foliage.type.AmbientAudio;
import electrosphere.game.data.foliage.type.GrowthModel;
import electrosphere.game.data.foliage.type.TreeModel;
import electrosphere.game.data.graphics.GraphicsTemplate;
import electrosphere.game.data.particle.ParticleEmitter;
@ -107,11 +106,6 @@ public class CommonEntityType {
*/
GrowthModel growthModel;
/**
* The model for a tree
*/
TreeModel treeModel;
/**
* The ambient audio model
*/
@ -276,14 +270,6 @@ public class CommonEntityType {
return growthModel;
}
/**
* Gets the tree model
* @return The tree model
*/
public TreeModel getTreeModel(){
return treeModel;
}
/**
* Gets the ambient audio model
* @return The ambient audio model

View File

@ -96,7 +96,7 @@ public class TreeModel {
//The minimum scalar of a branch to generate a sway behavior tree
float minimumScalarToGenerateSwayTree;
//The maximum scalar of a branch to generate a sway behavior tree
//The maximum scalar of a branch to generate a sway behavior tree*
float maximumScalarToGenerateSwayTree;
//The model for the trunk of the tree
@ -354,4 +354,130 @@ public class TreeModel {
return leafModelPath;
}
public void setLimbScalarFalloffFactor(float limbScalarFalloffFactor) {
this.limbScalarFalloffFactor = limbScalarFalloffFactor;
}
public void setMinimumLimbScalar(float minimumLimbScalar) {
this.minimumLimbScalar = minimumLimbScalar;
}
public void setMaximumLimbDispersion(float maximumLimbDispersion) {
this.maximumLimbDispersion = maximumLimbDispersion;
}
public void setMinimumLimbDispersion(float minimumLimbDispersion) {
this.minimumLimbDispersion = minimumLimbDispersion;
}
public void setMinimumNumberForks(int minimumNumberForks) {
this.minimumNumberForks = minimumNumberForks;
}
public void setMaximumNumberForks(int maximumNumberForks) {
this.maximumNumberForks = maximumNumberForks;
}
public void setBranchHeight(float branchHeight) {
this.branchHeight = branchHeight;
}
public void setCentralTrunk(boolean centralTrunk) {
this.centralTrunk = centralTrunk;
}
public void setMaximumTrunkSegments(int maximumTrunkSegments) {
this.maximumTrunkSegments = maximumTrunkSegments;
}
public void setMaximumBranchSegments(int maximumBranchSegments) {
this.maximumBranchSegments = maximumBranchSegments;
}
public void setMaxBranchSegmentFalloffFactor(float maxBranchSegmentFalloffFactor) {
this.maxBranchSegmentFalloffFactor = maxBranchSegmentFalloffFactor;
}
public void setMinimumSegmentToSpawnLeaves(int minimumSegmentToSpawnLeaves) {
this.minimumSegmentToSpawnLeaves = minimumSegmentToSpawnLeaves;
}
public void setMinBranchHeightToStartSpawningLeaves(float minBranchHeightToStartSpawningLeaves) {
this.minBranchHeightToStartSpawningLeaves = minBranchHeightToStartSpawningLeaves;
}
public void setMaxBranchHeightToStartSpawningLeaves(float maxBranchHeightToStartSpawningLeaves) {
this.maxBranchHeightToStartSpawningLeaves = maxBranchHeightToStartSpawningLeaves;
}
public void setLeafIncrement(float leafIncrement) {
this.leafIncrement = leafIncrement;
}
public void setMinLeavesToSpawnPerPoint(int minLeavesToSpawnPerPoint) {
this.minLeavesToSpawnPerPoint = minLeavesToSpawnPerPoint;
}
public void setMaxLeavesToSpawnPerPoint(int maxLeavesToSpawnPerPoint) {
this.maxLeavesToSpawnPerPoint = maxLeavesToSpawnPerPoint;
}
public void setLeafDistanceFromCenter(float leafDistanceFromCenter) {
this.leafDistanceFromCenter = leafDistanceFromCenter;
}
public void setPhysicsCutoff(int physicsCutoff) {
this.physicsCutoff = physicsCutoff;
}
public void setPhysicsBody(CollidableTemplate physicsBody) {
this.physicsBody = physicsBody;
}
public void setPeelVariance(double peelVariance) {
this.peelVariance = peelVariance;
}
public void setPeelMinimum(double peelMinimum) {
this.peelMinimum = peelMinimum;
}
public void setSwaySigmoidFactor(double swaySigmoidFactor) {
this.swaySigmoidFactor = swaySigmoidFactor;
}
public void setMinimumSwayTime(int minimumSwayTime) {
this.minimumSwayTime = minimumSwayTime;
}
public void setSwayTimeVariance(int swayTimeVariance) {
this.swayTimeVariance = swayTimeVariance;
}
public void setYawVariance(double yawVariance) {
this.yawVariance = yawVariance;
}
public void setYawMinimum(double yawMinimum) {
this.yawMinimum = yawMinimum;
}
public void setMinimumScalarToGenerateSwayTree(float minimumScalarToGenerateSwayTree) {
this.minimumScalarToGenerateSwayTree = minimumScalarToGenerateSwayTree;
}
public void setMaximumScalarToGenerateSwayTree(float maximumScalarToGenerateSwayTree) {
this.maximumScalarToGenerateSwayTree = maximumScalarToGenerateSwayTree;
}
public void setTrunkModelPath(String trunkModelPath) {
this.trunkModelPath = trunkModelPath;
}
public void setLeafModelPath(String leafModelPath) {
this.leafModelPath = leafModelPath;
}
}