Tree work + Documentation work

This commit is contained in:
austin 2023-11-05 10:08:51 -05:00
parent e37b48d267
commit 4673e09396
16 changed files with 421 additions and 232 deletions

8
.vscode/launch.json vendored
View File

@ -32,6 +32,14 @@
"mainClass": "electrosphere.engine.Main",
"projectName": "Renderer",
"args" : "--headless"
},
{
"type": "java",
"name": "Launch Main (Macro Simulate)",
"request": "launch",
"mainClass": "electrosphere.engine.Main",
"projectName": "Renderer",
"args" : "--macro-simulate"
}
]
}

View File

@ -69,7 +69,17 @@
"yawVariance": 0.2,
"yawMinimum": 0.1,
"minimumScalarToGenerateSwayTree": 0.5,
"maximumScalarToGenerateSwayTree": 1.0
"maximumScalarToGenerateSwayTree": 1.0,
"physicsCutoff": 3,
"physicsBody": {
"type" : "CYLINDER",
"dimension1" : 3,
"dimension2" : 1,
"dimension3" : 1,
"offsetX" : 0,
"offsetY" : 1.5,
"offsetZ" : 0
}
},
"modelPath" : "Models/proceduralTree2/proceduralTree2v2.fbx"
}

View File

@ -0,0 +1,13 @@
# Documentation System Explanation
The engine uses doxygen to document its features, code, and organization.
## Building
On windows, doxywizard can be used to build the documentation in a gui format. Simply open Renderer/docs as the working directory from the top, then open the file "Doxyfile". The project should be preconfigured. Lastly move to the "Run" tab, click "Run doxygen" to generate documentation. You can then optionally click "Show HTML Output" to navigate to the documentation locally via native browser.
TODO: Linux instructions
## Usage Notes
### Images
Images have proven to be tricky with doxygen on windows. Relative paths only kind of work. Unfortunately this means all images need to be in Renderer/docs/src/images without conflicting names. Potential solutions to look in to are namespacing the file names to the page they show up in.

View File

@ -0,0 +1,108 @@
# Collision Engine
## High Level Overview
The goal of the collision engine system is to allow parallel collision detection of different classes of objects.
For instance, you could have a collision system dedicated to fire and things that are flammable, where only objects in one of those two categories are present. Or, you could have a collision system dedicated to interactible object prompts, where if the player entity is within one of these zones it performs some prompting logic.
The big case for this engine is the main physics system. The goal is to provide different classes of things for entities to collide with such that they can control the collision physics differently (think a tree vs the ground vs a slippery floor).
## Major Usage Notes
- All geometries are aligned along z by default in the library (ie your cylinders will be on their sides)
## Main Classes
[CollisionEngine.java](@ref #electrosphere.collision.CollisionEngine) - Represents a specific collision system. It may be helpful to think of it as viewing the world through a specific lens. Keeps track of all entities that do its type of collisions and fires callbacks on collision. Should be updated each tick.
[Collidable.java](@ref #electrosphere.collision.collidable.Collidable) - Contains the collision information for a single object in a given collision system. Stores both the description of the collidable (is it a tree, a frog, or the ground, etc) as well as a list of impulses to be applied.
## Library Explanation
The library currently in use is Ode4J. There are a couple main classes that will be explained now.
- DSpace - The main class representing the overall simulation
- DWorld - A 'world' within the space that can have geometries inside it that collide. Must be used to create bodies. Probably stores stuff like gravity.
- DBody - A rigid body that has some physical properties. Can contain many different geometries.
- DGeom - A geometry shape (capsule, box, etc)
## Code Organization and Best Practices
#### Startup
Each client scene creates a collision engine for physics on connection. Each scene the server manages also creates a collision engine for physics.
#### Usage
## Future Goals
- Ability to turn off impulse generation for when we purely care about whether things are colliding or not (hitboxes, fire system, ui system, etc)
- As always, code organization

View File

@ -0,0 +1,23 @@
# Physics Engine
## High Level Overview
The goal of the physics engine is to wrap around the collision engine to allow physics to occur within the game.
## Major Usage Notes
## Main Classes
## Code Organization and Best Practices
## Future Goals

View File

@ -52,7 +52,7 @@ import electrosphere.entity.types.hitbox.HitboxData;
import electrosphere.logger.LoggerInterface;
/**
*
* The main collision engine class. Tracks all entities that collide in its system and fires callbacks when they do.
*/
public class CollisionEngine {

View File

@ -1,24 +0,0 @@
package electrosphere.collision;
import java.util.LinkedList;
import electrosphere.collision.collidable.Collidable;
/**
* Contains masks for different collision engine functions
*/
public class CollisionMasks {
//Only terrain
public static final LinkedList<String> terrainMask = new LinkedList<String>();
/**
* Fills in all the collision engine masks
*/
public static void initMasks(){
//terrain mask
terrainMask.add(Collidable.TYPE_TERRAIN);
}
}

View File

@ -28,8 +28,7 @@ import electrosphere.entity.types.terrain.TerrainChunkData;
import electrosphere.server.datacell.Realm;
/**
*
* @author amaterasu
* Utilities for leveraging the collision system to perform physics
*/
public class PhysicsUtils {

View File

@ -21,7 +21,6 @@ import electrosphere.client.sim.ClientSimulation;
import electrosphere.client.terrain.cells.DrawCellManager;
import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.collision.CollisionEngine;
import electrosphere.collision.CollisionMasks;
import electrosphere.collision.CollisionWorldData;
import electrosphere.controls.CameraHandler;
import electrosphere.controls.ControlCallback;
@ -397,8 +396,6 @@ public class Globals {
if(Globals.userSettings.getNetRunNetMonitor()){
netMonitor = new NetMonitor();
}
//init collision masks
CollisionMasks.initMasks();
}
public static void initDefaultAudioResources(){

View File

@ -17,6 +17,9 @@ public class CLIParser {
Globals.RUN_SERVER = true;
Globals.HEADLESS = true;
} break;
case "--macro-simulate": {
//TODO: macro simulate
} break;
}
}
}

View File

@ -15,6 +15,7 @@ import electrosphere.client.terrain.cells.DrawCellManager;
import electrosphere.collision.CollisionEngine;
import electrosphere.controls.ControlHandler;
import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.DrawableUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
@ -256,7 +257,7 @@ public class ClientLoading {
for(int x = 0; x < 5; x++){
for(int z = 0; z < 5; z++){
Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong());
EntityUtils.getPosition(tree).set(5 + x * 5,0,5 + z * 5);
ClientEntityUtils.initiallyPositionEntity(tree, new Vector3d(5 + x * 5,0,5 + z * 5));
}
}

View File

@ -10,7 +10,6 @@ import org.joml.Vector3d;
import org.joml.Vector3f;
import org.ode4j.ode.DBody;
import electrosphere.collision.CollisionMasks;
import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;

View File

@ -229,11 +229,11 @@ public class GroundMovementTree implements BehaviorTree {
// System.out.println(EntityUtils.getEntityPosition(parent));
// System.out.println(message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ());
//this should only fire on the client, we don't want the server snap updating due to client position reporting
if(position.distance(message.getpositionX(),message.getpositionY(),message.getpositionZ()) > STATE_DIFFERENCE_HARD_UPDATE_THRESHOLD){
EntityUtils.getPosition(parent).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
} else if(position.distance(message.getpositionX(),message.getpositionY(),message.getpositionZ()) > STATE_DIFFERENCE_SOFT_UPDATE_THRESHOLD){
EntityUtils.getPosition(parent).add(new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()).mul(SOFT_UPDATE_MULTIPLIER));
}
// if(position.distance(message.getpositionX(),message.getpositionY(),message.getpositionZ()) > STATE_DIFFERENCE_HARD_UPDATE_THRESHOLD){
// EntityUtils.getPosition(parent).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
// } else if(position.distance(message.getpositionX(),message.getpositionY(),message.getpositionZ()) > STATE_DIFFERENCE_SOFT_UPDATE_THRESHOLD){
// EntityUtils.getPosition(parent).add(new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()).mul(SOFT_UPDATE_MULTIPLIER));
// }
//we want to always update the server facing vector with where the client says they're facing
EntityUtils.getRotation(parent).set(message.getrotationX(),message.getrotationY(),message.getrotationZ(),message.getrotationW());
// CreatureUtils.setFacingVector(parent, new Vector3d(message.getrotationX(),message.getrotationY(),message.getrotationZ()));

View File

@ -14,11 +14,16 @@ import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector4d;
import org.joml.Vector4f;
import org.ode4j.ode.DBody;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals;
import electrosphere.entity.DrawableUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.BehaviorTree;
import electrosphere.entity.types.attach.AttachUtils;
@ -56,6 +61,8 @@ public class ProceduralTree {
static final ShaderAttribute leafColorAttribute = new ShaderAttribute(9);
static final float TREE_MASS = 1.0f;
//The static setup logic
static {
//create map of attributes and register them
@ -92,6 +99,10 @@ public class ProceduralTree {
public static Entity clientGenerateProceduralTree(String type, long seed){
Random treeRandom = new Random(seed);
//call recursive branching routine to generate branches from trunk + leaf blobs
FoliageType foliageType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
TreeModel treeModel = foliageType.getTreeModel();
//generate trunk
Entity trunkChild = EntityCreationUtils.createClientSpatialEntity();
InstancedActor instancedActor = InstancedEntityUtils.makeEntityInstancedWithModelTransform(trunkChild, branchInstanceTemplate, modelMatrixAttribute);
@ -99,9 +110,25 @@ public class ProceduralTree {
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f().identity());
instancedActor.setAttribute(baseSizeAttribute, 1.0f);
//call recursive branching routine to generate branches from trunk + leaf blobs
FoliageType foliageType = Globals.gameConfigCurrent.getFoliageMap().getFoliage(type);
TreeModel treeModel = foliageType.getTreeModel();
//attach physics
DBody rigidBody = PhysicsUtils.createCylinderBody(
Globals.clientSceneWrapper.getCollisionEngine(),
treeModel.getPhysicsBody().getDimension1(),
treeModel.getPhysicsBody().getDimension2()
);
Collidable collidable = new Collidable(trunkChild, Collidable.TYPE_OBJECT);
trunkChild.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody);
trunkChild.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(0,treeModel.getPhysicsBody().getOffsetY(),0));
trunkChild.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, treeModel.getPhysicsBody());
trunkChild.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
trunkChild.putData(EntityDataStrings.PHYSICS_MASS, TREE_MASS);
Globals.clientSceneWrapper.getCollisionEngine().registerPhysicsEntity(trunkChild);
Globals.clientSceneWrapper.getCollisionEngine().registerDynamicPhysicsEntity(trunkChild);
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
//generate branches
clientGenerateBranchesAlt(
treeModel,
@ -331,223 +358,223 @@ public class ProceduralTree {
return rVal;
}
/**
* 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();
// /**
// * 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();
// 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);
// //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();
// //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);
// //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);
// //calculate attachment transform
// Matrix4f attachmentTransform = new Matrix4f().identity().translate(0,treeSegmentHeight,0).rotate(boneRotation);
//new position transform
Matrix4f newPositionTransform = new Matrix4f(transform).mul(boneTransform);
// //new position transform
// Matrix4f newPositionTransform = new Matrix4f(transform).mul(boneTransform);
//get new scalar
float newScalar = scalar - scalarFalloffFactor;
// //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());
// //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);
// //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
);
}
}
// //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();
// 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);
// //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();
// //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);
// //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();
// //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);
// //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);
// //new position transform
// Matrix4f newPositionTransform = new Matrix4f(transform).mul(boneTransform).translate(0,treeSegmentHeight,0);
//get new scalar
float newScalar = scalar - scalarFalloffFactor;
// //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());
// //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);
// //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);
// //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);
}
// //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
);
}
}
}
// //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();
// /**
// * 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));
// 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);
}
}
}
// //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);
// }
// }
// }

View File

@ -1,5 +1,7 @@
package electrosphere.game.data.foliage.type;
import electrosphere.game.data.creature.type.CollidableTemplate;
/**
* Describes characteristics about a type of tree (how do the limbs dispere, where to the leaves start growing, how sturdy is it, etc)
*/
@ -59,6 +61,12 @@ public class TreeModel {
//The distance from the central line of a branch to spawn a leaf at
float leafDistanceFromCenter;
//The branch count to stop generating physics for each branch
int physicsCutoff;
//The rigid body definition for a full scale tree branch
CollidableTemplate physicsBody;
//
//Tree branch sway factors
@ -304,7 +312,24 @@ public class TreeModel {
* @return
*/
public float getMaximumScalarToGenerateSwayTree(){
return maximumScalarToGenerateSwayTree;
return this.maximumScalarToGenerateSwayTree;
}
/**
* The branch count to stop generating physics for each branch
* @return
*/
public int getPhysicsCutoff(){
return this.physicsCutoff;
}
/**
* The rigid body definition for a full scale tree branch
* @return
*/
public CollidableTemplate getPhysicsBody(){
return this.physicsBody;
}
}

View File

@ -940,7 +940,7 @@ public class RenderingEngine {
modelTransformMatrix.translate(cameraModifiedPosition);
modelTransformMatrix.rotate(EntityUtils.getRotation(physicsEntity));
// modelTransformMatrix.translate(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()); //center sphere
modelTransformMatrix.scale(template.getDimension1(),template.getDimension2(),template.getDimension3());
modelTransformMatrix.scale(template.getDimension1() * 0.5,template.getDimension2() * 0.5,template.getDimension3() * 0.5);
physicsGraphicsModel.modelMatrix = modelTransformMatrix;
physicsGraphicsModel.draw(renderPipelineState);
}