Proper tree transforms
This commit is contained in:
parent
9811c18cf7
commit
f113f45317
@ -30,6 +30,39 @@
|
|||||||
"growthRate" : 0.001
|
"growthRate" : 0.001
|
||||||
},
|
},
|
||||||
"modelPath" : "Models/grass1.fbx"
|
"modelPath" : "Models/grass1.fbx"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "oak",
|
||||||
|
"tokens" : [
|
||||||
|
"TREE",
|
||||||
|
"REACTS_TO_WIND",
|
||||||
|
"GROWS_BACK",
|
||||||
|
"FLAMMABLE"
|
||||||
|
],
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"modelPath" : "Models/proceduralTree2/proceduralTree2v2.fbx"
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|||||||
251
assets/Shaders/instanced/colorshift/colorshift.fs
Normal file
251
assets/Shaders/instanced/colorshift/colorshift.fs
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
#define NR_POINT_LIGHTS 10
|
||||||
|
|
||||||
|
#define SMALL_EPSILON 0.0001
|
||||||
|
|
||||||
|
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 TexCoord;
|
||||||
|
in vec4 FragPosLightSpace;
|
||||||
|
in vec3 colorShiftValue;
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
|
||||||
|
vec3 norm = normalize(Normal);
|
||||||
|
vec3 viewDir = normalize(viewPos - FragPos);
|
||||||
|
|
||||||
|
//grab light intensity
|
||||||
|
float lightIntensity = calcLightIntensityTotal(norm);
|
||||||
|
|
||||||
|
if(texture(material.diffuse, TexCoord).a < SMALL_EPSILON){
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get color of base texture
|
||||||
|
vec3 textureColor = texture(material.diffuse, TexCoord).rgb;
|
||||||
|
textureColor = vec3(
|
||||||
|
textureColor.r * (colorShiftValue.x),
|
||||||
|
textureColor.g * (colorShiftValue.y),
|
||||||
|
textureColor.b * (colorShiftValue.z)
|
||||||
|
);
|
||||||
|
|
||||||
|
//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);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculates the color when using a directional light.
|
||||||
|
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||||
|
// vec3 lightDir = normalize(-dLDirection);
|
||||||
|
// // 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);
|
||||||
|
// // combine results
|
||||||
|
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||||
|
// vec3 diffuse = dLDiffuse * diff;
|
||||||
|
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||||
|
|
||||||
|
|
||||||
|
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||||
|
|
||||||
|
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//
|
||||||
|
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];// * 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
62
assets/Shaders/instanced/colorshift/colorshift.vs
Normal file
62
assets/Shaders/instanced/colorshift/colorshift.vs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//Vertex Shader
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//input buffers
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aNormal;
|
||||||
|
layout (location = 2) in vec4 aWeights;
|
||||||
|
layout (location = 4) in vec2 aTex;
|
||||||
|
layout (location = 5) in vec4 modelA;
|
||||||
|
layout (location = 6) in vec4 modelB;
|
||||||
|
layout (location = 7) in vec4 modelC;
|
||||||
|
layout (location = 8) in vec4 modelD;
|
||||||
|
layout (location = 9) in vec3 colorShift;
|
||||||
|
|
||||||
|
|
||||||
|
//coordinate space transformation matrices
|
||||||
|
uniform mat4 transform;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 lightSpaceMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//output buffers
|
||||||
|
out vec3 Normal;
|
||||||
|
out vec3 FragPos;
|
||||||
|
out vec2 TexCoord;
|
||||||
|
out vec4 FragPosLightSpace;
|
||||||
|
out vec3 colorShiftValue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
mat4 model = mat4(modelA,modelB,modelC,modelD);
|
||||||
|
colorShiftValue = colorShift;
|
||||||
|
|
||||||
|
//normalize posiiton and normal
|
||||||
|
vec4 FinalVertex = vec4(aPos, 1.0);
|
||||||
|
vec4 FinalNormal = vec4(aNormal, 1.0);
|
||||||
|
|
||||||
|
//make sure the W component is 1.0
|
||||||
|
FinalVertex = vec4(FinalVertex.xyz, 1.0);
|
||||||
|
FinalNormal = vec4(FinalNormal.xyz, 1.0);
|
||||||
|
|
||||||
|
|
||||||
|
//push frag, normal, and texture positions to fragment shader
|
||||||
|
FragPos = vec3(model * FinalVertex);
|
||||||
|
Normal = mat3(transpose(inverse(model))) * aNormal;
|
||||||
|
TexCoord = aTex;
|
||||||
|
|
||||||
|
|
||||||
|
//shadow map stuff
|
||||||
|
FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);
|
||||||
|
|
||||||
|
|
||||||
|
//set final position with opengl space
|
||||||
|
gl_Position = projection * view * model * FinalVertex;
|
||||||
|
}
|
||||||
245
assets/Shaders/instanced/generic/generic.fs
Normal file
245
assets/Shaders/instanced/generic/generic.fs
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
#define NR_POINT_LIGHTS 10
|
||||||
|
|
||||||
|
#define SMALL_EPSILON 0.0001
|
||||||
|
|
||||||
|
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 TexCoord;
|
||||||
|
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);
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
|
||||||
|
vec3 norm = normalize(Normal);
|
||||||
|
vec3 viewDir = normalize(viewPos - FragPos);
|
||||||
|
|
||||||
|
//grab light intensity
|
||||||
|
float lightIntensity = calcLightIntensityTotal(norm);
|
||||||
|
|
||||||
|
if(texture(material.diffuse, TexCoord).a < SMALL_EPSILON){
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get color of base texture
|
||||||
|
vec3 textureColor = texture(material.diffuse, TexCoord).rgb;
|
||||||
|
|
||||||
|
//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);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculates the color when using a directional light.
|
||||||
|
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||||
|
// vec3 lightDir = normalize(-dLDirection);
|
||||||
|
// // 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);
|
||||||
|
// // combine results
|
||||||
|
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||||
|
// vec3 diffuse = dLDiffuse * diff;
|
||||||
|
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||||
|
|
||||||
|
|
||||||
|
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||||
|
|
||||||
|
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//
|
||||||
|
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];// * 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
60
assets/Shaders/instanced/generic/generic.vs
Normal file
60
assets/Shaders/instanced/generic/generic.vs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//Vertex Shader
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//input buffers
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aNormal;
|
||||||
|
layout (location = 2) in vec4 aWeights;
|
||||||
|
layout (location = 4) in vec2 aTex;
|
||||||
|
layout (location = 5) in vec4 modelA;
|
||||||
|
layout (location = 6) in vec4 modelB;
|
||||||
|
layout (location = 7) in vec4 modelC;
|
||||||
|
layout (location = 8) in vec4 modelD;
|
||||||
|
|
||||||
|
|
||||||
|
//coordinate space transformation matrices
|
||||||
|
uniform mat4 transform;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 lightSpaceMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//output buffers
|
||||||
|
out vec3 Normal;
|
||||||
|
out vec3 FragPos;
|
||||||
|
out vec2 TexCoord;
|
||||||
|
out vec4 FragPosLightSpace;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
mat4 model = mat4(modelA,modelB,modelC,modelD);
|
||||||
|
|
||||||
|
|
||||||
|
//normalize posiiton and normal
|
||||||
|
vec4 FinalVertex = vec4(aPos, 1.0);
|
||||||
|
vec4 FinalNormal = vec4(aNormal, 1.0);
|
||||||
|
|
||||||
|
//make sure the W component is 1.0
|
||||||
|
FinalVertex = vec4(FinalVertex.xyz, 1.0);
|
||||||
|
FinalNormal = vec4(FinalNormal.xyz, 1.0);
|
||||||
|
|
||||||
|
|
||||||
|
//push frag, normal, and texture positions to fragment shader
|
||||||
|
FragPos = vec3(model * FinalVertex);
|
||||||
|
Normal = mat3(transpose(inverse(model))) * aNormal;
|
||||||
|
TexCoord = aTex;
|
||||||
|
|
||||||
|
|
||||||
|
//shadow map stuff
|
||||||
|
FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);
|
||||||
|
|
||||||
|
|
||||||
|
//set final position with opengl space
|
||||||
|
gl_Position = projection * view * model * FinalVertex;
|
||||||
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
#maven.buildNumber.plugin properties file
|
#maven.buildNumber.plugin properties file
|
||||||
#Sun Aug 20 22:06:17 EDT 2023
|
#Sat Sep 02 19:48:14 EDT 2023
|
||||||
buildNumber=10
|
buildNumber=11
|
||||||
|
|||||||
@ -240,7 +240,10 @@ public class ClientLoading {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// for(int i = 0; i < 6; i++){
|
// for(int i = 0; i < 6; i++){
|
||||||
Entity tree = ProceduralTree.clientGenerateProceduralTree("asdf", 0);
|
Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", 0);
|
||||||
|
EntityUtils.getPosition(tree).set(5,0,5);
|
||||||
|
EntityUtils.getScale(tree).set(0.5f);
|
||||||
|
EntityUtils.getRotation(tree).rotateLocalX(0.5);
|
||||||
// EntityUtils.getPosition(tree).set(5,0,i * 3);
|
// EntityUtils.getPosition(tree).set(5,0,i * 3);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|||||||
@ -171,6 +171,7 @@ public class EntityDataStrings {
|
|||||||
public static final String ATTACH_CHILDREN_LIST = "attachChildrenList";
|
public static final String ATTACH_CHILDREN_LIST = "attachChildrenList";
|
||||||
public static final String ATTACH_ROTATION_OFFSET = "attachRotationOffset";
|
public static final String ATTACH_ROTATION_OFFSET = "attachRotationOffset";
|
||||||
public static final String ATTACH_POSITION_OFFSET = "attachPositionOffset";
|
public static final String ATTACH_POSITION_OFFSET = "attachPositionOffset";
|
||||||
|
public static final String ATTACH_TRANSFORM = "attachTransform";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Item Entity
|
Item Entity
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package electrosphere.entity;
|
|||||||
public class EntityTags {
|
public class EntityTags {
|
||||||
|
|
||||||
public static final String BONE_ATTACHED = "boneAttached";
|
public static final String BONE_ATTACHED = "boneAttached";
|
||||||
|
public static final String TRANSFORM_ATTACHED = "transformAttached";
|
||||||
public static final String COLLIDABLE = "collidable";
|
public static final String COLLIDABLE = "collidable";
|
||||||
public static final String SPRINTABLE = "sprintable";
|
public static final String SPRINTABLE = "sprintable";
|
||||||
public static final String MOVEABLE = "moveable";
|
public static final String MOVEABLE = "moveable";
|
||||||
|
|||||||
@ -45,6 +45,7 @@ public class Scene {
|
|||||||
tagEntityMap.put(EntityTags.ITEM, new HashSet<Entity>());
|
tagEntityMap.put(EntityTags.ITEM, new HashSet<Entity>());
|
||||||
tagEntityMap.put(EntityTags.GRAVITY, new HashSet<Entity>());
|
tagEntityMap.put(EntityTags.GRAVITY, new HashSet<Entity>());
|
||||||
tagEntityMap.put(EntityTags.PARTICLE, new HashSet<Entity>());
|
tagEntityMap.put(EntityTags.PARTICLE, new HashSet<Entity>());
|
||||||
|
tagEntityMap.put(EntityTags.TRANSFORM_ATTACHED, new HashSet<Entity>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -14,48 +14,30 @@ import electrosphere.server.datacell.utils.ServerEntityTagUtils;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joml.Matrix4d;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Quaterniond;
|
import org.joml.Quaterniond;
|
||||||
import org.joml.Quaternionf;
|
import org.joml.Quaternionf;
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
import org.joml.Vector4d;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author amaterasu
|
* @author amaterasu
|
||||||
*/
|
*/
|
||||||
public class AttachUtils {
|
public class AttachUtils {
|
||||||
|
|
||||||
|
|
||||||
public static void serverAttachEntityToEntityAtBone(Entity parent, Entity toAttach, String boneName, Quaterniond rotation){
|
|
||||||
ServerEntityTagUtils.attachTagToEntity(toAttach, EntityTags.BONE_ATTACHED);
|
|
||||||
toAttach.putData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED, true);
|
|
||||||
toAttach.putData(EntityDataStrings.ATTACH_PARENT, parent);
|
|
||||||
toAttach.putData(EntityDataStrings.ATTACH_TARGET_BONE, boneName);
|
|
||||||
toAttach.putData(EntityDataStrings.ATTACH_ROTATION_OFFSET, rotation);
|
|
||||||
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
|
||||||
getChildrenList(parent).add(toAttach);
|
|
||||||
} else {
|
|
||||||
LinkedList<Entity> childrenEntities = new LinkedList<Entity> ();
|
|
||||||
childrenEntities.add(toAttach);
|
|
||||||
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void clientAttachEntityToEntityAtBone(Entity parent, Entity toAttach, String boneName, Quaterniond rotation){
|
|
||||||
Globals.clientSceneWrapper.getScene().registerEntityToTag(toAttach, EntityTags.BONE_ATTACHED);
|
|
||||||
toAttach.putData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED, true);
|
|
||||||
toAttach.putData(EntityDataStrings.ATTACH_PARENT, parent);
|
|
||||||
toAttach.putData(EntityDataStrings.ATTACH_TARGET_BONE, boneName);
|
|
||||||
toAttach.putData(EntityDataStrings.ATTACH_ROTATION_OFFSET, rotation);
|
|
||||||
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
//
|
||||||
getChildrenList(parent).add(toAttach);
|
// FUNCTIONS TO UPDATE ATTACHMENTS FOR CURRENT FRAME
|
||||||
} else {
|
//
|
||||||
LinkedList<Entity> childrenEntities = new LinkedList<Entity> ();
|
|
||||||
childrenEntities.add(toAttach);
|
|
||||||
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void serverUpdateAttachedEntityPositions(ServerDataCell cell){
|
public static void serverUpdateAttachedEntityPositions(ServerDataCell cell){
|
||||||
for(Entity currentEntity : cell.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){
|
for(Entity currentEntity : cell.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){
|
||||||
@ -90,7 +72,11 @@ public class AttachUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client version of attachment update functions
|
||||||
|
*/
|
||||||
public static void clientUpdateAttachedEntityPositions(){
|
public static void clientUpdateAttachedEntityPositions(){
|
||||||
|
//update entities attached to bones of other entities
|
||||||
for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){
|
for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){
|
||||||
Entity parent;
|
Entity parent;
|
||||||
if((parent = (Entity)currentEntity.getData(EntityDataStrings.ATTACH_PARENT))!=null){
|
if((parent = (Entity)currentEntity.getData(EntityDataStrings.ATTACH_PARENT))!=null){
|
||||||
@ -125,28 +111,103 @@ public class AttachUtils {
|
|||||||
EntityUtils.getPosition(currentEntity).set(new Vector3d(parentPosition).add(positionOffset));
|
EntityUtils.getPosition(currentEntity).set(new Vector3d(parentPosition).add(positionOffset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Matrix4d parentTransform = new Matrix4d().identity();
|
||||||
public static void serverDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){
|
//update entities attached to centerpoint + transform of other entities
|
||||||
ServerEntityTagUtils.removeTagFromEntity(toAttach, EntityTags.BONE_ATTACHED);
|
for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.TRANSFORM_ATTACHED)){
|
||||||
toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
Entity parent;
|
||||||
toAttach.removeData(EntityDataStrings.ATTACH_PARENT);
|
if((parent = (Entity)currentEntity.getData(EntityDataStrings.ATTACH_PARENT))!=null){
|
||||||
toAttach.removeData(EntityDataStrings.ATTACH_TARGET_BONE);
|
Matrix4f transform;
|
||||||
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
if((transform = getTransformOffset(currentEntity))!=null){
|
||||||
getChildrenList(parent).remove(toAttach);
|
//parent objects
|
||||||
|
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
||||||
|
Quaterniond parentRotation = EntityUtils.getRotation(parent);
|
||||||
|
Vector3f parentScale = EntityUtils.getScale(parent);
|
||||||
|
// calculate new transform for current entity
|
||||||
|
parentTransform.identity()
|
||||||
|
.translate(parentPosition)
|
||||||
|
.rotate(parentRotation)
|
||||||
|
.scale(parentScale.x,parentScale.y,parentScale.z)
|
||||||
|
.mul(transform);
|
||||||
|
//transform bone space
|
||||||
|
Vector4d positionRaw = parentTransform.transform(new Vector4d(0,0,0,1));
|
||||||
|
Vector3d position = new Vector3d(positionRaw.x,positionRaw.y,positionRaw.z);
|
||||||
|
Quaterniond rotation = parentTransform.getUnnormalizedRotation(new Quaterniond()).normalize();
|
||||||
|
Vector3d scaleRaw = parentTransform.getScale(new Vector3d());
|
||||||
|
Vector3f scale = new Vector3f((float)scaleRaw.x,(float)scaleRaw.y,(float)scaleRaw.z);
|
||||||
|
//transform worldspace
|
||||||
|
// position.add(new Vector3d(EntityUtils.getPosition(parent)));
|
||||||
|
//set
|
||||||
|
EntityUtils.getPosition(currentEntity).set(position);
|
||||||
|
EntityUtils.getRotation(currentEntity).set(rotation);
|
||||||
|
EntityUtils.getScale(currentEntity).set(scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clientDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){
|
|
||||||
Globals.clientSceneWrapper.getScene().removeEntityFromTag(toAttach, EntityTags.BONE_ATTACHED);
|
|
||||||
toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
|
||||||
toAttach.removeData(EntityDataStrings.ATTACH_PARENT);
|
|
||||||
toAttach.removeData(EntityDataStrings.ATTACH_TARGET_BONE);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// FUNCTIONS TO ATTACH AN ENTITY
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void serverAttachEntityToEntityAtBone(Entity parent, Entity toAttach, String boneName, Quaterniond rotation){
|
||||||
|
ServerEntityTagUtils.attachTagToEntity(toAttach, EntityTags.BONE_ATTACHED);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED, true);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_PARENT, parent);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_TARGET_BONE, boneName);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_ROTATION_OFFSET, rotation);
|
||||||
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
||||||
getChildrenList(parent).remove(toAttach);
|
getChildrenList(parent).add(toAttach);
|
||||||
|
} else {
|
||||||
|
LinkedList<Entity> childrenEntities = new LinkedList<Entity> ();
|
||||||
|
childrenEntities.add(toAttach);
|
||||||
|
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void clientAttachEntityToEntityAtBone(Entity parent, Entity toAttach, String boneName, Quaterniond rotation){
|
||||||
|
Globals.clientSceneWrapper.getScene().registerEntityToTag(toAttach, EntityTags.BONE_ATTACHED);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED, true);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_PARENT, parent);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_TARGET_BONE, boneName);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_ROTATION_OFFSET, rotation);
|
||||||
|
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
||||||
|
getChildrenList(parent).add(toAttach);
|
||||||
|
} else {
|
||||||
|
LinkedList<Entity> childrenEntities = new LinkedList<Entity> ();
|
||||||
|
childrenEntities.add(toAttach);
|
||||||
|
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches an entity to another based on the parent's absolute position in the game engine
|
* Attaches an entity to another based on the parent's absolute position in the game engine
|
||||||
* @param parent The parent to attach to
|
* @param parent The parent to attach to
|
||||||
@ -169,7 +230,130 @@ public class AttachUtils {
|
|||||||
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches an entity such that a transform will be applied to it relative to the parent's position and rotation every frame
|
||||||
|
* @param parent The parent entity
|
||||||
|
* @param toAttach The child entity
|
||||||
|
* @param transform The transform
|
||||||
|
*/
|
||||||
|
public static void clientAttachEntityAtTransform(Entity parent, Entity toAttach, Matrix4f transform){
|
||||||
|
Globals.clientSceneWrapper.getScene().registerEntityToTag(toAttach, EntityTags.TRANSFORM_ATTACHED);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED, true);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_PARENT, parent);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_TARGET_BASE, true);
|
||||||
|
toAttach.putData(EntityDataStrings.ATTACH_TRANSFORM, transform);
|
||||||
|
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
||||||
|
getChildrenList(parent).add(toAttach);
|
||||||
|
} else {
|
||||||
|
LinkedList<Entity> childrenEntities = new LinkedList<Entity> ();
|
||||||
|
childrenEntities.add(toAttach);
|
||||||
|
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantically attaches an entity to another entity
|
||||||
|
* @param parent The parent entity
|
||||||
|
* @param child The child entity
|
||||||
|
*/
|
||||||
|
public static void attachEntityToEntity(Entity parent, Entity child){
|
||||||
|
child.putData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED, true);
|
||||||
|
child.putData(EntityDataStrings.ATTACH_PARENT, parent);
|
||||||
|
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
||||||
|
getChildrenList(parent).add(child);
|
||||||
|
} else {
|
||||||
|
List<Entity> childrenEntities = new LinkedList<Entity>();
|
||||||
|
childrenEntities.add(child);
|
||||||
|
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// FUNCTIONS TO DETATCH AN ENTITY
|
||||||
|
//
|
||||||
|
|
||||||
|
public static void serverDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){
|
||||||
|
ServerEntityTagUtils.removeTagFromEntity(toAttach, EntityTags.BONE_ATTACHED);
|
||||||
|
toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
||||||
|
toAttach.removeData(EntityDataStrings.ATTACH_PARENT);
|
||||||
|
toAttach.removeData(EntityDataStrings.ATTACH_TARGET_BONE);
|
||||||
|
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
||||||
|
getChildrenList(parent).remove(toAttach);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clientDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){
|
||||||
|
Globals.clientSceneWrapper.getScene().removeEntityFromTag(toAttach, EntityTags.BONE_ATTACHED);
|
||||||
|
toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
||||||
|
toAttach.removeData(EntityDataStrings.ATTACH_PARENT);
|
||||||
|
toAttach.removeData(EntityDataStrings.ATTACH_TARGET_BONE);
|
||||||
|
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
||||||
|
getChildrenList(parent).remove(toAttach);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// GETTERS
|
||||||
|
//
|
||||||
|
|
||||||
public static boolean isAttached(Entity e){
|
public static boolean isAttached(Entity e){
|
||||||
return e.containsKey(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
return e.containsKey(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
||||||
}
|
}
|
||||||
@ -185,6 +369,15 @@ public class AttachUtils {
|
|||||||
protected static Quaterniond getRotationOffset(Entity e){
|
protected static Quaterniond getRotationOffset(Entity e){
|
||||||
return (Quaterniond)e.getData(EntityDataStrings.ATTACH_ROTATION_OFFSET);
|
return (Quaterniond)e.getData(EntityDataStrings.ATTACH_ROTATION_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the transform for a transform attached entity
|
||||||
|
* @param e The entity
|
||||||
|
* @return The transform if it exists, false otherwise
|
||||||
|
*/
|
||||||
|
protected static Matrix4f getTransformOffset(Entity e){
|
||||||
|
return (Matrix4f)e.getData(EntityDataStrings.ATTACH_TRANSFORM);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean hasChildren(Entity e){
|
public static boolean hasChildren(Entity e){
|
||||||
return e.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST) && !getChildrenList(e).isEmpty();
|
return e.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST) && !getChildrenList(e).isEmpty();
|
||||||
@ -197,18 +390,6 @@ public class AttachUtils {
|
|||||||
public static LinkedList<Entity> getChildrenList(Entity e){
|
public static LinkedList<Entity> getChildrenList(Entity e){
|
||||||
return (LinkedList<Entity>)e.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
|
return (LinkedList<Entity>)e.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void attachEntityToEntity(Entity parent, Entity child){
|
|
||||||
child.putData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED, true);
|
|
||||||
child.putData(EntityDataStrings.ATTACH_PARENT, parent);
|
|
||||||
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
|
|
||||||
getChildrenList(parent).add(child);
|
|
||||||
} else {
|
|
||||||
List<Entity> childrenEntities = new LinkedList<Entity>();
|
|
||||||
childrenEntities.add(child);
|
|
||||||
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Quaterniond getEquipPointRotationOffset(List<Float> values){
|
public static Quaterniond getEquipPointRotationOffset(List<Float> values){
|
||||||
return new Quaterniond(values.get(0),values.get(1),values.get(2),values.get(3));
|
return new Quaterniond(values.get(0),values.get(1),values.get(2),values.get(3));
|
||||||
|
|||||||
@ -21,6 +21,8 @@ import electrosphere.entity.state.BehaviorTree;
|
|||||||
import electrosphere.entity.types.attach.AttachUtils;
|
import electrosphere.entity.types.attach.AttachUtils;
|
||||||
import electrosphere.entity.types.instance.InstanceTemplate;
|
import electrosphere.entity.types.instance.InstanceTemplate;
|
||||||
import electrosphere.entity.types.instance.InstancedEntityUtils;
|
import electrosphere.entity.types.instance.InstancedEntityUtils;
|
||||||
|
import electrosphere.game.data.foliage.type.FoliageType;
|
||||||
|
import electrosphere.game.data.foliage.type.TreeModel;
|
||||||
import electrosphere.renderer.actor.instance.InstancedActor;
|
import electrosphere.renderer.actor.instance.InstancedActor;
|
||||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||||
@ -33,6 +35,9 @@ public class ProceduralTree {
|
|||||||
//The instance template for the branch
|
//The instance template for the branch
|
||||||
static InstanceTemplate branchInstanceTemplate;
|
static InstanceTemplate branchInstanceTemplate;
|
||||||
|
|
||||||
|
//the instance template for a leaf blob
|
||||||
|
static InstanceTemplate leafInstanceTemplate;
|
||||||
|
|
||||||
//The model attribute
|
//The model attribute
|
||||||
static final ShaderAttribute modelMatrixAttribute = new ShaderAttribute(new int[]{
|
static final ShaderAttribute modelMatrixAttribute = new ShaderAttribute(new int[]{
|
||||||
5,6,7,8
|
5,6,7,8
|
||||||
@ -43,8 +48,11 @@ public class ProceduralTree {
|
|||||||
9,10,11,12
|
9,10,11,12
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//the size of the base of the branch segment, attribute
|
||||||
static final ShaderAttribute baseSizeAttribute = new ShaderAttribute(13);
|
static final ShaderAttribute baseSizeAttribute = new ShaderAttribute(13);
|
||||||
|
|
||||||
|
static final ShaderAttribute leafColorAttribute = new ShaderAttribute(9);
|
||||||
|
|
||||||
//The static setup logic
|
//The static setup logic
|
||||||
static {
|
static {
|
||||||
//create map of attributes and register them
|
//create map of attributes and register them
|
||||||
@ -56,25 +64,30 @@ public class ProceduralTree {
|
|||||||
branchInstanceTemplate = InstanceTemplate.createInstanceTemplate(
|
branchInstanceTemplate = InstanceTemplate.createInstanceTemplate(
|
||||||
1000,
|
1000,
|
||||||
"Models/proceduralTree2/proceduralTree2v2.fbx",
|
"Models/proceduralTree2/proceduralTree2v2.fbx",
|
||||||
"Shaders/proceduraltree/proceduraltree.vs",
|
"Shaders/instanced/proceduraltree/proceduraltree.vs",
|
||||||
"Shaders/proceduraltree/proceduraltree.fs",
|
"Shaders/instanced/proceduraltree/proceduraltree.fs",
|
||||||
attributes);
|
attributes);
|
||||||
|
|
||||||
|
Map<ShaderAttribute,HomogenousBufferTypes> leafAttributes = new HashMap<ShaderAttribute,HomogenousBufferTypes>();
|
||||||
|
leafAttributes.put(modelMatrixAttribute,HomogenousBufferTypes.MAT4F);
|
||||||
|
leafAttributes.put(leafColorAttribute, HomogenousBufferTypes.VEC3F);
|
||||||
|
leafInstanceTemplate = InstanceTemplate.createInstanceTemplate(
|
||||||
|
10000,
|
||||||
|
"Models/foliageBlockTemplate1Test1.fbx",
|
||||||
|
"Shaders/instanced/colorshift/colorshift.vs",
|
||||||
|
"Shaders/instanced/colorshift/colorshift.fs",
|
||||||
|
leafAttributes
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO: make variable based on tree type
|
|
||||||
static final int MAX_HEIGHT_SEGMENTS = 4;
|
|
||||||
static final int MIN_HEIGHT_SEGMENTS = 4;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client side function to generate a tree
|
* Client side function to generate a tree
|
||||||
* @param type
|
* @param type The type of tree as a string
|
||||||
* @param seed
|
* @param seed The seed (lol) for the tree
|
||||||
* @return
|
* @return The top level tree entity
|
||||||
*/
|
*/
|
||||||
public static Entity clientGenerateProceduralTree(String type, long seed){
|
public static Entity clientGenerateProceduralTree(String type, long seed){
|
||||||
Random treeRandom = new Random(seed);
|
Random treeRandom = new Random(seed);
|
||||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
|
||||||
|
|
||||||
//generate trunk
|
//generate trunk
|
||||||
Entity trunkChild = EntityCreationUtils.createClientSpatialEntity();
|
Entity trunkChild = EntityCreationUtils.createClientSpatialEntity();
|
||||||
@ -83,189 +96,168 @@ public class ProceduralTree {
|
|||||||
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
||||||
instancedActor.setAttribute(baseSizeAttribute, 1.0f);
|
instancedActor.setAttribute(baseSizeAttribute, 1.0f);
|
||||||
// EntityCreationUtils.makeEntityDrawable(trunkChild, "Models/proceduralTree2/proceduralTree2.fbx");
|
// EntityCreationUtils.makeEntityDrawable(trunkChild, "Models/proceduralTree2/proceduralTree2.fbx");
|
||||||
AttachUtils.clientAttachEntityAtCurrentOffset(rVal, trunkChild);
|
|
||||||
|
|
||||||
//generate branches
|
|
||||||
Quaterniond currentRotation = new Quaterniond(0,0,0,1).rotateLocalX(0).rotateLocalZ(0).normalize();
|
|
||||||
// clientGenerateBranches(type,trunkChild,treeRandom,new Vector3d(0,3.0,0),currentRotation,1);
|
|
||||||
|
|
||||||
Matrix4f transform = new Matrix4f().identity().translate(0,3,0);
|
|
||||||
clientGenerateBranches(type,trunkChild,treeRandom,transform,1);
|
|
||||||
|
|
||||||
//call recursive branching routine to generate branches from trunk + leaf blobs
|
//call recursive branching routine to generate branches from trunk + leaf blobs
|
||||||
//...
|
Matrix4f transform = new Matrix4f().identity().translate(0,3,0);
|
||||||
// clientGenerateBranches(type, rVal, treeRandom, new Vector3d(0,heightSegments,0), new Quaterniond(0,0.7071068,0,0.7071068), heightSegments);
|
FoliageType foliageType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
|
||||||
int topLayerLeavesCount = treeRandom.nextInt(3) + 3;
|
TreeModel treeModel = foliageType.getTreeModel();
|
||||||
float topLayerRotationOffset = treeRandom.nextFloat();
|
// clientGenerateBranches(
|
||||||
// for(int i = 0; i < topLayerLeavesCount; i++){
|
// treeModel,
|
||||||
// Entity leafBlock = EntityCreationUtils.createClientSpatialEntity();
|
// trunkChild,
|
||||||
// EntityCreationUtils.makeEntityDrawable(leafBlock, "Models/foliageBlockTemplate1Test1.fbx");
|
// treeRandom,
|
||||||
// float radius = 1;
|
// transform,
|
||||||
// double x = radius * Math.cos(i * (Math.PI * 2.0 / (float)topLayerLeavesCount) + topLayerRotationOffset);
|
// 1,
|
||||||
// double z = radius * Math.sin(i * (Math.PI * 2.0 / (float)topLayerLeavesCount) + topLayerRotationOffset);
|
// 1,
|
||||||
// EntityUtils.getPosition(leafBlock).set(x,20,z);
|
// true
|
||||||
// DrawableUtils.makeEntityTransparent(leafBlock);
|
// );
|
||||||
// }
|
clientGenerateBranchesAlt(
|
||||||
|
treeModel,
|
||||||
int layerCount = 8;
|
trunkChild,
|
||||||
int halfLayer = layerCount / 2;
|
treeRandom,
|
||||||
float maxRadius = 2f;
|
new Vector3d(0,0,0),
|
||||||
float spacingBetweenLayers = 1;
|
new Quaterniond(0,0,0,1),
|
||||||
float layerDensityDecreaseRate = 3;
|
new Vector3d(0,3,0),
|
||||||
int initialDensity = 20;
|
new Quaternionf(0,0,0,1),
|
||||||
float startingHeight = 4;
|
1,
|
||||||
// for(int leafLayer = 0; leafLayer < layerCount; leafLayer++){
|
1,
|
||||||
// topLayerLeavesCount = treeRandom.nextInt(3) + 3 * (int)(halfLayer * ((halfLayer - Math.abs(leafLayer - halfLayer))/(float)halfLayer));
|
true
|
||||||
// topLayerRotationOffset = treeRandom.nextFloat();
|
);
|
||||||
// for(int i = 0; i < topLayerLeavesCount; i++){
|
|
||||||
// Entity leafBlock = EntityCreationUtils.createClientSpatialEntity();
|
|
||||||
// EntityCreationUtils.makeEntityDrawable(leafBlock, "Models/foliageBlockTemplate1Test1.fbx");
|
|
||||||
// float radius = maxRadius * ((float)Math.sin(Math.PI * ((halfLayer - Math.abs(leafLayer - halfLayer))/(float)halfLayer) / 2.0f));
|
|
||||||
// double x = radius * Math.cos(i * (Math.PI * 2.0 / (float)topLayerLeavesCount) + topLayerRotationOffset);
|
|
||||||
// double z = radius * Math.sin(i * (Math.PI * 2.0 / (float)topLayerLeavesCount) + topLayerRotationOffset);
|
|
||||||
// EntityUtils.getPosition(leafBlock).set(x,20 - leafLayer,z);
|
|
||||||
// DrawableUtils.makeEntityTransparent(leafBlock);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for(int leafLayer = 0; leafLayer < layerCount; leafLayer++){
|
|
||||||
// topLayerLeavesCount = initialDensity - (int)(layerDensityDecreaseRate * leafLayer);
|
|
||||||
// topLayerRotationOffset = treeRandom.nextFloat();
|
|
||||||
// for(int i = 0; i < topLayerLeavesCount; i++){
|
|
||||||
// Entity leafBlock = EntityCreationUtils.createClientSpatialEntity();
|
|
||||||
// EntityCreationUtils.makeEntityDrawable(leafBlock, "Models/foliageBlockTemplate1Test1.fbx");
|
|
||||||
// float radius = maxRadius * (1.0f - (leafLayer / (float)layerCount));
|
|
||||||
// double x = radius * Math.cos(i * (Math.PI * 2.0 / (float)topLayerLeavesCount) + topLayerRotationOffset);
|
|
||||||
// double z = radius * Math.sin(i * (Math.PI * 2.0 / (float)topLayerLeavesCount) + topLayerRotationOffset);
|
|
||||||
// EntityUtils.getPosition(leafBlock).set(x,startingHeight + leafLayer * spacingBetweenLayers,z);
|
|
||||||
// EntityUtils.getScale(leafBlock).set(1);
|
|
||||||
// Quaterniond rotation = EntityUtils.getRotation(leafBlock);
|
|
||||||
// rotation.rotateLocalX(treeRandom.nextFloat());
|
|
||||||
// rotation.rotateLocalY(treeRandom.nextFloat());
|
|
||||||
// rotation.rotateLocalZ(treeRandom.nextFloat());
|
|
||||||
// // Globals.clientSceneWrapper.getScene().registerBehaviorTree(new BehaviorTree() {
|
|
||||||
// // double initialX = rotation.x;
|
|
||||||
// // double initialY = rotation.y;
|
|
||||||
// // double initialZ = rotation.z;
|
|
||||||
// // public void simulate(float deltaTime) {
|
|
||||||
// // Quaterniond rotation = EntityUtils.getRotation(leafBlock);
|
|
||||||
// // rotation.rotateLocalX(
|
|
||||||
// // treeRandom.nextFloat() * 0.001f
|
|
||||||
// // );
|
|
||||||
// // rotation.rotateLocalY(treeRandom.nextFloat() * 0.001f);
|
|
||||||
// // rotation.rotateLocalZ(treeRandom.nextFloat() * 0.001f);
|
|
||||||
// // }});
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//attach btress
|
//attach btress
|
||||||
//..attach wind
|
//..attach wind
|
||||||
//...
|
//...
|
||||||
|
|
||||||
return rVal;
|
return trunkChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static void clientGenerateBranches(String type, Entity parent, Random rand, Vector3d currentPosition, Quaterniond currentAbsoluteRotation, float scalar){
|
public static void clientGenerateBranchesAlt(
|
||||||
// float scalarFalloffFactor = 0.15f;
|
TreeModel type,
|
||||||
// if(scalar > 0.25){
|
Entity parent,
|
||||||
// //how much does it peel off of the current vector
|
Random rand,
|
||||||
// double peelRotation = (rand.nextFloat() * 0.4 + 0.1);
|
Vector3d parentPosition, // The parent's origin bone's position in space
|
||||||
// //the initial rotation around Y that the branch will peel towards
|
Quaterniond parentRotation, // The parent's origin bone's rotation
|
||||||
// double offsetRotation = rand.nextFloat();
|
Vector3d offsetFromParent, // The offset from the parent's origin bone that this branch's origin bone should be at
|
||||||
// int branchNum = rand.nextInt(2) + 2;
|
Quaternionf rotationFromParent, // The rotation of the parent's extended bone. Should be equivalent to the origin bone's rotation on this branch
|
||||||
// for(int i = 0; i < 1; i++){
|
float scalar,
|
||||||
// //get new rotation
|
int currentSegmentNumber,
|
||||||
// double pitchFactor = Math.sin(offsetRotation);
|
boolean isCentralTrunk
|
||||||
// double rollFactor = Math.cos(offsetRotation);
|
){
|
||||||
// //update offsetrotation
|
//how fast do the branches shrink in size
|
||||||
// offsetRotation = offsetRotation + i * 2.0 * Math.PI / (float)branchNum;
|
float scalarFalloffFactor = type.getLimbScalarFalloffFactor();
|
||||||
|
//the minimum branch size before we stop generating branch segments/trunk segments
|
||||||
|
float minimumScalar = type.getMinimumLimbScalar();
|
||||||
|
//how high is the model for a single branch segment
|
||||||
|
float treeSegmentHeight = type.getBranchHeight();
|
||||||
|
//how much to spread the branches along the current segment
|
||||||
|
float minimumSegmentDispersion = type.getMinimumLimbDispersion();
|
||||||
|
float dispersionSpread = type.getMaximumLimbDispersion() - type.getMinimumLimbDispersion();
|
||||||
|
//the number of branches to make per segment
|
||||||
|
int minBranches = type.getMinimumNumberForks();
|
||||||
|
int maxBranches = type.getMaximumNumberForks();
|
||||||
|
//the maximum number of segments in an single arc for both trunk and branches
|
||||||
|
int maximumTrunkSegments = type.getMaximumTrunkSegments();
|
||||||
|
int maximumBranchSegments = type.getMaximumBranchSegments();
|
||||||
|
|
||||||
|
if(scalar > minimumScalar && currentSegmentNumber < maximumBranchSegments){
|
||||||
|
int minimumSegmentToSpawnLeaves = type.getMinimumSegmentToSpawnLeaves();
|
||||||
|
|
||||||
// //the rotation applied to the bone
|
//how much does it peel off of the current vector
|
||||||
// Quaternionf boneRotation = new Quaternionf(0,0,0,1).rotateLocalX((float)(pitchFactor * peelRotation)).rotateLocalZ((float)(rollFactor * peelRotation)).normalize();
|
double peelRotation = (rand.nextFloat() * dispersionSpread + minimumSegmentDispersion);
|
||||||
|
//the initial rotation around Y that the branch will peel towards
|
||||||
|
double offsetRotation = 0;
|
||||||
|
double rotationInitialOffset = rand.nextFloat();
|
||||||
|
int branchNum = rand.nextInt(maxBranches - minBranches) + minBranches;
|
||||||
|
for(int i = 0; i < branchNum; i++){
|
||||||
|
|
||||||
// //The new absolute rotation at the end of the bone
|
//what we want to solve for:
|
||||||
// Quaterniond newAbsoluteRotation = new Quaterniond(currentAbsoluteRotation).mul(new Quaterniond(boneRotation.x,boneRotation.y,boneRotation.z,boneRotation.w)).normalize();
|
//get parent position + rotation
|
||||||
|
//get an offset from the parent position for this position
|
||||||
|
//get a rotation from the parent rotation for this rotation
|
||||||
|
//get an offset from the current position for the child position
|
||||||
|
//get a rotation from the current rotation for the child rotation
|
||||||
|
|
||||||
|
//calculate transform from parent entity
|
||||||
|
//this is the transform that will be applied every time the attachutils updates
|
||||||
|
Matrix4f transformFromParent = new Matrix4f()
|
||||||
|
.translate(new Vector3f(
|
||||||
|
(float)offsetFromParent.x,
|
||||||
|
(float)offsetFromParent.y,
|
||||||
|
(float)offsetFromParent.z
|
||||||
|
))
|
||||||
|
.rotate(new Quaternionf(
|
||||||
|
(float)rotationFromParent.x,
|
||||||
|
(float)rotationFromParent.y,
|
||||||
|
(float)rotationFromParent.z,
|
||||||
|
(float)rotationFromParent.w
|
||||||
|
));
|
||||||
|
|
||||||
|
//calculate combined transform
|
||||||
|
Matrix4f combinedTransform = new Matrix4f().translate(new Vector3f(
|
||||||
|
(float)parentPosition.x,
|
||||||
|
(float)parentPosition.y,
|
||||||
|
(float)parentPosition.z
|
||||||
|
)).rotate(new Quaternionf(
|
||||||
|
(float)parentRotation.x,
|
||||||
|
(float)parentRotation.y,
|
||||||
|
(float)parentRotation.z,
|
||||||
|
(float)parentRotation.w
|
||||||
|
)).mul(transformFromParent);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//calculate current branch's stuff
|
||||||
|
//get current position
|
||||||
|
Vector4f currentPositionf = combinedTransform.transform(new Vector4f(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
));
|
||||||
|
Vector3d currentPosition = new Vector3d(currentPositionf.x,currentPositionf.y,currentPositionf.z);
|
||||||
|
|
||||||
|
//The new absolute rotation at the end of the bone
|
||||||
|
Quaterniond currentAbsoluteRotation = combinedTransform.getNormalizedRotation(new Quaterniond()).normalize();
|
||||||
|
|
||||||
// //calculates the bone transform matrix
|
|
||||||
// Matrix4f transform = new Matrix4f().identity().rotate(boneRotation).scale(scalar - scalarFalloffFactor,1,scalar - scalarFalloffFactor);
|
|
||||||
|
|
||||||
// Matrix4f newPositionTransform = new Matrix4f().identity().rotate(new Quaternionf(
|
|
||||||
// (float)currentAbsoluteRotation.x,
|
|
||||||
// (float)currentAbsoluteRotation.y,
|
|
||||||
// (float)currentAbsoluteRotation.z,
|
|
||||||
// (float)currentAbsoluteRotation.w
|
|
||||||
// )).rotate(boneRotation).scale(scalar - scalarFalloffFactor,1,scalar - scalarFalloffFactor);
|
|
||||||
|
|
||||||
|
|
||||||
// //create entity
|
|
||||||
// Entity branch = EntityCreationUtils.createClientSpatialEntity();
|
|
||||||
// InstancedActor instancedActor = InstancedEntityUtils.makeEntityInstancedWithModelTransform(branch, branchInstanceTemplate, modelMatrixAttribute);
|
|
||||||
// instancedActor.setAttribute(boneMatrixAttribute, transform);
|
|
||||||
// instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
|
||||||
|
|
||||||
|
|
||||||
// //debug output
|
|
||||||
// Vector4f transformLocal = newPositionTransform.transform(new Vector4f(0,3,0,1));
|
|
||||||
// Vector3d transformedPosition = new Vector3d(currentPosition).add(transformLocal.x,transformLocal.y,transformLocal.z);
|
|
||||||
|
|
||||||
// //set entity stuuff
|
|
||||||
// EntityUtils.getPosition(branch).set(currentPosition);
|
|
||||||
// EntityUtils.getScale(branch).set(scalar,1,scalar);
|
|
||||||
// EntityUtils.getRotation(branch).set(currentAbsoluteRotation);
|
|
||||||
// Vector3d newPosition = new Vector3d(
|
|
||||||
// transformLocal.x,
|
|
||||||
// transformLocal.y,
|
|
||||||
// transformLocal.z
|
|
||||||
// ).add(currentPosition.x,currentPosition.y,currentPosition.z);
|
|
||||||
// AttachUtils.clientAttachEntityAtCurrentOffset(parent, branch);
|
|
||||||
|
|
||||||
// //debug stuff
|
|
||||||
// Entity debugSphere = EntityCreationUtils.createClientSpatialEntity();
|
|
||||||
// EntityCreationUtils.makeEntityDrawable(debugSphere, "Models/unitsphere_1.fbx");
|
|
||||||
// EntityUtils.getScale(debugSphere).set(0.5f);
|
|
||||||
// EntityUtils.getPosition(debugSphere).set(newPosition);
|
|
||||||
|
|
||||||
|
|
||||||
// System.out.println(transformedPosition);
|
|
||||||
// System.out.println("vs");
|
//calculate child stuff
|
||||||
// System.out.println(newPosition);
|
|
||||||
// System.out.println();
|
|
||||||
|
|
||||||
// clientGenerateBranches(type, branch, rand, newPosition, newAbsoluteRotation, scalar - scalarFalloffFactor);
|
//update offsetrotation
|
||||||
// }
|
offsetRotation = rotationInitialOffset + (i + 1) * (2.0 * Math.PI / (float)branchNum);
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public static void clientGenerateBranches(String type, Entity parent, Random rand, Matrix4f transform, float scalar){
|
|
||||||
float scalarFalloffFactor = 0.15f;
|
|
||||||
if(scalar > 0.25){
|
|
||||||
//how much does it peel off of the current vector
|
|
||||||
double peelRotation = (rand.nextFloat() * 0.4 + 0.1);
|
|
||||||
//the initial rotation around Y that the branch will peel towards
|
|
||||||
double offsetRotation = rand.nextFloat();
|
|
||||||
int branchNum = rand.nextInt(2) + 2;
|
|
||||||
for(int i = 0; i < branchNum; i++){
|
|
||||||
//get new rotation
|
//get new rotation
|
||||||
double pitchFactor = Math.sin(offsetRotation);
|
double pitchFactor = Math.sin(offsetRotation);
|
||||||
double rollFactor = Math.cos(offsetRotation);
|
double rollFactor = Math.cos(offsetRotation);
|
||||||
//update offsetrotation
|
|
||||||
offsetRotation = offsetRotation + (i + 1) * 2.0 * Math.PI / (float)branchNum;
|
|
||||||
|
|
||||||
//the rotation applied to the bone
|
//the rotation applied to the bone
|
||||||
Quaternionf boneRotation = new Quaternionf(0,0,0,1).rotateLocalX((float)(pitchFactor * peelRotation)).rotateLocalZ((float)(rollFactor * peelRotation)).normalize();
|
Quaternionf boneRotation = new Quaternionf(0,0,0,1).rotateLocalX((float)(pitchFactor * peelRotation)).rotateLocalZ((float)(rollFactor * peelRotation)).normalize();
|
||||||
|
|
||||||
//get current position
|
|
||||||
Vector4f currentPositionf = transform.transform(new Vector4f(0,0,0,1));
|
|
||||||
Vector3d currentPosition = new Vector3d(currentPositionf.x,currentPositionf.y,currentPositionf.z);
|
|
||||||
|
|
||||||
//The new absolute rotation at the end of the bone
|
|
||||||
Quaterniond currentAbsoluteRotation = transform.getNormalizedRotation(new Quaterniond()).normalize();
|
|
||||||
// Quaterniond newAbsoluteRotation = new Quaterniond(currentAbsoluteRotation).mul(new Quaterniond(boneRotation.x,boneRotation.y,boneRotation.z,boneRotation.w)).normalize();
|
|
||||||
|
|
||||||
//calculates the bone transform matrix
|
//calculates the bone transform matrix
|
||||||
Matrix4f boneTransform = new Matrix4f().identity().rotate(boneRotation);
|
Matrix4f boneTransform = new Matrix4f().identity().rotate(boneRotation);
|
||||||
|
|
||||||
|
//calculate attachment transform
|
||||||
|
// Matrix4f attachmentTransform = new Matrix4f().identity().rotate(new Quaternionf(
|
||||||
|
// (float)currentAbsoluteRotation.x,
|
||||||
|
// (float)currentAbsoluteRotation.y,
|
||||||
|
// (float)currentAbsoluteRotation.z,
|
||||||
|
// (float)currentAbsoluteRotation.w
|
||||||
|
// )).translate(0,treeSegmentHeight,0);
|
||||||
|
|
||||||
//new position transform
|
//new position transform
|
||||||
Matrix4f newPositionTransform = new Matrix4f(transform).mul(boneTransform).translate(0,3,0);
|
Matrix4f newPositionTransform = new Matrix4f().rotate(boneRotation).translate(0,treeSegmentHeight,0);
|
||||||
|
|
||||||
|
Vector4f newPositionRaw = newPositionTransform.transform(new Vector4f(0,0,0,1));
|
||||||
|
Vector3d newPosition = new Vector3d(newPositionRaw.x,newPositionRaw.y,newPositionRaw.z);
|
||||||
|
|
||||||
//get new scalar
|
//get new scalar
|
||||||
float newScalar = scalar - scalarFalloffFactor;
|
float newScalar = scalar - scalarFalloffFactor;
|
||||||
@ -278,28 +270,283 @@ public class ProceduralTree {
|
|||||||
instancedActor.setAttribute(baseSizeAttribute, scalar);
|
instancedActor.setAttribute(baseSizeAttribute, scalar);
|
||||||
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
||||||
|
|
||||||
|
|
||||||
//debug output
|
|
||||||
// Vector4f newPositionF = newPositionTransform.transform(new Vector4f(0,0,0,1));
|
|
||||||
// Vector3d newAbsolutePosition = new Vector3d(newPositionF.x,newPositionF.y,newPositionF.z);
|
|
||||||
|
|
||||||
//set entity stuuff
|
//set entity stuuff
|
||||||
EntityUtils.getPosition(branch).set(currentPosition);
|
EntityUtils.getPosition(branch).set(currentPosition);
|
||||||
EntityUtils.getScale(branch).set(1,1,1);
|
EntityUtils.getScale(branch).set(1,1,1);
|
||||||
EntityUtils.getRotation(branch).set(currentAbsoluteRotation);
|
EntityUtils.getRotation(branch).set(currentAbsoluteRotation);
|
||||||
AttachUtils.clientAttachEntityAtCurrentOffset(parent, branch);
|
// AttachUtils.clientAttachEntityAtCurrentOffset(parent, branch);
|
||||||
|
AttachUtils.clientAttachEntityAtTransform(parent, branch, transformFromParent);
|
||||||
|
|
||||||
//debug stuff
|
//debug stuff
|
||||||
|
// Vector4f newPositionF = newPositionTransform.transform(new Vector4f(0,0,0,1));
|
||||||
|
// Vector3d newAbsolutePosition = new Vector3d(newPositionF.x,newPositionF.y,newPositionF.z);
|
||||||
// Entity debugSphere = EntityCreationUtils.createClientSpatialEntity();
|
// Entity debugSphere = EntityCreationUtils.createClientSpatialEntity();
|
||||||
// EntityCreationUtils.makeEntityDrawable(debugSphere, "Models/unitsphere_1.fbx");
|
// EntityCreationUtils.makeEntityDrawable(debugSphere, "Models/unitsphere_1.fbx");
|
||||||
// EntityUtils.getScale(debugSphere).set(0.5f);
|
// EntityUtils.getScale(debugSphere).set(0.5f);
|
||||||
// EntityUtils.getPosition(debugSphere).set(newAbsolutePosition);
|
// EntityUtils.getPosition(debugSphere).set(newAbsolutePosition);
|
||||||
|
|
||||||
|
//attach leaf blobs
|
||||||
|
if(
|
||||||
|
!isCentralTrunk &&
|
||||||
|
currentSegmentNumber >= minimumSegmentToSpawnLeaves
|
||||||
|
){
|
||||||
|
// createLeafBlobsOnBranch(type,rand,transform,boneTransform,branch);
|
||||||
|
}
|
||||||
|
|
||||||
clientGenerateBranches(type, branch, rand, newPositionTransform, scalar - scalarFalloffFactor);
|
//recurse
|
||||||
|
clientGenerateBranchesAlt(
|
||||||
|
type,
|
||||||
|
branch,
|
||||||
|
rand,
|
||||||
|
currentPosition,
|
||||||
|
currentAbsoluteRotation,
|
||||||
|
newPosition,
|
||||||
|
boneRotation,
|
||||||
|
scalar - scalarFalloffFactor,
|
||||||
|
currentSegmentNumber + 1,
|
||||||
|
false //can't be central trunk
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates branches
|
||||||
|
* @param type The type of branch
|
||||||
|
* @param parent The immediate parent of the branch
|
||||||
|
* @param rand The random
|
||||||
|
* @param transform The current ik transform for the branch
|
||||||
|
* @param scalar The scalar for the current width of the branch
|
||||||
|
* @param isCentralTrunk True if the tree should generate a central trunk with branches coming off of it
|
||||||
|
*/
|
||||||
|
public static void clientGenerateBranches(
|
||||||
|
TreeModel type,
|
||||||
|
Entity parent,
|
||||||
|
Random rand,
|
||||||
|
Matrix4f transform,
|
||||||
|
float scalar,
|
||||||
|
int currentSegmentNumber,
|
||||||
|
boolean isCentralTrunk
|
||||||
|
){
|
||||||
|
//how fast do the branches shrink in size
|
||||||
|
float scalarFalloffFactor = type.getLimbScalarFalloffFactor();
|
||||||
|
//the minimum branch size before we stop generating branch segments/trunk segments
|
||||||
|
float minimumScalar = type.getMinimumLimbScalar();
|
||||||
|
//how high is the model for a single branch segment
|
||||||
|
float treeSegmentHeight = type.getBranchHeight();
|
||||||
|
//how much to spread the branches along the current segment
|
||||||
|
float minimumSegmentDispersion = type.getMinimumLimbDispersion();
|
||||||
|
float dispersionSpread = type.getMaximumLimbDispersion() - type.getMinimumLimbDispersion();
|
||||||
|
//the number of branches to make per segment
|
||||||
|
int minBranches = type.getMinimumNumberForks();
|
||||||
|
int maxBranches = type.getMaximumNumberForks();
|
||||||
|
//the maximum number of segments in an single arc for both trunk and branches
|
||||||
|
int maximumTrunkSegments = type.getMaximumTrunkSegments();
|
||||||
|
int maximumBranchSegments = type.getMaximumBranchSegments();
|
||||||
|
|
||||||
|
if(scalar > minimumScalar && currentSegmentNumber < maximumTrunkSegments){
|
||||||
|
boolean hasCentralTrunk = type.getCentralTrunk();
|
||||||
|
//if there is a central trunk and this is the central trunk, generate the next central trunk segment
|
||||||
|
if(isCentralTrunk && hasCentralTrunk){
|
||||||
|
//the rotation applied to the bone
|
||||||
|
Quaternionf boneRotation = new Quaternionf(0,0,0,1).normalize();
|
||||||
|
|
||||||
|
//get current position
|
||||||
|
Vector4f currentPositionf = transform.transform(new Vector4f(0,0,0,1));
|
||||||
|
Vector3d currentPosition = new Vector3d(currentPositionf.x,currentPositionf.y,currentPositionf.z);
|
||||||
|
|
||||||
|
//The new absolute rotation at the end of the bone
|
||||||
|
Quaterniond currentAbsoluteRotation = transform.getNormalizedRotation(new Quaterniond()).normalize();
|
||||||
|
|
||||||
|
//calculates the bone transform matrix
|
||||||
|
Matrix4f boneTransform = new Matrix4f().identity().rotate(boneRotation);
|
||||||
|
|
||||||
|
//calculate attachment transform
|
||||||
|
Matrix4f attachmentTransform = new Matrix4f().identity().translate(0,treeSegmentHeight,0).rotate(boneRotation);
|
||||||
|
|
||||||
|
//new position transform
|
||||||
|
Matrix4f newPositionTransform = new Matrix4f(transform).mul(boneTransform);
|
||||||
|
|
||||||
|
//get new scalar
|
||||||
|
float newScalar = scalar - scalarFalloffFactor;
|
||||||
|
|
||||||
|
|
||||||
|
//create entity
|
||||||
|
Entity branch = EntityCreationUtils.createClientSpatialEntity();
|
||||||
|
InstancedActor instancedActor = InstancedEntityUtils.makeEntityInstancedWithModelTransform(branch, branchInstanceTemplate, modelMatrixAttribute);
|
||||||
|
instancedActor.setAttribute(boneMatrixAttribute, boneTransform.scale(newScalar,1,newScalar));
|
||||||
|
instancedActor.setAttribute(baseSizeAttribute, scalar);
|
||||||
|
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
||||||
|
|
||||||
|
//set entity stuuff
|
||||||
|
EntityUtils.getPosition(branch).set(currentPosition);
|
||||||
|
EntityUtils.getScale(branch).set(1,1,1);
|
||||||
|
EntityUtils.getRotation(branch).set(currentAbsoluteRotation);
|
||||||
|
// AttachUtils.clientAttachEntityAtCurrentOffset(parent, branch);
|
||||||
|
// AttachUtils.clientAttachEntityAtTransform(parent, branch, attachmentTransform);
|
||||||
|
|
||||||
|
//recurse
|
||||||
|
clientGenerateBranches(
|
||||||
|
type,
|
||||||
|
branch,
|
||||||
|
rand,
|
||||||
|
newPositionTransform,
|
||||||
|
scalar - scalarFalloffFactor,
|
||||||
|
currentSegmentNumber + 1,
|
||||||
|
true //can't be central trunk
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scalar > minimumScalar && currentSegmentNumber < maximumBranchSegments){
|
||||||
|
int minimumSegmentToSpawnLeaves = type.getMinimumSegmentToSpawnLeaves();
|
||||||
|
|
||||||
|
//how much does it peel off of the current vector
|
||||||
|
double peelRotation = (rand.nextFloat() * dispersionSpread + minimumSegmentDispersion);
|
||||||
|
//the initial rotation around Y that the branch will peel towards
|
||||||
|
double offsetRotation = 0;
|
||||||
|
double rotationInitialOffset = rand.nextFloat();
|
||||||
|
int branchNum = rand.nextInt(maxBranches - minBranches) + minBranches;
|
||||||
|
for(int i = 0; i < branchNum; i++){
|
||||||
|
//update offsetrotation
|
||||||
|
offsetRotation = rotationInitialOffset + (i + 1) * (2.0 * Math.PI / (float)branchNum);
|
||||||
|
//get new rotation
|
||||||
|
double pitchFactor = Math.sin(offsetRotation);
|
||||||
|
double rollFactor = Math.cos(offsetRotation);
|
||||||
|
|
||||||
|
//the rotation applied to the bone
|
||||||
|
Quaternionf boneRotation = new Quaternionf(0,0,0,1).rotateLocalX((float)(pitchFactor * peelRotation)).rotateLocalZ((float)(rollFactor * peelRotation)).normalize();
|
||||||
|
|
||||||
|
//get current position
|
||||||
|
Vector4f currentPositionf = transform.transform(new Vector4f(0,0,0,1));
|
||||||
|
Vector3d currentPosition = new Vector3d(currentPositionf.x,currentPositionf.y,currentPositionf.z);
|
||||||
|
|
||||||
|
//The new absolute rotation at the end of the bone
|
||||||
|
Quaterniond currentAbsoluteRotation = transform.getNormalizedRotation(new Quaterniond()).normalize();
|
||||||
|
|
||||||
|
//calculates the bone transform matrix
|
||||||
|
Matrix4f boneTransform = new Matrix4f().identity().rotate(boneRotation);
|
||||||
|
|
||||||
|
//new position transform
|
||||||
|
Matrix4f newPositionTransform = new Matrix4f(transform).mul(boneTransform).translate(0,treeSegmentHeight,0);
|
||||||
|
|
||||||
|
//get new scalar
|
||||||
|
float newScalar = scalar - scalarFalloffFactor;
|
||||||
|
|
||||||
|
|
||||||
|
//create entity
|
||||||
|
Entity branch = EntityCreationUtils.createClientSpatialEntity();
|
||||||
|
InstancedActor instancedActor = InstancedEntityUtils.makeEntityInstancedWithModelTransform(branch, branchInstanceTemplate, modelMatrixAttribute);
|
||||||
|
instancedActor.setAttribute(boneMatrixAttribute, boneTransform.scale(newScalar,1,newScalar));
|
||||||
|
instancedActor.setAttribute(baseSizeAttribute, scalar);
|
||||||
|
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
||||||
|
|
||||||
|
//set entity stuuff
|
||||||
|
EntityUtils.getPosition(branch).set(currentPosition);
|
||||||
|
EntityUtils.getScale(branch).set(1,1,1);
|
||||||
|
EntityUtils.getRotation(branch).set(currentAbsoluteRotation);
|
||||||
|
// AttachUtils.clientAttachEntityAtCurrentOffset(parent, branch);
|
||||||
|
// AttachUtils.clientAttachEntityAtTransform(parent, branch, attachmentTransform);
|
||||||
|
|
||||||
|
//debug stuff
|
||||||
|
// Vector4f newPositionF = newPositionTransform.transform(new Vector4f(0,0,0,1));
|
||||||
|
// Vector3d newAbsolutePosition = new Vector3d(newPositionF.x,newPositionF.y,newPositionF.z);
|
||||||
|
// Entity debugSphere = EntityCreationUtils.createClientSpatialEntity();
|
||||||
|
// EntityCreationUtils.makeEntityDrawable(debugSphere, "Models/unitsphere_1.fbx");
|
||||||
|
// EntityUtils.getScale(debugSphere).set(0.5f);
|
||||||
|
// EntityUtils.getPosition(debugSphere).set(newAbsolutePosition);
|
||||||
|
|
||||||
|
//attach leaf blobs
|
||||||
|
if(
|
||||||
|
!isCentralTrunk &&
|
||||||
|
currentSegmentNumber >= minimumSegmentToSpawnLeaves
|
||||||
|
){
|
||||||
|
createLeafBlobsOnBranch(type,rand,transform,boneTransform,branch);
|
||||||
|
}
|
||||||
|
|
||||||
|
//recurse
|
||||||
|
clientGenerateBranches(
|
||||||
|
type,
|
||||||
|
branch,
|
||||||
|
rand,
|
||||||
|
newPositionTransform,
|
||||||
|
scalar - scalarFalloffFactor,
|
||||||
|
currentSegmentNumber + 1,
|
||||||
|
false //can't be central trunk
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates leaf blobs around branch segments
|
||||||
|
* @param type The type of tree
|
||||||
|
* @param rand The random
|
||||||
|
* @param transform The current branch segment transform
|
||||||
|
* @param boneTransform The bone transform to the next branch segment
|
||||||
|
* @param branch The branch entity
|
||||||
|
*/
|
||||||
|
private static void createLeafBlobsOnBranch(TreeModel type, Random rand, Matrix4f transform, Matrix4f boneTransform, Entity branch){
|
||||||
|
//how high is the model for a single branch segment
|
||||||
|
float treeSegmentHeight = type.getBranchHeight();
|
||||||
|
|
||||||
|
float minBranchHeightToStartSpawningLeaves = type.getMinBranchHeightToStartSpawningLeaves();
|
||||||
|
float maxBranchHeightToStartSpawningLeaves = type.getMaxBranchHeightToStartSpawningLeaves();
|
||||||
|
float leafIncrement = type.getLeafIncrement();
|
||||||
|
int minLeavesToSpawnPerPoint = type.getMinLeavesToSpawnPerPoint();
|
||||||
|
int maxLeavesToSpawnPerPoint = type.getMaxLeavesToSpawnPerPoint();
|
||||||
|
for(
|
||||||
|
float positionAlongBranch = minBranchHeightToStartSpawningLeaves;
|
||||||
|
positionAlongBranch < maxBranchHeightToStartSpawningLeaves;
|
||||||
|
positionAlongBranch = positionAlongBranch + leafIncrement
|
||||||
|
){
|
||||||
|
int numToSpawn = rand.nextInt(maxLeavesToSpawnPerPoint - minLeavesToSpawnPerPoint) + minLeavesToSpawnPerPoint;
|
||||||
|
double currentLeafRotation = rand.nextFloat();
|
||||||
|
float distanceFromCenter = type.getLeafDistanceFromCenter();
|
||||||
|
for(int leafIncrementer = 0; leafIncrementer < numToSpawn; leafIncrementer++){
|
||||||
|
//offset radially
|
||||||
|
float xOffset = (float)Math.sin(currentLeafRotation) * distanceFromCenter;
|
||||||
|
float zOffset = (float)Math.cos(currentLeafRotation) * distanceFromCenter;
|
||||||
|
//update offsetrotation
|
||||||
|
currentLeafRotation = currentLeafRotation + (leafIncrementer + 1) * 2.0 * Math.PI / (float)numToSpawn;
|
||||||
|
//construct model matrix
|
||||||
|
Matrix4f leafPositionTransform = new Matrix4f(transform).mul(boneTransform).translate(xOffset,positionAlongBranch,zOffset);
|
||||||
|
Vector4f leafCurrentPositionf = leafPositionTransform.transform(new Vector4f(0,0,0,1));
|
||||||
|
Vector3d leafCurrentPosition = new Vector3d(leafCurrentPositionf.x,leafCurrentPositionf.y,leafCurrentPositionf.z);
|
||||||
|
//create entity
|
||||||
|
Entity leaf = EntityCreationUtils.createClientSpatialEntity();
|
||||||
|
InstancedActor leafInstancedActor = InstancedEntityUtils.makeEntityInstancedWithModelTransform(leaf, leafInstanceTemplate, modelMatrixAttribute);
|
||||||
|
leafInstancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
||||||
|
leafInstancedActor.setAttribute(leafColorAttribute, new Vector3f(36/255.0f,173/255.0f,31/255.0f));
|
||||||
|
|
||||||
|
//set entity stuuff
|
||||||
|
EntityUtils.getPosition(leaf).set(leafCurrentPosition);
|
||||||
|
EntityUtils.getScale(leaf).set(1,1,1);
|
||||||
|
EntityUtils.getRotation(leaf).set(new Quaterniond().identity());
|
||||||
|
AttachUtils.clientAttachEntityAtCurrentOffset(branch, leaf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The behavior tree for branches swaying in the wind
|
||||||
|
*/
|
||||||
|
static class BranchBehaviorTree implements BehaviorTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param branch The branch entity
|
||||||
|
*/
|
||||||
|
protected BranchBehaviorTree(Entity branch){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simulate(float deltaTime) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,8 @@ public class FoliageType {
|
|||||||
|
|
||||||
//Denotes an ambient foliage that will be placed on a voxel
|
//Denotes an ambient foliage that will be placed on a voxel
|
||||||
public static final String TOKEN_AMBIENT = "AMBIENT";
|
public static final String TOKEN_AMBIENT = "AMBIENT";
|
||||||
|
//Denotes an tree object
|
||||||
|
public static final String TOKEN_TREE = "TREE";
|
||||||
|
|
||||||
//the name of the foliage type
|
//the name of the foliage type
|
||||||
String name;
|
String name;
|
||||||
@ -20,6 +22,8 @@ public class FoliageType {
|
|||||||
GrowthModel growthModel;
|
GrowthModel growthModel;
|
||||||
//the list of tokens
|
//the list of tokens
|
||||||
List<String> tokens;
|
List<String> tokens;
|
||||||
|
//The model for a tree
|
||||||
|
TreeModel treeModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name of the foliage type
|
* Gets the name of the foliage type
|
||||||
@ -60,5 +64,13 @@ public class FoliageType {
|
|||||||
public GrowthModel getGrowthModel(){
|
public GrowthModel getGrowthModel(){
|
||||||
return growthModel;
|
return growthModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tree model
|
||||||
|
* @return The tree model
|
||||||
|
*/
|
||||||
|
public TreeModel getTreeModel(){
|
||||||
|
return treeModel;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,206 @@
|
|||||||
|
package electrosphere.game.data.foliage.type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes characteristics about a type of tree (how do the limbs dispere, where to the leaves start growing, how sturdy is it, etc)
|
||||||
|
*/
|
||||||
|
public class TreeModel {
|
||||||
|
|
||||||
|
//how quickly do the limbs shrink
|
||||||
|
float limbScalarFalloffFactor;
|
||||||
|
|
||||||
|
//How small are the terminal limbs, basically how small can it get before it stops generating
|
||||||
|
float minimumLimbScalar;
|
||||||
|
|
||||||
|
//The maximum a single branch can disperse from the current line
|
||||||
|
float maximumLimbDispersion;
|
||||||
|
|
||||||
|
//The minimum a single branch must disperse from the current line
|
||||||
|
float minimumLimbDispersion;
|
||||||
|
|
||||||
|
//The minimum number of branch forks per iteration
|
||||||
|
int minimumNumberForks;
|
||||||
|
|
||||||
|
//The maximum number of branch forks per iteration
|
||||||
|
int maximumNumberForks;
|
||||||
|
|
||||||
|
//The height of a single branch, should be the height of the model
|
||||||
|
float branchHeight;
|
||||||
|
|
||||||
|
//if true, always generates a central trunk
|
||||||
|
boolean centralTrunk;
|
||||||
|
|
||||||
|
//The maximum number of linear segments for the trunk (ie how many times can a function recurse)
|
||||||
|
int maximumTrunkSegments;
|
||||||
|
|
||||||
|
//The maximum number of linear segments for the branch (ie how many times can a function recurse)
|
||||||
|
int maximumBranchSegments;
|
||||||
|
|
||||||
|
//The rate at which number of branch segments from the current trunk falls off over time
|
||||||
|
float maxBranchSegmentFalloffFactor;
|
||||||
|
|
||||||
|
//The minimum segment number required to start spawning leaves
|
||||||
|
int minimumSegmentToSpawnLeaves;
|
||||||
|
|
||||||
|
//the minimum distance along a given segment to start spawning leaves at
|
||||||
|
float minBranchHeightToStartSpawningLeaves;
|
||||||
|
|
||||||
|
//the maximum distance along a given segment to start spawning leaves at
|
||||||
|
float maxBranchHeightToStartSpawningLeaves;
|
||||||
|
|
||||||
|
//The increment along the branch segment to spawn leaves at
|
||||||
|
float leafIncrement;
|
||||||
|
|
||||||
|
//the minimum leaves to spawn per leaf point
|
||||||
|
int minLeavesToSpawnPerPoint;
|
||||||
|
|
||||||
|
//the maximum leaves to spawn per leaf point
|
||||||
|
int maxLeavesToSpawnPerPoint;
|
||||||
|
|
||||||
|
//The distance from the central line of a branch to spawn a leaf at
|
||||||
|
float leafDistanceFromCenter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* how quickly do the limbs shrink
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getLimbScalarFalloffFactor(){
|
||||||
|
return limbScalarFalloffFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How small are the terminal limbs
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getMinimumLimbScalar(){
|
||||||
|
return minimumLimbScalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum a single branch can disperse from the current line
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getMaximumLimbDispersion(){
|
||||||
|
return maximumLimbDispersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum a single branch must disperse from the current line
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getMinimumLimbDispersion(){
|
||||||
|
return minimumLimbDispersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum number of branch forks per iteration
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMinimumNumberForks(){
|
||||||
|
return minimumNumberForks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of branch forks per iteration
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMaximumNumberForks(){
|
||||||
|
return maximumNumberForks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The height of a single branch, should be the height of the model
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getBranchHeight(){
|
||||||
|
return branchHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if true, always generates a central trunk
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean getCentralTrunk(){
|
||||||
|
return centralTrunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of linear segments for the trunk (ie how many times can a function recurse)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMaximumTrunkSegments(){
|
||||||
|
return maximumTrunkSegments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of linear segments for the branch (ie how many times can a function recurse)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMaximumBranchSegments(){
|
||||||
|
return maximumBranchSegments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rate at which number of branch segments from the current trunk falls off over time
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getMaxBranchSegmentFalloffFactor(){
|
||||||
|
return maxBranchSegmentFalloffFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum segment number required to start spawning leaves
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMinimumSegmentToSpawnLeaves(){
|
||||||
|
return minimumSegmentToSpawnLeaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the minimum distance along a given segment to start spawning leaves at
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getMinBranchHeightToStartSpawningLeaves(){
|
||||||
|
return minBranchHeightToStartSpawningLeaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the maximum distance along a given segment to start spawning leaves at
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getMaxBranchHeightToStartSpawningLeaves(){
|
||||||
|
return maxBranchHeightToStartSpawningLeaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The increment along the branch segment to spawn leaves at
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getLeafIncrement(){
|
||||||
|
return leafIncrement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the minimum leaves to spawn per leaf point
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMinLeavesToSpawnPerPoint(){
|
||||||
|
return minLeavesToSpawnPerPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the maximum leaves to spawn per leaf point
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMaxLeavesToSpawnPerPoint(){
|
||||||
|
return maxLeavesToSpawnPerPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The distance from the central line of a branch to spawn a leaf at
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getLeafDistanceFromCenter(){
|
||||||
|
return leafDistanceFromCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -6,10 +6,12 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.joml.Matrix4d;
|
import org.joml.Matrix4d;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityDataStrings;
|
import electrosphere.entity.EntityDataStrings;
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.renderer.Model;
|
import electrosphere.renderer.Model;
|
||||||
import electrosphere.renderer.RenderPipelineState;
|
import electrosphere.renderer.RenderPipelineState;
|
||||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||||
@ -78,20 +80,22 @@ public class InstancedActor implements Comparable<InstancedActor> {
|
|||||||
} else {
|
} else {
|
||||||
attributes.put(attribute, new Matrix4f((Matrix4f)value));
|
attributes.put(attribute, new Matrix4f((Matrix4f)value));
|
||||||
}
|
}
|
||||||
}
|
} else if(value instanceof Matrix4d){
|
||||||
if(value instanceof Matrix4d){
|
|
||||||
if(attributes.containsKey(attribute)){
|
if(attributes.containsKey(attribute)){
|
||||||
((Matrix4d)attributes.get(attribute)).set((Matrix4d)value);
|
((Matrix4d)attributes.get(attribute)).set((Matrix4d)value);
|
||||||
} else {
|
} else {
|
||||||
attributes.put(attribute, new Matrix4d((Matrix4d)value));
|
attributes.put(attribute, new Matrix4d((Matrix4d)value));
|
||||||
}
|
}
|
||||||
}
|
} else if(
|
||||||
if(
|
|
||||||
value instanceof Double ||
|
value instanceof Double ||
|
||||||
value instanceof Float ||
|
value instanceof Float ||
|
||||||
value instanceof Integer
|
value instanceof Integer
|
||||||
){
|
){
|
||||||
attributes.put(attribute, value);
|
attributes.put(attribute, value);
|
||||||
|
} else if(value instanceof Vector3f){
|
||||||
|
attributes.put(attribute, value);
|
||||||
|
} else {
|
||||||
|
LoggerInterface.loggerRenderer.ERROR("Unsupported operation", new Exception());
|
||||||
}
|
}
|
||||||
// attributes.put(attribute, value);
|
// attributes.put(attribute, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -202,6 +202,16 @@ public class HomogenousInstancedArray {
|
|||||||
GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, bufferPointer);
|
GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, bufferPointer);
|
||||||
//tell opengl to send a new value from buffer for each instance (instead of whole buffer for every instance)
|
//tell opengl to send a new value from buffer for each instance (instead of whole buffer for every instance)
|
||||||
GL45.glVertexAttribDivisor(attributeIndex, 1);
|
GL45.glVertexAttribDivisor(attributeIndex, 1);
|
||||||
|
} else if(type == HomogenousBufferTypes.VEC3F){
|
||||||
|
GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, bufferPointer);
|
||||||
|
//enable attributes
|
||||||
|
GL45.glEnableVertexAttribArray(attributeIndex);
|
||||||
|
//update attribute to point to buffer at correct offset + stride
|
||||||
|
GL45.glVertexAttribPointer(attributeIndex, 3, GL45.GL_FLOAT, false, 0, 0);
|
||||||
|
//bind buffer
|
||||||
|
GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, bufferPointer);
|
||||||
|
//tell opengl to send a new value from buffer for each instance (instead of whole buffer for every instance)
|
||||||
|
GL45.glVertexAttribDivisor(attributeIndex, 1);
|
||||||
} else {
|
} else {
|
||||||
LoggerInterface.loggerRenderer.ERROR("Unsupported operation", new Exception());
|
LoggerInterface.loggerRenderer.ERROR("Unsupported operation", new Exception());
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user