Proper tree transforms
This commit is contained in:
parent
9811c18cf7
commit
f113f45317
@ -30,6 +30,39 @@
|
||||
"growthRate" : 0.001
|
||||
},
|
||||
"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
|
||||
#Sun Aug 20 22:06:17 EDT 2023
|
||||
buildNumber=10
|
||||
#Sat Sep 02 19:48:14 EDT 2023
|
||||
buildNumber=11
|
||||
|
||||
@ -240,7 +240,10 @@ public class ClientLoading {
|
||||
});
|
||||
|
||||
// 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);
|
||||
// }
|
||||
|
||||
|
||||
@ -171,6 +171,7 @@ public class EntityDataStrings {
|
||||
public static final String ATTACH_CHILDREN_LIST = "attachChildrenList";
|
||||
public static final String ATTACH_ROTATION_OFFSET = "attachRotationOffset";
|
||||
public static final String ATTACH_POSITION_OFFSET = "attachPositionOffset";
|
||||
public static final String ATTACH_TRANSFORM = "attachTransform";
|
||||
|
||||
/*
|
||||
Item Entity
|
||||
|
||||
@ -3,6 +3,7 @@ package electrosphere.entity;
|
||||
public class EntityTags {
|
||||
|
||||
public static final String BONE_ATTACHED = "boneAttached";
|
||||
public static final String TRANSFORM_ATTACHED = "transformAttached";
|
||||
public static final String COLLIDABLE = "collidable";
|
||||
public static final String SPRINTABLE = "sprintable";
|
||||
public static final String MOVEABLE = "moveable";
|
||||
|
||||
@ -45,6 +45,7 @@ public class Scene {
|
||||
tagEntityMap.put(EntityTags.ITEM, new HashSet<Entity>());
|
||||
tagEntityMap.put(EntityTags.GRAVITY, 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.List;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4d;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
*/
|
||||
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);
|
||||
} else {
|
||||
LinkedList<Entity> childrenEntities = new LinkedList<Entity> ();
|
||||
childrenEntities.add(toAttach);
|
||||
parent.putData(EntityDataStrings.ATTACH_CHILDREN_LIST, childrenEntities);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// FUNCTIONS TO UPDATE ATTACHMENTS FOR CURRENT FRAME
|
||||
//
|
||||
|
||||
public static void serverUpdateAttachedEntityPositions(ServerDataCell cell){
|
||||
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(){
|
||||
//update entities attached to bones of other entities
|
||||
for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){
|
||||
Entity parent;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Matrix4d parentTransform = new Matrix4d().identity();
|
||||
//update entities attached to centerpoint + transform of other entities
|
||||
for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.TRANSFORM_ATTACHED)){
|
||||
Entity parent;
|
||||
if((parent = (Entity)currentEntity.getData(EntityDataStrings.ATTACH_PARENT))!=null){
|
||||
Matrix4f transform;
|
||||
if((transform = getTransformOffset(currentEntity))!=null){
|
||||
//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)){
|
||||
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
|
||||
* @param parent The parent to attach to
|
||||
@ -169,7 +230,130 @@ public class AttachUtils {
|
||||
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){
|
||||
return e.containsKey(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
||||
}
|
||||
@ -185,6 +369,15 @@ public class AttachUtils {
|
||||
protected static Quaterniond getRotationOffset(Entity e){
|
||||
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){
|
||||
return e.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST) && !getChildrenList(e).isEmpty();
|
||||
@ -197,18 +390,6 @@ public class AttachUtils {
|
||||
public static LinkedList<Entity> getChildrenList(Entity e){
|
||||
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){
|
||||
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.instance.InstanceTemplate;
|
||||
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.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||
@ -33,6 +35,9 @@ public class ProceduralTree {
|
||||
//The instance template for the branch
|
||||
static InstanceTemplate branchInstanceTemplate;
|
||||
|
||||
//the instance template for a leaf blob
|
||||
static InstanceTemplate leafInstanceTemplate;
|
||||
|
||||
//The model attribute
|
||||
static final ShaderAttribute modelMatrixAttribute = new ShaderAttribute(new int[]{
|
||||
5,6,7,8
|
||||
@ -43,8 +48,11 @@ public class ProceduralTree {
|
||||
9,10,11,12
|
||||
});
|
||||
|
||||
//the size of the base of the branch segment, attribute
|
||||
static final ShaderAttribute baseSizeAttribute = new ShaderAttribute(13);
|
||||
|
||||
static final ShaderAttribute leafColorAttribute = new ShaderAttribute(9);
|
||||
|
||||
//The static setup logic
|
||||
static {
|
||||
//create map of attributes and register them
|
||||
@ -56,25 +64,30 @@ public class ProceduralTree {
|
||||
branchInstanceTemplate = InstanceTemplate.createInstanceTemplate(
|
||||
1000,
|
||||
"Models/proceduralTree2/proceduralTree2v2.fbx",
|
||||
"Shaders/proceduraltree/proceduraltree.vs",
|
||||
"Shaders/proceduraltree/proceduraltree.fs",
|
||||
"Shaders/instanced/proceduraltree/proceduraltree.vs",
|
||||
"Shaders/instanced/proceduraltree/proceduraltree.fs",
|
||||
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
|
||||
* @param type
|
||||
* @param seed
|
||||
* @return
|
||||
* @param type The type of tree as a string
|
||||
* @param seed The seed (lol) for the tree
|
||||
* @return The top level tree entity
|
||||
*/
|
||||
public static Entity clientGenerateProceduralTree(String type, long seed){
|
||||
Random treeRandom = new Random(seed);
|
||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||
|
||||
//generate trunk
|
||||
Entity trunkChild = EntityCreationUtils.createClientSpatialEntity();
|
||||
@ -83,189 +96,168 @@ public class ProceduralTree {
|
||||
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
|
||||
instancedActor.setAttribute(baseSizeAttribute, 1.0f);
|
||||
// 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
|
||||
//...
|
||||
// clientGenerateBranches(type, rVal, treeRandom, new Vector3d(0,heightSegments,0), new Quaterniond(0,0.7071068,0,0.7071068), heightSegments);
|
||||
int topLayerLeavesCount = treeRandom.nextInt(3) + 3;
|
||||
float topLayerRotationOffset = treeRandom.nextFloat();
|
||||
// for(int i = 0; i < topLayerLeavesCount; i++){
|
||||
// Entity leafBlock = EntityCreationUtils.createClientSpatialEntity();
|
||||
// EntityCreationUtils.makeEntityDrawable(leafBlock, "Models/foliageBlockTemplate1Test1.fbx");
|
||||
// float radius = 1;
|
||||
// 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,z);
|
||||
// DrawableUtils.makeEntityTransparent(leafBlock);
|
||||
// }
|
||||
|
||||
int layerCount = 8;
|
||||
int halfLayer = layerCount / 2;
|
||||
float maxRadius = 2f;
|
||||
float spacingBetweenLayers = 1;
|
||||
float layerDensityDecreaseRate = 3;
|
||||
int initialDensity = 20;
|
||||
float startingHeight = 4;
|
||||
// for(int leafLayer = 0; leafLayer < layerCount; leafLayer++){
|
||||
// topLayerLeavesCount = treeRandom.nextInt(3) + 3 * (int)(halfLayer * ((halfLayer - Math.abs(leafLayer - halfLayer))/(float)halfLayer));
|
||||
// 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);
|
||||
// // }});
|
||||
// }
|
||||
// }
|
||||
Matrix4f transform = new Matrix4f().identity().translate(0,3,0);
|
||||
FoliageType foliageType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
|
||||
TreeModel treeModel = foliageType.getTreeModel();
|
||||
// clientGenerateBranches(
|
||||
// treeModel,
|
||||
// trunkChild,
|
||||
// treeRandom,
|
||||
// transform,
|
||||
// 1,
|
||||
// 1,
|
||||
// true
|
||||
// );
|
||||
clientGenerateBranchesAlt(
|
||||
treeModel,
|
||||
trunkChild,
|
||||
treeRandom,
|
||||
new Vector3d(0,0,0),
|
||||
new Quaterniond(0,0,0,1),
|
||||
new Vector3d(0,3,0),
|
||||
new Quaternionf(0,0,0,1),
|
||||
1,
|
||||
1,
|
||||
true
|
||||
);
|
||||
|
||||
//attach btress
|
||||
//..attach wind
|
||||
//...
|
||||
|
||||
return rVal;
|
||||
return trunkChild;
|
||||
}
|
||||
|
||||
// public static void clientGenerateBranches(String type, Entity parent, Random rand, Vector3d currentPosition, Quaterniond currentAbsoluteRotation, 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 < 1; i++){
|
||||
// //get new rotation
|
||||
// double pitchFactor = Math.sin(offsetRotation);
|
||||
// double rollFactor = Math.cos(offsetRotation);
|
||||
// //update offsetrotation
|
||||
// offsetRotation = offsetRotation + i * 2.0 * Math.PI / (float)branchNum;
|
||||
public static void clientGenerateBranchesAlt(
|
||||
TreeModel type,
|
||||
Entity parent,
|
||||
Random rand,
|
||||
Vector3d parentPosition, // The parent's origin bone's position in space
|
||||
Quaterniond parentRotation, // The parent's origin bone's rotation
|
||||
Vector3d offsetFromParent, // The offset from the parent's origin bone that this branch's origin bone should be at
|
||||
Quaternionf rotationFromParent, // The rotation of the parent's extended bone. Should be equivalent to the origin bone's rotation on this branch
|
||||
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 < maximumBranchSegments){
|
||||
int minimumSegmentToSpawnLeaves = type.getMinimumSegmentToSpawnLeaves();
|
||||
|
||||
// //the rotation applied to the bone
|
||||
// Quaternionf boneRotation = new Quaternionf(0,0,0,1).rotateLocalX((float)(pitchFactor * peelRotation)).rotateLocalZ((float)(rollFactor * peelRotation)).normalize();
|
||||
//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++){
|
||||
|
||||
// //The new absolute rotation at the end of the bone
|
||||
// Quaterniond newAbsoluteRotation = new Quaterniond(currentAbsoluteRotation).mul(new Quaterniond(boneRotation.x,boneRotation.y,boneRotation.z,boneRotation.w)).normalize();
|
||||
//what we want to solve for:
|
||||
//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");
|
||||
// System.out.println(newPosition);
|
||||
// System.out.println();
|
||||
|
||||
//calculate child stuff
|
||||
|
||||
// clientGenerateBranches(type, branch, rand, newPosition, newAbsoluteRotation, scalar - scalarFalloffFactor);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
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++){
|
||||
//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);
|
||||
//update offsetrotation
|
||||
offsetRotation = offsetRotation + (i + 1) * 2.0 * Math.PI / (float)branchNum;
|
||||
|
||||
//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();
|
||||
// Quaterniond newAbsoluteRotation = new Quaterniond(currentAbsoluteRotation).mul(new Quaterniond(boneRotation.x,boneRotation.y,boneRotation.z,boneRotation.w)).normalize();
|
||||
|
||||
//calculates the bone transform matrix
|
||||
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
|
||||
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
|
||||
float newScalar = scalar - scalarFalloffFactor;
|
||||
@ -278,28 +270,283 @@ public class ProceduralTree {
|
||||
instancedActor.setAttribute(baseSizeAttribute, scalar);
|
||||
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
|
||||
EntityUtils.getPosition(branch).set(currentPosition);
|
||||
EntityUtils.getScale(branch).set(1,1,1);
|
||||
EntityUtils.getRotation(branch).set(currentAbsoluteRotation);
|
||||
AttachUtils.clientAttachEntityAtCurrentOffset(parent, branch);
|
||||
// AttachUtils.clientAttachEntityAtCurrentOffset(parent, branch);
|
||||
AttachUtils.clientAttachEntityAtTransform(parent, branch, transformFromParent);
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
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
|
||||
public static final String TOKEN_AMBIENT = "AMBIENT";
|
||||
//Denotes an tree object
|
||||
public static final String TOKEN_TREE = "TREE";
|
||||
|
||||
//the name of the foliage type
|
||||
String name;
|
||||
@ -20,6 +22,8 @@ public class FoliageType {
|
||||
GrowthModel growthModel;
|
||||
//the list of tokens
|
||||
List<String> tokens;
|
||||
//The model for a tree
|
||||
TreeModel treeModel;
|
||||
|
||||
/**
|
||||
* Gets the name of the foliage type
|
||||
@ -60,5 +64,13 @@ public class FoliageType {
|
||||
public GrowthModel getGrowthModel(){
|
||||
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.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.Model;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
@ -78,20 +80,22 @@ public class InstancedActor implements Comparable<InstancedActor> {
|
||||
} else {
|
||||
attributes.put(attribute, new Matrix4f((Matrix4f)value));
|
||||
}
|
||||
}
|
||||
if(value instanceof Matrix4d){
|
||||
} else if(value instanceof Matrix4d){
|
||||
if(attributes.containsKey(attribute)){
|
||||
((Matrix4d)attributes.get(attribute)).set((Matrix4d)value);
|
||||
} else {
|
||||
attributes.put(attribute, new Matrix4d((Matrix4d)value));
|
||||
}
|
||||
}
|
||||
if(
|
||||
} else if(
|
||||
value instanceof Double ||
|
||||
value instanceof Float ||
|
||||
value instanceof Integer
|
||||
){
|
||||
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);
|
||||
}
|
||||
|
||||
@ -202,6 +202,16 @@ public class HomogenousInstancedArray {
|
||||
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 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 {
|
||||
LoggerInterface.loggerRenderer.ERROR("Unsupported operation", new Exception());
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user