Trees be freaking out yo
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2023-09-21 19:41:27 -04:00
parent f113f45317
commit fe1680b7d9
3 changed files with 346 additions and 41 deletions

View File

@ -1,5 +1,6 @@
package electrosphere.engine.loadingthreads;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.joml.Quaterniond;
@ -239,12 +240,17 @@ public class ClientLoading {
}
});
// for(int i = 0; i < 6; i++){
Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", 0);
Random rand = new Random(0);
{
Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong());
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);
}
// for(int i = 0; i < 6; i++){
// Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong());
// // 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 * 5);
// }
}

View File

@ -252,6 +252,15 @@ public class AttachUtils {
}
}
/**
* Updates the transform for the attachment
* @param toAttach The entity that is attached
* @param transform The transform
*/
public static void updateAttachTransform(Entity toAttach, Matrix4f transform){
toAttach.putData(EntityDataStrings.ATTACH_TRANSFORM, transform);
}
/**
* Semantically attaches an entity to another entity

View File

@ -1,6 +1,8 @@
package electrosphere.entity.types.tree;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@ -10,6 +12,7 @@ import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector4d;
import org.joml.Vector4f;
import electrosphere.engine.Globals;
@ -95,25 +98,17 @@ public class ProceduralTree {
instancedActor.setAttribute(boneMatrixAttribute, new Matrix4f().identity());
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
instancedActor.setAttribute(baseSizeAttribute, 1.0f);
// EntityCreationUtils.makeEntityDrawable(trunkChild, "Models/proceduralTree2/proceduralTree2.fbx");
//call recursive branching routine to generate branches from trunk + leaf blobs
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
// );
//generate branches
clientGenerateBranchesAlt(
treeModel,
trunkChild,
treeRandom,
0,
0,
new Vector3d(0,0,0),
new Quaterniond(0,0,0,1),
new Vector3d(0,3,0),
@ -123,17 +118,15 @@ public class ProceduralTree {
true
);
//attach btress
//..attach wind
//...
return trunkChild;
}
public static void clientGenerateBranchesAlt(
public static List<Entity> clientGenerateBranchesAlt(
TreeModel type,
Entity parent,
Random rand,
double parentPeel,
double parentRotationOffset,
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
@ -142,6 +135,7 @@ public class ProceduralTree {
int currentSegmentNumber,
boolean isCentralTrunk
){
List<Entity> rVal = new LinkedList<Entity>();
//how fast do the branches shrink in size
float scalarFalloffFactor = type.getLimbScalarFalloffFactor();
//the minimum branch size before we stop generating branch segments/trunk segments
@ -245,14 +239,6 @@ public class ProceduralTree {
//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().rotate(boneRotation).translate(0,treeSegmentHeight,0);
@ -263,7 +249,12 @@ public class ProceduralTree {
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));
@ -277,27 +268,41 @@ public class ProceduralTree {
// 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);
rVal.add(branch);
//attach leaf blobs
if(
!isCentralTrunk &&
currentSegmentNumber >= minimumSegmentToSpawnLeaves
){
// createLeafBlobsOnBranch(type,rand,transform,boneTransform,branch);
createLeafBlobsOnBranch(
type,
branch,
rand,
currentPosition,
currentAbsoluteRotation,
newPosition,
boneRotation,
scalar - scalarFalloffFactor,
currentSegmentNumber + 1,
false //can't be central trunk
);
}
//recurse
clientGenerateBranchesAlt(
List<Entity> childBranches = clientGenerateBranchesAlt(
type,
branch,
rand,
peelRotation,
offsetRotation,
currentPosition,
currentAbsoluteRotation,
newPosition,
@ -306,8 +311,22 @@ public class ProceduralTree {
currentSegmentNumber + 1,
false //can't be central trunk
);
//add behavior tree to update all child branch attachment points to new point
if(childBranches.size() > 0){
Globals.clientSceneWrapper.getScene().registerBehaviorTree(new BranchBehaviorTree(
parent,
branch,
childBranches,
newScalar,
parentPeel,
offsetRotation,
treeSegmentHeight
));
}
}
}
return rVal;
}
/**
@ -528,22 +547,293 @@ public class ProceduralTree {
}
}
/**
* 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,
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
){
//get type data
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++){
//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
//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;
//calculate the transform from parent
Quaterniond parentLocalRotationFromVertical = new Quaterniond().rotationTo(new Vector3d(0,1,0), offsetFromParent);
Vector4d transformedPos = parentLocalRotationFromVertical.transform(new Vector4d(xOffset,positionAlongBranch,zOffset,1));
//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)transformedPos.x,
(float)transformedPos.y,
(float)transformedPos.z
))
.rotate(new Quaternionf(
(float)rotationFromParent.x,
(float)rotationFromParent.y,
(float)rotationFromParent.z,
(float)rotationFromParent.w
));
//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(parent, leaf);
// AttachUtils.clientAttachEntityAtCurrentOffset(parent, branch);
AttachUtils.clientAttachEntityAtTransform(parent, leaf, transformFromParent);
}
}
// for(int i = 0; i < branchNum; i++){
// //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
// Quaterniond parentLocalRotationFromVertical = new Quaterniond().rotationTo(new Vector3d(0,1,0), offsetFromParent);
// parentLocalRotationFromVertical.transform(new Vector4d(0,0,0,1));
// //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();
// //calculate child stuff
// //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();
// //calculates the bone transform matrix
// Matrix4f boneTransform = new Matrix4f().identity().rotate(boneRotation);
// //new position transform
// 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;
// //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, transformFromParent);
// }
}
/**
* The behavior tree for branches swaying in the wind
*/
static class BranchBehaviorTree implements BehaviorTree {
//The parent that the branch is attached to
Entity parent;
//The branch that is having its offset changed
Entity branch;
//the initial peel for the branch
double initialPeel;
//The current peel for the branch
double currentPeel;
//The initial yaw for the branch
double initialYaw;
//the current yaw for the branch
double currentYaw;
//The height of the
float treeSegmentHeight;
//Every child branch
List<Entity> children;
//The current scalar of the branch
double currentScalar;
/**
* Constructor
* @param branch The branch entity
*/
protected BranchBehaviorTree(Entity branch){
protected BranchBehaviorTree(Entity parent, Entity branch, List<Entity> children, double currentScalar, double peel, double yaw, float treeSegmentHeight){
this.parent = parent;
this.branch = branch;
this.initialPeel = peel;
this.currentPeel = peel;
this.initialYaw = yaw;
this.currentYaw = yaw;
this.treeSegmentHeight = treeSegmentHeight;
this.children = children;
this.currentScalar = currentScalar;
}
@Override
public void simulate(float deltaTime) {
System.out.println(currentYaw);
// currentYaw = currentYaw * Math.abs(currentYaw - initialYaw) + new Random().nextDouble() * (1 - Math.abs(currentYaw - initialYaw));
currentPeel = initialPeel * Math.abs(currentPeel - initialPeel) + new Random().nextDouble() * (1 - Math.abs(currentPeel - initialPeel));
//get new rotation
double pitchFactor = Math.sin(currentYaw);
double rollFactor = Math.cos(currentYaw);
//the rotation applied to the bone
Quaternionf boneRotation = new Quaternionf(0,0,0,1).rotateLocalX((float)(pitchFactor * currentPeel)).rotateLocalZ((float)(rollFactor * currentPeel)).normalize();
//calculates the bone transform matrix
Matrix4f boneTransform = new Matrix4f().identity().rotate(boneRotation);
//new position transform
Matrix4f newPositionTransform = new Matrix4f().rotate(boneRotation).translate(0,treeSegmentHeight,0);
Vector4f newPositionRaw = newPositionTransform.transform(new Vector4f(0,0,0,1));
Matrix4f transformFromParent = new Matrix4f()
.translate(new Vector3f(
(float)newPositionRaw.x,
(float)newPositionRaw.y,
(float)newPositionRaw.z
))
.rotate(new Quaternionf(
(float)boneRotation.x,
(float)boneRotation.y,
(float)boneRotation.z,
(float)boneRotation.w
));
//update branch actor branch matrix
InstancedActor branchActor = InstancedActor.getInstancedActor(branch);
branchActor.setAttribute(boneMatrixAttribute, new Matrix4f(transformFromParent).scale((float)currentScalar,1,(float)currentScalar));
//update children positions
for(Entity child : children){
AttachUtils.updateAttachTransform(child,transformFromParent);
}
}
}