implement instancing

This commit is contained in:
RandomityGuy 2021-06-04 16:38:08 +05:30
parent abcd9db939
commit 4eb5a1fd27
16 changed files with 305 additions and 92 deletions

View file

@ -22,7 +22,7 @@ import dif.math.Point3F;
import h3d.prim.BigPrimitive;
import dif.Interior;
import dif.Dif;
import src.InteriorGeometry;
import src.InteriorObject;
class DifBuilderTriangle {
public var texture:String;
@ -71,7 +71,7 @@ class DifBuilder {
}
];
public static function loadDif(path:String, itr:InteriorGeometry) {
public static function loadDif(path:String, itr:InteriorObject) {
var dif = ResourceLoader.loadInterior(path);
var geo = dif.interiors[0];

View file

@ -1,17 +1,14 @@
package src;
import src.MarbleWorld;
import src.GameObject;
import collision.CollisionHull;
import collision.CollisionSurface;
import collision.CollisionEntity;
import hxd.FloatBuffer;
import h3d.prim.DynamicPrimitive;
import h3d.scene.Trail;
import src.DynamicPolygon;
import h3d.mat.Data.Blend;
import h3d.prim.Cube;
import dts.Sequence;
import h3d.scene.Mesh;
import h3d.scene.CustomObject;
import h3d.prim.Polygon;
import h3d.prim.UV;
import h3d.Vector;
@ -20,7 +17,6 @@ import dts.Node;
import h3d.mat.BlendMode;
import h3d.mat.Data.Wrap;
import h3d.mat.Texture;
import hxd.res.Loader;
import h3d.mat.Material;
import h3d.scene.Object;
import haxe.io.Path;
@ -66,11 +62,13 @@ typedef SkinMeshData = {
}
@:publicFields
class DtsObject extends Object {
class DtsObject extends GameObject {
var dtsPath:String;
var directoryPath:String;
var dts:DtsFile;
var level:MarbleWorld;
var materials:Array<Material> = [];
var matNameOverride:Map<String, String> = new Map();
@ -79,10 +77,12 @@ class DtsObject extends Object {
var graphNodes:Array<Object> = [];
var useInstancing:Bool = true;
var isTSStatic:Bool;
var isCollideable:Bool;
var showSequences:Bool = true;
var hasNonVisualSequences:Bool = true;
var isInstanced:Bool = false;
var _regenNormals:Bool = false;
@ -97,11 +97,14 @@ class DtsObject extends Object {
super();
}
public function init() {
public function init(level:MarbleWorld) {
this.dts = ResourceLoader.loadDts(this.dtsPath);
this.directoryPath = Path.directory(this.dtsPath);
this.level = level;
this.computeMaterials();
isInstanced = this.level.instanceManager.isInstanced(this) && useInstancing;
if (!isInstanced)
this.computeMaterials();
var graphNodes = [];
var rootNodesIdx = [];
@ -150,55 +153,71 @@ class DtsObject extends Object {
if (mesh == null)
continue;
var vertices = mesh.vertices.map(v -> new Vector(v.x, v.y, v.z));
var vertexNormals = mesh.normals.map(v -> new Vector(v.x, v.y, v.z));
if (!isInstanced) {
var vertices = mesh.vertices.map(v -> new Vector(v.x, v.y, v.z));
var vertexNormals = mesh.normals.map(v -> new Vector(v.x, v.y, v.z));
var geometry = this.generateMaterialGeometry(mesh, vertices, vertexNormals);
for (k in 0...geometry.length) {
if (geometry[k].vertices.length == 0)
continue;
var geometry = this.generateMaterialGeometry(mesh, vertices, vertexNormals);
for (k in 0...geometry.length) {
if (geometry[k].vertices.length == 0)
continue;
var poly = new Polygon(geometry[k].vertices.map(x -> x.toPoint()));
poly.normals = geometry[k].normals.map(x -> x.toPoint());
poly.uvs = geometry[k].uvs;
var poly = new Polygon(geometry[k].vertices.map(x -> x.toPoint()));
poly.normals = geometry[k].normals.map(x -> x.toPoint());
poly.uvs = geometry[k].uvs;
var obj = new Mesh(poly, materials[k], this.graphNodes[i]);
var obj = new Mesh(poly, materials[k], this.graphNodes[i]);
}
} else {
var usedMats = [];
for (prim in mesh.primitives) {
if (!usedMats.contains(prim.matIndex)) {
usedMats.push(prim.matIndex);
}
}
for (k in usedMats) {
var obj = new Object(this.graphNodes[i]);
}
}
}
}
}
for (i in 0...dts.nodes.length) {
var objects = dts.objects.filter(object -> object.node == i);
var meshSurfaces = [];
var collider = new CollisionHull();
if (this.isCollideable) {
for (i in 0...dts.nodes.length) {
var objects = dts.objects.filter(object -> object.node == i);
var meshSurfaces = [];
var collider = new CollisionHull();
for (object in objects) {
var isCollisionObject = dts.names[object.name].substr(0, 3).toLowerCase() == "col";
for (object in objects) {
var isCollisionObject = dts.names[object.name].substr(0, 3).toLowerCase() == "col";
if (isCollisionObject) {
for (j in object.firstMesh...(object.firstMesh + object.numMeshes)) {
if (j >= this.dts.meshes.length)
continue;
if (isCollisionObject) {
for (j in object.firstMesh...(object.firstMesh + object.numMeshes)) {
if (j >= this.dts.meshes.length)
continue;
var mesh = this.dts.meshes[j];
if (mesh == null)
continue;
var mesh = this.dts.meshes[j];
if (mesh == null)
continue;
var vertices = mesh.vertices.map(v -> new Vector(v.x, v.y, v.z));
var vertexNormals = mesh.normals.map(v -> new Vector(v.x, v.y, v.z));
var vertices = mesh.vertices.map(v -> new Vector(v.x, v.y, v.z));
var vertexNormals = mesh.normals.map(v -> new Vector(v.x, v.y, v.z));
var surfaces = this.generateCollisionGeometry(mesh, vertices, vertexNormals);
for (surface in surfaces)
collider.addSurface(surface);
meshSurfaces = meshSurfaces.concat(surfaces);
var surfaces = this.generateCollisionGeometry(mesh, vertices, vertexNormals);
for (surface in surfaces)
collider.addSurface(surface);
meshSurfaces = meshSurfaces.concat(surfaces);
}
}
}
if (meshSurfaces.length != 0)
colliders.push(collider);
else
colliders.push(null);
}
if (meshSurfaces.length != 0)
colliders.push(collider);
else
colliders.push(null);
}
this.updateNodeTransforms();
@ -209,31 +228,52 @@ class DtsObject extends Object {
continue;
if (mesh.meshType == 1) {
var vertices = mesh.vertices.map(v -> new Vector(v.x, v.y, v.z));
var vertexNormals = mesh.normals.map(v -> new Vector(v.x, v.y, v.z));
var geometry = this.generateMaterialGeometry(mesh, vertices, vertexNormals);
var skinObj = new Object();
for (k in 0...geometry.length) {
if (geometry[k].vertices.length == 0)
continue;
var poly = new DynamicPolygon(geometry[k].vertices.map(x -> x.toPoint()));
poly.normals = geometry[k].normals.map(x -> x.toPoint());
poly.uvs = geometry[k].uvs;
if (!isInstanced) {
var vertices = mesh.vertices.map(v -> new Vector(v.x, v.y, v.z));
var vertexNormals = mesh.normals.map(v -> new Vector(v.x, v.y, v.z));
var geometry = this.generateMaterialGeometry(mesh, vertices, vertexNormals);
for (k in 0...geometry.length) {
if (geometry[k].vertices.length == 0)
continue;
var obj = new Mesh(poly, materials[k], skinObj);
}
skinMeshData = {
meshIndex: i,
vertices: vertices,
normals: vertexNormals,
indices: [],
geometry: skinObj
};
var idx = geometry.map(x -> x.indices);
for (indexes in idx) {
skinMeshData.indices = skinMeshData.indices.concat(indexes);
var poly = new DynamicPolygon(geometry[k].vertices.map(x -> x.toPoint()));
poly.normals = geometry[k].normals.map(x -> x.toPoint());
poly.uvs = geometry[k].uvs;
var obj = new Mesh(poly, materials[k], skinObj);
}
skinMeshData = {
meshIndex: i,
vertices: vertices,
normals: vertexNormals,
indices: [],
geometry: skinObj
};
var idx = geometry.map(x -> x.indices);
for (indexes in idx) {
skinMeshData.indices = skinMeshData.indices.concat(indexes);
}
} else {
var usedMats = [];
for (prim in mesh.primitives) {
if (!usedMats.contains(prim.matIndex)) {
usedMats.push(prim.matIndex);
}
}
for (k in usedMats) {
var obj = new Object(skinObj);
}
skinMeshData = {
meshIndex: i,
vertices: [],
normals: [],
indices: [],
geometry: skinObj
};
}
}
}
@ -243,6 +283,7 @@ class DtsObject extends Object {
for (i in rootNodesIdx) {
rootObject.addChild(this.graphNodes[i]);
}
if (this.skinMeshData != null) {
rootObject.addChild(this.skinMeshData.geometry);
}
@ -288,9 +329,9 @@ class DtsObject extends Object {
if (flags & 16 > 0)
material.blendMode = BlendMode.Sub;
if (this.isTSStatic && !(flags & 64 > 0)) {
// TODO THIS SHIT
}
// if (this.isTSStatic && !(flags & 64 > 0)) {
// // TODO THIS SHIT
// }
// ((flags & 32) || environmentMaterial) ? new Materia
this.materials.push(material);
@ -322,7 +363,7 @@ class DtsObject extends Object {
}
function generateCollisionGeometry(dtsMesh:dts.Mesh, vertices:Array<Vector>, vertexNormals:Array<Vector>) {
var surfaces = this.materials.map(x -> new CollisionSurface());
var surfaces = this.dts.matNames.map(x -> new CollisionSurface());
for (surface in surfaces) {
surface.points = [];
surface.normals = [];
@ -374,7 +415,7 @@ class DtsObject extends Object {
}
function generateMaterialGeometry(dtsMesh:dts.Mesh, vertices:Array<Vector>, vertexNormals:Array<Vector>) {
var materialGeometry:Array<MaterialGeometry> = this.materials.map(x -> {
var materialGeometry:Array<MaterialGeometry> = this.dts.matNames.map(x -> {
vertices: [],
normals: [],
uvs: [],
@ -541,7 +582,7 @@ class DtsObject extends Object {
}
}
if (this.skinMeshData != null) {
if (this.skinMeshData != null && !isInstanced) {
var info = this.skinMeshData;
var mesh = this.dts.meshes[info.meshIndex];
@ -555,7 +596,7 @@ class DtsObject extends Object {
for (i in 0...mesh.nodeIndices.length) {
var mat = mesh.initialTransforms[i].clone();
mat.transpose();
var tform = this.graphNodes[mesh.nodeIndices[i]].getAbsPos().clone();
var tform = this.graphNodes[mesh.nodeIndices[i]].getRelPos(this).clone();
mat.multiply(mat, tform);
boneTransformations.push(mat);

7
src/GameObject.hx Normal file
View file

@ -0,0 +1,7 @@
package src;
import h3d.scene.Object;
class GameObject extends Object {
public var identifier:String;
}

78
src/InstanceManager.hx Normal file
View file

@ -0,0 +1,78 @@
package src;
import h2d.col.Matrix;
import src.GameObject;
import h3d.scene.Scene;
import h3d.scene.Object;
import h3d.scene.Mesh;
import h3d.scene.MeshBatch;
typedef MeshBatchInfo = {
var instances:Array<Object>;
var meshbatch:MeshBatch;
var mesh:Mesh;
}
class InstanceManager {
var objects:Map<String, Array<MeshBatchInfo>> = new Map();
var scene:Scene;
public function new(scene:Scene) {
this.scene = scene;
}
public function update(dt:Float) {
for (obj => meshes in objects) {
for (minfo in meshes) {
if (minfo.meshbatch != null) {
minfo.meshbatch.begin(minfo.instances.length);
for (instance in minfo.instances) {
var transform = instance.getAbsPos().clone();
minfo.meshbatch.setTransform(transform);
minfo.meshbatch.emitInstance();
}
}
}
}
}
public function addObject(object:GameObject) {
function getAllChildren(object:Object):Array<Object> {
var ret = [object];
for (i in 0...object.numChildren) {
ret = ret.concat(getAllChildren(object.getChildAt(i)));
}
return ret;
}
if (isInstanced(object)) {
// Add existing instance
var objs = getAllChildren(object);
var minfos = objects.get(object.identifier);
for (i in 0...objs.length) {
minfos[i].instances.push(objs[i]);
}
} else {
// First time appending the thing so bruh
var infos = [];
var objs = getAllChildren(object);
var minfos = [];
for (obj in objs) {
var isMesh = obj is Mesh;
var minfo:MeshBatchInfo = {
instances: [obj],
meshbatch: isMesh ? new MeshBatch(cast(cast(obj, Mesh).primitive), cast(cast(obj, Mesh)).material, scene) : null,
mesh: isMesh ? cast obj : null
}
minfos.push(minfo);
}
objects.set(object.identifier, minfos);
}
}
public function isInstanced(object:GameObject) {
if (objects.exists(object.identifier))
return true;
return false;
}
}

View file

@ -2,14 +2,10 @@ package src;
import h3d.Matrix;
import collision.CollisionEntity;
import dif.math.Point3F;
import h3d.scene.Mesh;
import h3d.col.Bounds;
import h3d.scene.RenderContext;
import h3d.prim.Polygon;
import src.GameObject;
import h3d.scene.Object;
class InteriorGeometry extends Object {
class InteriorObject extends GameObject {
public var collider:CollisionEntity;
public function new() {

View file

@ -1,9 +1,15 @@
package;
import shapes.Trapdoor;
import shapes.AntiGravity;
import shapes.SuperJump;
import h3d.prim.Polygon;
import src.ResourceLoader;
import src.GameObject;
import shapes.Tornado;
import shapes.DuctFan;
import dts.DtsFile;
import src.InteriorGeometry;
import src.InteriorObject;
import h3d.Quat;
import src.PathedInteriorMarker;
import src.PathedInterior;
@ -28,10 +34,11 @@ class Main extends hxd.App {
super.init();
dtsObj = new Tornado();
dtsObj.x = 5;
world = new MarbleWorld(s3d);
var db = new InteriorGeometry();
var db = new InteriorObject();
DifBuilder.loadDif("data/interiors/beginner/training_friction.dif", db);
world.addInterior(db);
var tform = db.getTransform();
@ -44,10 +51,16 @@ class Main extends hxd.App {
// pim.setPosition(new Vector(5, 0, 0));
// pi.setTransform(pim);
// var cube = new Cube();
// cube.addUVs();
// var cube = new Polygon([new h3d.col.Point(0, 0, 0), new h3d.col.Point(0, 0, 1), new h3d.col.Point(0, 1, 0)]);
// cube.addNormals();
// var mat = Material.create();
// cube.addUVs();
// var tex = ResourceLoader.loader.load("data/interiors/arrow_cool1.jpg").toTexture();
// var mat = Material.create(tex);
// var mesh = new Mesh(cube, mat);
// var go = new GameObject();
// go.identifier = "lol";
// go.addChild(mesh);
// world.instanceManager.addObject(go);
// var m1 = new PathedInteriorMarker();
// m1.msToNext = 5;
@ -73,6 +86,15 @@ class Main extends hxd.App {
world.addDtsObject(dtsObj);
for (i in 0...10) {
for (j in 0...10) {
var trapdoor = new Tornado();
trapdoor.x = i * 2;
trapdoor.y = j * 2;
world.addDtsObject(trapdoor);
}
}
// for (surf in db.collider.surfaces) {
// var surfmin = new CustomObject(cube, mat, s3d);
// var bound = surf.boundingBox;
@ -110,6 +132,7 @@ class Main extends hxd.App {
}
static function main() {
h3d.mat.PbrMaterialSetup.set();
new Main();
}
}

View file

@ -1,19 +1,22 @@
package src;
import src.InstanceManager;
import h3d.scene.MeshBatch;
import src.DtsObject;
import src.PathedInterior;
import hxd.Key;
import h3d.Vector;
import src.InteriorGeometry;
import src.InteriorObject;
import h3d.scene.Scene;
import h3d.scene.CustomObject;
import collision.CollisionWorld;
import src.Marble;
class MarbleWorld {
var collisionWorld:CollisionWorld;
public var collisionWorld:CollisionWorld;
public var instanceManager:InstanceManager;
public var interiors:Array<InteriorGeometry> = [];
public var interiors:Array<InteriorObject> = [];
public var pathedInteriors:Array<PathedInterior> = [];
public var marbles:Array<Marble> = [];
public var dtsObjects:Array<DtsObject> = [];
@ -25,9 +28,10 @@ class MarbleWorld {
public function new(scene:Scene) {
this.collisionWorld = new CollisionWorld();
this.scene = scene;
this.instanceManager = new InstanceManager(scene);
}
public function addInterior(obj:InteriorGeometry) {
public function addInterior(obj:InteriorObject) {
this.interiors.push(obj);
this.collisionWorld.addEntity(obj.collider);
this.scene.addChild(obj);
@ -42,8 +46,12 @@ class MarbleWorld {
public function addDtsObject(obj:DtsObject) {
this.dtsObjects.push(obj);
this.scene.addChild(obj);
obj.init();
obj.init(cast this);
if (obj.useInstancing) {
this.instanceManager.addObject(obj);
} else
this.scene.addChild(obj);
// this.instanceManager.addObject(obj);
for (collider in obj.colliders) {
if (collider != null)
this.collisionWorld.addEntity(collider);
@ -67,6 +75,7 @@ class MarbleWorld {
for (marble in marbles) {
marble.update(currentTime, dt, collisionWorld, this.pathedInteriors);
}
this.instanceManager.update(dt);
currentTime += dt;
}
}

View file

@ -4,7 +4,7 @@ import h3d.Matrix;
import h3d.Vector;
import src.Util;
import src.PathedInteriorMarker;
import src.InteriorGeometry;
import src.InteriorObject;
typedef PIState = {
var currentTime:Float;
@ -15,7 +15,7 @@ typedef PIState = {
var velocity:Vector;
}
class PathedInterior extends InteriorGeometry {
class PathedInterior extends InteriorObject {
public var markerData:Array<PathedInteriorMarker> = [];
public var duration:Float;

View file

@ -1,5 +1,6 @@
package src;
import h3d.scene.Object;
import sys.FileSystem;
import sys.io.File;
import haxe.io.Path;

13
src/shapes/AntiGravity.hx Normal file
View file

@ -0,0 +1,13 @@
package shapes;
import src.DtsObject;
class AntiGravity extends DtsObject {
public function new() {
super();
this.dtsPath = "data/shapes/items/antigravity.dts";
this.isCollideable = false;
this.isTSStatic = false;
this.identifier = "AntiGravity";
}
}

View file

@ -9,6 +9,7 @@ class DuctFan extends ForceObject {
this.dtsPath = "data/shapes/hazards/ductfan.dts";
this.isCollideable = true;
this.isTSStatic = false;
this.identifier = "DuctFan";
this.forceDatas = [
{
forceType: ForceCone,

View file

@ -9,6 +9,7 @@ class SmallDuctFan extends ForceObject {
this.dtsPath = "data/shapes/hazards/ductfan.dts";
this.isCollideable = true;
this.isTSStatic = false;
this.identifier = "DuctFan";
this.forceDatas = [
{
forceType: ForceCone,

13
src/shapes/SuperJump.hx Normal file
View file

@ -0,0 +1,13 @@
package shapes;
import src.DtsObject;
class SuperJump extends DtsObject {
public function new() {
super();
this.dtsPath = "data/shapes/items/superjump.dts";
this.isCollideable = false;
this.isTSStatic = false;
this.identifier = "SuperJump";
}
}

13
src/shapes/SuperSpeed.hx Normal file
View file

@ -0,0 +1,13 @@
package shapes;
import src.DtsObject;
class SuperSpeed extends DtsObject {
public function new() {
super();
this.dtsPath = "data/shapes/items/superspeed.dts";
this.isCollideable = false;
this.isTSStatic = false;
this.identifier = "SuperSpeed";
}
}

View file

@ -9,6 +9,8 @@ class Tornado extends ForceObject {
this.dtsPath = "data/shapes/hazards/tornado.dts";
this.isCollideable = true;
this.isTSStatic = false;
this.identifier = "Tornado";
// this.useInstancing = false;
this.forceDatas = [
{
forceType: ForceSpherical,

15
src/shapes/Trapdoor.hx Normal file
View file

@ -0,0 +1,15 @@
package shapes;
import src.DtsObject;
import h3d.Vector;
import src.ForceObject;
class Trapdoor extends DtsObject {
public function new() {
super();
this.dtsPath = "data/shapes/hazards/trapdoor.dts";
this.isCollideable = true;
this.isTSStatic = false;
this.identifier = "Trapdoor";
}
}