Procedural Tree Trunk code
This commit is contained in:
parent
a16a310b25
commit
9811c18cf7
@ -21,6 +21,39 @@
|
||||
"scale" : [0.0015, 0.0015, 0.0015]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path" : "Models/proceduralTree1/proceduralTrunk1.fbx",
|
||||
"meshes" : [
|
||||
{
|
||||
"meshName" : "Cube",
|
||||
"rotation" : [-0.7071068, 0.0, 0.0, 0.7071068],
|
||||
"offset" : [0.0, 0.0, 0.0],
|
||||
"scale" : [1.0, 1.0, 1.0]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path" : "Models/proceduralTree2/proceduralTree2.fbx",
|
||||
"meshes" : [
|
||||
{
|
||||
"meshName" : "Trunk",
|
||||
"rotation" : [-0.7071068, 0.0, 0.0, 0.7071068],
|
||||
"offset" : [0.0, 0.0, 0.0],
|
||||
"scale" : [1.0, 1.0, 1.0]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path" : "Models/proceduralTree2/proceduralTree2v2.fbx",
|
||||
"meshes" : [
|
||||
{
|
||||
"meshName" : "Trunk",
|
||||
"rotation" : [-0.7071068, 0.0, 0.0, 0.7071068],
|
||||
"offset" : [0.0, 0.0, 0.0],
|
||||
"scale" : [1.0, 1.0, 1.0]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
assets/Models/proceduralTree1/proceduralLeafBlob1.fbx
Normal file
BIN
assets/Models/proceduralTree1/proceduralLeafBlob1.fbx
Normal file
Binary file not shown.
BIN
assets/Models/proceduralTree1/proceduralTrunk1.fbx
Normal file
BIN
assets/Models/proceduralTree1/proceduralTrunk1.fbx
Normal file
Binary file not shown.
BIN
assets/Models/proceduralTree1/proceduralTrunk1.png
Normal file
BIN
assets/Models/proceduralTree1/proceduralTrunk1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
assets/Models/proceduralTree2/Trunk.png
Normal file
BIN
assets/Models/proceduralTree2/Trunk.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
BIN
assets/Models/proceduralTree2/proceduralTree2.fbx
Normal file
BIN
assets/Models/proceduralTree2/proceduralTree2.fbx
Normal file
Binary file not shown.
BIN
assets/Models/proceduralTree2/proceduralTree2v2.fbx
Normal file
BIN
assets/Models/proceduralTree2/proceduralTree2v2.fbx
Normal file
Binary file not shown.
Binary file not shown.
@ -67,10 +67,8 @@ float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
|
||||
void main(){
|
||||
if(hasTransparency == 1){
|
||||
if(texture(material.diffuse, TexCoord).a < 0.01){
|
||||
discard;
|
||||
}
|
||||
if(texture(material.diffuse, TexCoord).a < 0.01){
|
||||
discard;
|
||||
}
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
|
||||
238
assets/Shaders/proceduraltree/proceduraltree.fs
Normal file
238
assets/Shaders/proceduraltree/proceduraltree.fs
Normal file
@ -0,0 +1,238 @@
|
||||
#version 330 core
|
||||
|
||||
#define NR_POINT_LIGHTS 10
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
layout (std140) uniform Lights {
|
||||
// this is how many because we have to align
|
||||
// bytes it SHOULD in multiples of 16, this
|
||||
// take it where it ACTUALLY is
|
||||
//
|
||||
//refer: https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL
|
||||
//
|
||||
// base alignment aligned offset
|
||||
//direct light
|
||||
vec3 dLDirection; // 16 0
|
||||
vec3 dLAmbient; // 16 16
|
||||
vec3 dLDiffuse; // 16 32
|
||||
vec3 dLSpecular; // 16 48
|
||||
|
||||
//point light
|
||||
vec3 pLposition[NR_POINT_LIGHTS]; // 16*10 64
|
||||
float pLconstant[NR_POINT_LIGHTS]; // 16*10 224
|
||||
float pLlinear[NR_POINT_LIGHTS]; // 16*10 384
|
||||
float pLquadratic[NR_POINT_LIGHTS]; // 16*10 544
|
||||
vec3 pLambient[NR_POINT_LIGHTS]; // 16*10 704
|
||||
vec3 pLdiffuse[NR_POINT_LIGHTS]; // 16*10 864
|
||||
vec3 pLspecular[NR_POINT_LIGHTS]; // 16*10 1024
|
||||
|
||||
//for a total size of 1184
|
||||
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 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);
|
||||
|
||||
//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, texture(material.diffuse, TexCoord).a);//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;
|
||||
}
|
||||
74
assets/Shaders/proceduraltree/proceduraltree.vs
Normal file
74
assets/Shaders/proceduraltree/proceduraltree.vs
Normal file
@ -0,0 +1,74 @@
|
||||
//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 vec4 boneA;
|
||||
layout (location = 10) in vec4 boneB;
|
||||
layout (location = 11) in vec4 boneC;
|
||||
layout (location = 12) in vec4 boneD;
|
||||
layout (location = 13) in float baseSize;
|
||||
|
||||
|
||||
//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);
|
||||
|
||||
mat4 scaleMatrix = mat4(
|
||||
baseSize,0,0,0,
|
||||
0,baseSize,0,0,
|
||||
0,0,baseSize,0,
|
||||
0,0,0,1
|
||||
);
|
||||
|
||||
mat4 bone = mat4(boneA,boneB,boneC,boneD);
|
||||
mat4 BoneTransform = (bone * aWeights[0]) + (scaleMatrix * (1.0 - aWeights[0]));
|
||||
|
||||
//normalize posiiton and normal
|
||||
vec4 FinalVertex = BoneTransform * vec4(aPos, 1.0);
|
||||
vec4 FinalNormal = BoneTransform * 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;
|
||||
}
|
||||
@ -445,6 +445,18 @@
|
||||
"Textures/leaf3layer1.png",
|
||||
"Textures/leaf3layer1.png"
|
||||
]
|
||||
},
|
||||
"Models/proceduralTree2/proceduralTree2.fbx": {
|
||||
"Trunk" : [
|
||||
"Models/proceduralTree2/Trunk.png",
|
||||
"Models/proceduralTree2/Trunk.png"
|
||||
]
|
||||
},
|
||||
"Models/proceduralTree2/proceduralTree2v2.fbx": {
|
||||
"Trunk" : [
|
||||
"Models/proceduralTree2/Trunk.png",
|
||||
"Models/proceduralTree2/Trunk.png"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,3 @@
|
||||
#maven.buildNumber.plugin properties file
|
||||
#Tue Jul 25 19:29:28 EDT 2023
|
||||
buildNumber=5
|
||||
#Sun Aug 20 22:06:17 EDT 2023
|
||||
buildNumber=10
|
||||
|
||||
@ -195,7 +195,7 @@ public class ClientFoliageManager {
|
||||
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
|
||||
entity.putData(EntityDataStrings.DRAW_SOLID_PASS, true);
|
||||
Globals.clientScene.registerEntity(entity);
|
||||
Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAW_INSTANCED);
|
||||
Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAW_INSTANCED_MANAGED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -22,6 +22,7 @@ import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.BehaviorTree;
|
||||
import electrosphere.entity.state.movement.ApplyRotationTree;
|
||||
import electrosphere.entity.types.camera.CameraEntityUtils;
|
||||
import electrosphere.entity.types.tree.ProceduralTree;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.menu.MenuGenerators;
|
||||
import electrosphere.menu.MenuGeneratorsMultiplayer;
|
||||
@ -238,6 +239,11 @@ public class ClientLoading {
|
||||
}
|
||||
});
|
||||
|
||||
// for(int i = 0; i < 6; i++){
|
||||
Entity tree = ProceduralTree.clientGenerateProceduralTree("asdf", 0);
|
||||
// EntityUtils.getPosition(tree).set(5,0,i * 3);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
static void initDrawCellManager(){
|
||||
|
||||
@ -23,6 +23,12 @@ public class EntityDataStrings {
|
||||
public static final String DRAW_OUTLINE = "drawOutline";
|
||||
public static final String INSTANCED_ACTOR = "instancedActor";
|
||||
public static final String DRAW_INSTANCED = "drawInstanced";
|
||||
|
||||
|
||||
/*
|
||||
Instanced Entity
|
||||
*/
|
||||
public static final String INSTANCED_MODEL_ATTRIBUTE = "instancedModelAttribute";
|
||||
|
||||
|
||||
/*
|
||||
@ -160,9 +166,11 @@ public class EntityDataStrings {
|
||||
*/
|
||||
public static final String ATTACH_ENTITY_IS_ATTACHED = "attachIsAttached";
|
||||
public static final String ATTACH_PARENT = "attachParent";
|
||||
public static final String ATTACH_TARGET_BONE = "attachTargetBone";
|
||||
public static final String ATTACH_TARGET_BONE = "attachTargetBone"; //Attaches to a specific bone of the entity
|
||||
public static final String ATTACH_TARGET_BASE = "attachTargetBase"; //Attaches to the base of the entity (should be the same as getPosition(entity))
|
||||
public static final String ATTACH_CHILDREN_LIST = "attachChildrenList";
|
||||
public static final String ATTACH_ROTATION_OFFSET = "attachRotationOffset";
|
||||
public static final String ATTACH_POSITION_OFFSET = "attachPositionOffset";
|
||||
|
||||
/*
|
||||
Item Entity
|
||||
|
||||
@ -12,7 +12,8 @@ public class EntityTags {
|
||||
public static final String CREATURE = "creature";
|
||||
public static final String UI = "ui";
|
||||
public static final String DRAWABLE = "drawable";
|
||||
public static final String DRAW_INSTANCED = "drawInstanced";
|
||||
public static final String DRAW_INSTANCED = "drawInstanced"; //if it's instanced, but not necessarily managed by a service (ie a tree branch)
|
||||
public static final String DRAW_INSTANCED_MANAGED = "drawInstancedManaged"; //if it's managed by a service (ie foliage manager)
|
||||
public static final String LIGHT = "light";
|
||||
public static final String ITEM = "item";
|
||||
public static final String GRAVITY = "gravity";
|
||||
|
||||
@ -119,6 +119,10 @@ public class AttachUtils {
|
||||
.mul(offsetRotation)
|
||||
.normalize();
|
||||
}
|
||||
} else if(currentEntity.getData(EntityDataStrings.ATTACH_TARGET_BASE)!=null){
|
||||
Vector3d positionOffset = getAttachPositionOffset(currentEntity);
|
||||
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
||||
EntityUtils.getPosition(currentEntity).set(new Vector3d(parentPosition).add(positionOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,6 +146,29 @@ public class AttachUtils {
|
||||
getChildrenList(parent).remove(toAttach);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches an entity to another based on the parent's absolute position in the game engine
|
||||
* @param parent The parent to attach to
|
||||
* @param toAttach The entity to attach to the parent
|
||||
*/
|
||||
public static void clientAttachEntityAtCurrentOffset(Entity parent, Entity toAttach){
|
||||
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
||||
Vector3d childPosition = EntityUtils.getPosition(toAttach);
|
||||
Vector3d offset = new Vector3d(childPosition).sub(parentPosition);
|
||||
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_BASE, true);
|
||||
toAttach.putData(EntityDataStrings.ATTACH_POSITION_OFFSET, offset);
|
||||
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 boolean isAttached(Entity e){
|
||||
return e.containsKey(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
|
||||
@ -162,6 +189,10 @@ public class AttachUtils {
|
||||
public static boolean hasChildren(Entity e){
|
||||
return e.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST) && !getChildrenList(e).isEmpty();
|
||||
}
|
||||
|
||||
public static Vector3d getAttachPositionOffset(Entity e){
|
||||
return (Vector3d)e.getData(EntityDataStrings.ATTACH_POSITION_OFFSET);
|
||||
}
|
||||
|
||||
public static LinkedList<Entity> getChildrenList(Entity e){
|
||||
return (LinkedList<Entity>)e.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
|
||||
|
||||
@ -20,30 +20,20 @@ import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
* Utilities for generating foliage
|
||||
*/
|
||||
public class FoliageUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Spawns a basic foliage object
|
||||
* @param type The type of foliage object
|
||||
* @return The entity for the foliage
|
||||
*/
|
||||
public static Entity spawnBasicFoliage(String type){
|
||||
FoliageType rawType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
|
||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||
EntityCreationUtils.makeEntityDrawable(rVal, rawType.getModelPath());
|
||||
// if(rawType.getPhysicsObjects() != null){
|
||||
// List<PhysicsObject> physicsObjects = rawType.getPhysicsObjects();
|
||||
// for(PhysicsObject physicsTemplate : physicsObjects){
|
||||
// switch(physicsTemplate.getType()){
|
||||
// case "CYLINDER":
|
||||
//// Matrix4f rotationTransform = new Matrix4f().rotate(rotation);
|
||||
//// Vector4f rotatedPosition = rotationTransform.transform(new Vector4f(physicsTemplate.(),physicsTemplate.getPositionY(),physicsTemplate.getPositionZ(),1.0f));
|
||||
//// Vector3f cubePosition = new Vector3f(position).add(rotatedPosition.x,rotatedPosition.y,rotatedPosition.z);
|
||||
//// Quaternionf cubeRotation = new Quaternionf(rotation).mul(new Quaternionf(physicsTemplate.getRotationX(),template.getRotationY(),physicsTemplate.getRotationZ(),physicsTemplate.getRotationW())).normalize();
|
||||
// CollisionObjUtils.attachCollisionCube(new Vector3f(1,1,1), position, rotation, rVal);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
for(String token : rawType.getTokens()){
|
||||
switch(token){
|
||||
case "BLENDER_TRANSFORM":
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
package electrosphere.entity.types.instance;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||
|
||||
/**
|
||||
* A template for creating an instance entity. Stores thing like capacity and the model
|
||||
*/
|
||||
public class InstanceTemplate {
|
||||
|
||||
//The path for the model for this instance
|
||||
protected String modelPath;
|
||||
|
||||
//The total number of instances to draw at a given time
|
||||
protected int capacity;
|
||||
|
||||
//The map of all attributes for instanced foliage
|
||||
protected Map<ShaderAttribute,HomogenousBufferTypes> attributes;
|
||||
|
||||
//shader paths
|
||||
protected String vertexPath;
|
||||
protected String fragmentPath;
|
||||
|
||||
/**
|
||||
* Creates a template to create instanced actors off of
|
||||
* @param capacity The number of actors that can be drawn per frame (going over this limit will result in drawing the closest ${capacity} number of actors)
|
||||
* @param modelPath The path for the model of the instance
|
||||
* @param vertexPath The vertex shader path
|
||||
* @param fragmentPath The fragment shader path
|
||||
* @param attributes The attributes used on this instance
|
||||
* @return The template
|
||||
*/
|
||||
public static InstanceTemplate createInstanceTemplate(int capacity, String modelPath, String vertexPath, String fragmentPath, Map<ShaderAttribute,HomogenousBufferTypes> attributes){
|
||||
InstanceTemplate rVal = new InstanceTemplate();
|
||||
rVal.capacity = capacity;
|
||||
rVal.modelPath = modelPath;
|
||||
rVal.vertexPath = vertexPath;
|
||||
rVal.fragmentPath = fragmentPath;
|
||||
rVal.attributes = attributes;
|
||||
return rVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package electrosphere.entity.types.instance;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityTags;
|
||||
import electrosphere.renderer.actor.instance.InstancedActor;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
|
||||
/**
|
||||
* Utilities for working with entities that are instanced models
|
||||
*/
|
||||
public class InstancedEntityUtils {
|
||||
|
||||
/**
|
||||
* Makes an already created entity a drawable, instanced entity (client only) by backing it with an InstancedActor
|
||||
* @param entity The entity
|
||||
* @param template The instance template to create the entity off of
|
||||
* @return The instanced actor that is attached to this entity
|
||||
*/
|
||||
public static InstancedActor makeEntityInstanced(Entity entity, InstanceTemplate template){
|
||||
InstancedActor instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||
template.modelPath,
|
||||
template.vertexPath,
|
||||
template.fragmentPath,
|
||||
template.attributes,
|
||||
template.capacity);
|
||||
entity.putData(EntityDataStrings.INSTANCED_ACTOR, instancedActor);
|
||||
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
||||
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
|
||||
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
|
||||
entity.putData(EntityDataStrings.DRAW_SOLID_PASS, true);
|
||||
entity.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
||||
Globals.clientScene.registerEntity(entity);
|
||||
Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAW_INSTANCED);
|
||||
return instancedActor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an already created entity a drawable, instanced entity (client only) by backing it with an InstancedActor
|
||||
* This variation also specifies a shader attribute that represents the model transform of the instance
|
||||
* The model transform is used to constantly automatically calculate the position of the mesh
|
||||
* @param entity The entity
|
||||
* @param template The instance template to create the entity off of
|
||||
* @param modelTransformAttribute The shader attribute that is the model transform
|
||||
* @return The instanced actor that is attached to this entity
|
||||
*/
|
||||
public static InstancedActor makeEntityInstancedWithModelTransform(Entity entity, InstanceTemplate template, ShaderAttribute modelTransformAttribute){
|
||||
InstancedActor instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||
template.modelPath,
|
||||
template.vertexPath,
|
||||
template.fragmentPath,
|
||||
template.attributes,
|
||||
template.capacity);
|
||||
entity.putData(EntityDataStrings.INSTANCED_ACTOR, instancedActor);
|
||||
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
||||
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
|
||||
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
|
||||
entity.putData(EntityDataStrings.DRAW_SOLID_PASS, true);
|
||||
entity.putData(EntityDataStrings.DATA_STRING_DRAW, true);
|
||||
entity.putData(EntityDataStrings.INSTANCED_MODEL_ATTRIBUTE, modelTransformAttribute);
|
||||
Globals.clientScene.registerEntity(entity);
|
||||
Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAW_INSTANCED);
|
||||
return instancedActor;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,305 @@
|
||||
package electrosphere.entity.types.tree;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
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.Vector4f;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.DrawableUtils;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityCreationUtils;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
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.renderer.actor.instance.InstancedActor;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||
|
||||
/**
|
||||
* Used for generating procedural trees
|
||||
*/
|
||||
public class ProceduralTree {
|
||||
|
||||
//The instance template for the branch
|
||||
static InstanceTemplate branchInstanceTemplate;
|
||||
|
||||
//The model attribute
|
||||
static final ShaderAttribute modelMatrixAttribute = new ShaderAttribute(new int[]{
|
||||
5,6,7,8
|
||||
});
|
||||
|
||||
//the bone attribute
|
||||
static final ShaderAttribute boneMatrixAttribute = new ShaderAttribute(new int[]{
|
||||
9,10,11,12
|
||||
});
|
||||
|
||||
static final ShaderAttribute baseSizeAttribute = new ShaderAttribute(13);
|
||||
|
||||
//The static setup logic
|
||||
static {
|
||||
//create map of attributes and register them
|
||||
Map<ShaderAttribute,HomogenousBufferTypes> attributes = new HashMap<ShaderAttribute,HomogenousBufferTypes>();
|
||||
attributes.put(modelMatrixAttribute,HomogenousBufferTypes.MAT4F);
|
||||
attributes.put(boneMatrixAttribute,HomogenousBufferTypes.MAT4F);
|
||||
attributes.put(baseSizeAttribute, HomogenousBufferTypes.FLOAT);
|
||||
|
||||
branchInstanceTemplate = InstanceTemplate.createInstanceTemplate(
|
||||
1000,
|
||||
"Models/proceduralTree2/proceduralTree2v2.fbx",
|
||||
"Shaders/proceduraltree/proceduraltree.vs",
|
||||
"Shaders/proceduraltree/proceduraltree.fs",
|
||||
attributes);
|
||||
}
|
||||
|
||||
|
||||
//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
|
||||
*/
|
||||
public static Entity clientGenerateProceduralTree(String type, long seed){
|
||||
Random treeRandom = new Random(seed);
|
||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||
|
||||
//generate trunk
|
||||
Entity trunkChild = EntityCreationUtils.createClientSpatialEntity();
|
||||
InstancedActor instancedActor = InstancedEntityUtils.makeEntityInstancedWithModelTransform(trunkChild, branchInstanceTemplate, modelMatrixAttribute);
|
||||
instancedActor.setAttribute(boneMatrixAttribute, new Matrix4f().identity());
|
||||
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);
|
||||
// // }});
|
||||
// }
|
||||
// }
|
||||
|
||||
//attach btress
|
||||
//..attach wind
|
||||
//...
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// //the rotation applied to the bone
|
||||
// Quaternionf boneRotation = new Quaternionf(0,0,0,1).rotateLocalX((float)(pitchFactor * peelRotation)).rotateLocalZ((float)(rollFactor * peelRotation)).normalize();
|
||||
|
||||
// //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();
|
||||
|
||||
// //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();
|
||||
|
||||
// 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++){
|
||||
//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);
|
||||
|
||||
//new position transform
|
||||
Matrix4f newPositionTransform = new Matrix4f(transform).mul(boneTransform).translate(0,3,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());
|
||||
|
||||
|
||||
//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);
|
||||
|
||||
//debug stuff
|
||||
// Entity debugSphere = EntityCreationUtils.createClientSpatialEntity();
|
||||
// EntityCreationUtils.makeEntityDrawable(debugSphere, "Models/unitsphere_1.fbx");
|
||||
// EntityUtils.getScale(debugSphere).set(0.5f);
|
||||
// EntityUtils.getPosition(debugSphere).set(newAbsolutePosition);
|
||||
|
||||
|
||||
clientGenerateBranches(type, branch, rand, newPositionTransform, scalar - scalarFalloffFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -378,6 +378,14 @@ public class Mesh {
|
||||
weight[2] = weight[2] * (1.0f / total);
|
||||
weight[3] = weight[3] * (1.0f / total);
|
||||
}
|
||||
//If all are 0 (for instance the vertex doesn't have any bones with any weight > 0), the values for each weight will be NaN after the divide immediately above
|
||||
//If NaN, set all to 0
|
||||
if(Float.isNaN(weight[0])){
|
||||
weight[0] = 0;
|
||||
weight[1] = 0;
|
||||
weight[2] = 0;
|
||||
weight[3] = 0;
|
||||
}
|
||||
boneIndexDataBuffer.put(index);
|
||||
boneWeightDataBuffer.put(weight);
|
||||
}
|
||||
|
||||
@ -87,6 +87,8 @@ import electrosphere.game.data.creature.type.CollidableTemplate;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.RenderPipelineState.SelectedShaderEnum;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.renderer.actor.instance.InstancedActor;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.debug.DebugRendering;
|
||||
import electrosphere.renderer.framebuffer.Framebuffer;
|
||||
import electrosphere.renderer.framebuffer.FramebufferUtils;
|
||||
@ -147,6 +149,11 @@ public class RenderingEngine {
|
||||
static float volumeDepthLinearCoef = 0.1f;
|
||||
static float volumeDepthQuadCoef = 0.01f;
|
||||
|
||||
/*
|
||||
Necessary static variables for drawing
|
||||
*/
|
||||
static Matrix4d modelTransformMatrix = new Matrix4d();
|
||||
|
||||
/*
|
||||
Vertical volumetrics
|
||||
TODO: implement
|
||||
@ -667,6 +674,38 @@ public class RenderingEngine {
|
||||
currentActor.draw(renderPipelineState);
|
||||
}
|
||||
}
|
||||
for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED)){
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) != null &&
|
||||
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
|
||||
){
|
||||
//fetch actor
|
||||
InstancedActor currentActor = InstancedActor.getInstancedActor(currentEntity);
|
||||
//if the shader attribute for model matrix exists, calculate the model matrix and apply
|
||||
if(InstancedActor.getInstanceModelAttribute(currentEntity) != null){
|
||||
ShaderAttribute modelAttribute = InstancedActor.getInstanceModelAttribute(currentEntity);
|
||||
//calculate model matrix
|
||||
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
||||
Quaterniond rotation = EntityUtils.getRotation(currentEntity);
|
||||
// modelTransformMatrix.identity();
|
||||
modelTransformMatrix.identity().translationRotateScale(
|
||||
cameraModifiedPosition,
|
||||
new Quaternionf((float)rotation.x,(float)rotation.y,(float)rotation.z,(float)rotation.w),
|
||||
new Vector3f(EntityUtils.getScale(currentEntity))
|
||||
);
|
||||
// modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
// modelTransformMatrix.rotate(rotation);
|
||||
// modelTransformMatrix.scale(new Vector3d(EntityUtils.getScale(currentEntity)));
|
||||
//set actor value
|
||||
currentActor.setAttribute(modelAttribute, new Matrix4f(modelTransformMatrix));
|
||||
// ((Matrix4f)currentActor.getAttributeValue(modelAttribute)).set(modelTransformMatrix);
|
||||
}
|
||||
//draw
|
||||
currentActor.draw(renderPipelineState);
|
||||
}
|
||||
}
|
||||
//draw all instanced models
|
||||
Globals.clientInstanceManager.draw(renderPipelineState);
|
||||
|
||||
@ -724,6 +763,21 @@ public class RenderingEngine {
|
||||
currentActor.draw(renderPipelineState);
|
||||
}
|
||||
}
|
||||
for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED)){
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) != null &&
|
||||
currentEntity.getData(EntityDataStrings.DRAW_TRANSPARENT_PASS) != null &&
|
||||
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
|
||||
){
|
||||
//fetch actor
|
||||
InstancedActor currentActor = InstancedActor.getInstancedActor(currentEntity);
|
||||
//draw
|
||||
if(currentActor != null){
|
||||
currentActor.draw(renderPipelineState);
|
||||
}
|
||||
}
|
||||
}
|
||||
//draw all instanced models
|
||||
Globals.clientInstanceManager.draw(renderPipelineState);
|
||||
|
||||
@ -740,8 +794,6 @@ public class RenderingEngine {
|
||||
|
||||
static void renderGameContentNoOIT(){
|
||||
|
||||
Matrix4d modelTransformMatrix = new Matrix4d();
|
||||
|
||||
//bind screen fbo
|
||||
screenFramebuffer.bind();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
@ -218,9 +218,9 @@ public class InstanceData {
|
||||
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
|
||||
Matrix4f mat = (Matrix4f)actor.getAttributeValue(attribute);
|
||||
buffer.put(mat.m00());
|
||||
buffer.put(mat.m10());
|
||||
buffer.put(mat.m20());
|
||||
buffer.put(mat.m30());
|
||||
buffer.put(mat.m01());
|
||||
buffer.put(mat.m02());
|
||||
buffer.put(mat.m03());
|
||||
|
||||
buffer.put(mat.m10());
|
||||
buffer.put(mat.m11());
|
||||
@ -241,9 +241,9 @@ public class InstanceData {
|
||||
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
|
||||
Matrix4d mat = (Matrix4d)actor.getAttributeValue(attribute);
|
||||
buffer.put((float)mat.m00());
|
||||
buffer.put((float)mat.m10());
|
||||
buffer.put((float)mat.m20());
|
||||
buffer.put((float)mat.m30());
|
||||
buffer.put((float)mat.m01());
|
||||
buffer.put((float)mat.m02());
|
||||
buffer.put((float)mat.m03());
|
||||
|
||||
buffer.put((float)mat.m10());
|
||||
buffer.put((float)mat.m11());
|
||||
|
||||
@ -51,6 +51,10 @@ public class InstanceManager {
|
||||
InstanceData instanceData = new InstanceData(capacity,vertexShaderPath,fragmentShaderPath);
|
||||
//queue shader
|
||||
Globals.assetManager.addShaderToQueue(vertexShaderPath, fragmentShaderPath);
|
||||
//if asset manager doesn't have model, queue model
|
||||
if(Globals.assetManager.fetchModel(modelPath) == null){
|
||||
Globals.assetManager.addModelPathToQueue(modelPath);
|
||||
}
|
||||
//set attributes
|
||||
for(ShaderAttribute attribute : attributeTypes.keySet()){
|
||||
instanceData.addDataType(attribute, attributeTypes.get(attribute));
|
||||
|
||||
@ -86,6 +86,13 @@ public class InstancedActor implements Comparable<InstancedActor> {
|
||||
attributes.put(attribute, new Matrix4d((Matrix4d)value));
|
||||
}
|
||||
}
|
||||
if(
|
||||
value instanceof Double ||
|
||||
value instanceof Float ||
|
||||
value instanceof Integer
|
||||
){
|
||||
attributes.put(attribute, value);
|
||||
}
|
||||
// attributes.put(attribute, value);
|
||||
}
|
||||
|
||||
@ -123,4 +130,14 @@ public class InstancedActor implements Comparable<InstancedActor> {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If it exists, gets the model attribute for this instance
|
||||
* @param entity The entity to get the attribute from
|
||||
* @return The attribute if it exists, or null
|
||||
*/
|
||||
public static ShaderAttribute getInstanceModelAttribute(Entity entity){
|
||||
return (ShaderAttribute)entity.getData(EntityDataStrings.INSTANCED_MODEL_ATTRIBUTE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -192,6 +192,16 @@ public class HomogenousInstancedArray {
|
||||
GL45.glVertexAttribDivisor(matrixAttributeIndices[1], 1);
|
||||
GL45.glVertexAttribDivisor(matrixAttributeIndices[2], 1);
|
||||
GL45.glVertexAttribDivisor(matrixAttributeIndices[3], 1);
|
||||
} else if(type == HomogenousBufferTypes.FLOAT){
|
||||
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, 1, 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());
|
||||
}
|
||||
|
||||
@ -226,6 +226,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
public void unloadPlayerlessChunks(){
|
||||
//TODO: improve to make have less performance impact
|
||||
for(ServerDataCell cell : loadedCells){
|
||||
loadedCellsLock.acquireUninterruptibly();
|
||||
if(cell.getPlayers().size() < 1){
|
||||
int frameCount = cellPlayerlessFrameMap.get(cell) + 1;
|
||||
cellPlayerlessFrameMap.put(cell,frameCount);
|
||||
@ -237,6 +238,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
cellPlayerlessFrameMap.put(cell, 0);
|
||||
}
|
||||
}
|
||||
loadedCellsLock.release();
|
||||
}
|
||||
for(ServerDataCell cell : toCleanQueue){
|
||||
parent.deregisterCell(cell);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user