refactor project structure, implement tessellator
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
window.BoundingBox = class {
|
||||
|
||||
/**
|
||||
* Bounding box
|
||||
*
|
||||
* @param minX Minimum x side
|
||||
* @param minY Minimum y side
|
||||
* @param minZ Minimum z side
|
||||
* @param maxX Maximum x side
|
||||
* @param maxY Maximum y side
|
||||
* @param maxZ Maximum z side
|
||||
*/
|
||||
constructor(minX, minY, minZ, maxX, maxY, maxZ) {
|
||||
this.epsilon = 0.0;
|
||||
|
||||
this.minX = minX;
|
||||
this.minY = minY;
|
||||
this.minZ = minZ;
|
||||
this.maxX = maxX;
|
||||
this.maxY = maxY;
|
||||
this.maxZ = maxZ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the current bounding box object
|
||||
*
|
||||
* @return Clone of the bounding box
|
||||
*/
|
||||
clone() {
|
||||
return new BoundingBox(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the bounding box. Positive and negative numbers controls which side of the box should grow.
|
||||
*
|
||||
* @param x Amount to expand the minX or maxX
|
||||
* @param y Amount to expand the minY or maxY
|
||||
* @param z Amount to expand the minZ or maxZ
|
||||
* @return The expanded bounding box
|
||||
*/
|
||||
expand(x, y, z) {
|
||||
let minX = this.minX;
|
||||
let minY = this.minY;
|
||||
let minZ = this.minZ;
|
||||
let maxX = this.maxX;
|
||||
let maxY = this.maxY;
|
||||
let maxZ = this.maxZ;
|
||||
|
||||
// Handle expanding of min/max x
|
||||
if (x < 0.0) {
|
||||
minX += x;
|
||||
} else {
|
||||
maxX += x;
|
||||
}
|
||||
|
||||
// Handle expanding of min/max y
|
||||
if (y < 0.0) {
|
||||
minY += y;
|
||||
} else {
|
||||
maxY += y;
|
||||
}
|
||||
|
||||
// Handle expanding of min/max z
|
||||
if (z < 0.0) {
|
||||
minZ += z;
|
||||
} else {
|
||||
maxZ += z;
|
||||
}
|
||||
|
||||
// Create new bounding box
|
||||
return new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Expand the bounding box on both sides.
|
||||
* The center is always fixed when using grow.
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
grow(x, y, z) {
|
||||
return new BoundingBox(
|
||||
this.minX - x,
|
||||
this.minY - y,
|
||||
this.minZ - z,
|
||||
this.maxX + x,
|
||||
this.maxY + y,
|
||||
this.maxZ + z
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check for collision on the X axis
|
||||
*
|
||||
* @param otherBoundingBox The other bounding box that is colliding with the this one.
|
||||
* @param x Position on the X axis that is colliding
|
||||
* @return Returns the corrected x position that collided.
|
||||
*/
|
||||
clipXCollide(otherBoundingBox, x) {
|
||||
// Check if the boxes are colliding on the Y axis
|
||||
if (otherBoundingBox.maxY <= this.minY || otherBoundingBox.minY >= this.maxY) {
|
||||
return x;
|
||||
}
|
||||
|
||||
// Check if the boxes are colliding on the Z axis
|
||||
if (otherBoundingBox.maxZ <= this.minZ || otherBoundingBox.minZ >= this.maxZ) {
|
||||
return x;
|
||||
}
|
||||
|
||||
// Check for collision if the X axis of the current box is bigger
|
||||
if (x > 0.0 && otherBoundingBox.maxX <= this.minX) {
|
||||
let max = this.minX - otherBoundingBox.maxX - this.epsilon;
|
||||
if (max < x) {
|
||||
x = max;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for collision if the X axis of the current box is smaller
|
||||
if (x < 0.0 && otherBoundingBox.minX >= this.maxX) {
|
||||
let max = this.maxX - otherBoundingBox.minX + this.epsilon;
|
||||
if (max > x) {
|
||||
x = max;
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for collision on the Y axis
|
||||
*
|
||||
* @param otherBoundingBox The other bounding box that is colliding with the this one.
|
||||
* @param y Position on the X axis that is colliding
|
||||
* @return Returns the corrected x position that collided.
|
||||
*/
|
||||
clipYCollide(otherBoundingBox, y) {
|
||||
// Check if the boxes are colliding on the X axis
|
||||
if (otherBoundingBox.maxX <= this.minX || otherBoundingBox.minX >= this.maxX) {
|
||||
return y;
|
||||
}
|
||||
|
||||
// Check if the boxes are colliding on the Z axis
|
||||
if (otherBoundingBox.maxZ <= this.minZ || otherBoundingBox.minZ >= this.maxZ) {
|
||||
return y;
|
||||
}
|
||||
|
||||
// Check for collision if the Y axis of the current box is bigger
|
||||
if (y > 0.0 && otherBoundingBox.maxY <= this.minY) {
|
||||
let max = this.minY - otherBoundingBox.maxY - this.epsilon;
|
||||
if (max < y) {
|
||||
y = max;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for collision if the Y axis of the current box is bigger
|
||||
if (y < 0.0 && otherBoundingBox.minY >= this.maxY) {
|
||||
let max = this.maxY - otherBoundingBox.minY + this.epsilon;
|
||||
if (max > y) {
|
||||
y = max;
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check for collision on the Y axis
|
||||
*
|
||||
* @param otherBoundingBox The other bounding box that is colliding with the this one.
|
||||
* @param z Position on the X axis that is colliding
|
||||
* @return Returns the corrected x position that collided.
|
||||
*/
|
||||
clipZCollide(otherBoundingBox, z) {
|
||||
// Check if the boxes are colliding on the X axis
|
||||
if (otherBoundingBox.maxX <= this.minX || otherBoundingBox.minX >= this.maxX) {
|
||||
return z;
|
||||
}
|
||||
|
||||
// Check if the boxes are colliding on the Y axis
|
||||
if (otherBoundingBox.maxY <= this.minY || otherBoundingBox.minY >= this.maxY) {
|
||||
return z;
|
||||
}
|
||||
|
||||
// Check for collision if the Z axis of the current box is bigger
|
||||
if (z > 0.0 && otherBoundingBox.maxZ <= this.minZ) {
|
||||
let max = this.minZ - otherBoundingBox.maxZ - this.epsilon;
|
||||
if (max < z) {
|
||||
z = max;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for collision if the Z axis of the current box is bigger
|
||||
if (z < 0.0 && otherBoundingBox.minZ >= this.maxZ) {
|
||||
let max = this.maxZ - otherBoundingBox.minZ + this.epsilon;
|
||||
if (max > z) {
|
||||
z = max;
|
||||
}
|
||||
}
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the two boxes are intersecting/overlapping
|
||||
*
|
||||
* @param otherBoundingBox The other bounding box that could intersect
|
||||
* @return The two boxes are overlapping
|
||||
*/
|
||||
intersects(otherBoundingBox) {
|
||||
// Check on X axis
|
||||
if (otherBoundingBox.maxX <= this.minX || otherBoundingBox.minX >= this.maxX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check on Y axis
|
||||
if (otherBoundingBox.maxY <= this.minY || otherBoundingBox.minY >= this.maxY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check on Z axis
|
||||
return (!(otherBoundingBox.maxZ <= this.minZ)) && (!(otherBoundingBox.minZ >= this.maxZ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the bounding box relative.
|
||||
*
|
||||
* @param x Relative offset x
|
||||
* @param y Relative offset y
|
||||
* @param z Relative offset z
|
||||
*/
|
||||
move(x, y, z) {
|
||||
this.minX += x;
|
||||
this.minY += y;
|
||||
this.minZ += z;
|
||||
this.maxX += x;
|
||||
this.maxY += y;
|
||||
this.maxZ += z;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new bounding box with the given offset
|
||||
*
|
||||
* @param x Relative offset x
|
||||
* @param y Relative offset x
|
||||
* @param z Relative offset x
|
||||
* @return New bounding box with the given offset relative to this bounding box
|
||||
*/
|
||||
offset(x, y, z) {
|
||||
return new BoundingBox(
|
||||
this.minX + x,
|
||||
this.minY + y,
|
||||
this.minZ + z,
|
||||
this.maxX + x,
|
||||
this.maxY + y,
|
||||
this.maxZ + z
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
window.Keyboard = class {
|
||||
|
||||
static state = {};
|
||||
|
||||
static create() {
|
||||
window.addEventListener('keydown', function (event) {
|
||||
Keyboard.state[event.code] = true;
|
||||
//console.log("Key " + event.code + " down");
|
||||
});
|
||||
window.addEventListener('keyup', function (event) {
|
||||
delete Keyboard.state[event.code];
|
||||
//console.log("Key " + event.code + " up");
|
||||
});
|
||||
};
|
||||
|
||||
static isKeyDown(key) {
|
||||
return Keyboard.state[key];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
window.MathHelper = class {
|
||||
|
||||
/**
|
||||
* Returns the greatest integer less than or equal to the double argument
|
||||
*/
|
||||
static floor_double(value) {
|
||||
let i = parseInt(value);
|
||||
return value < i ? i - 1 : i;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
window.Timer = class {
|
||||
|
||||
/**
|
||||
* Timer to control the tick speed independently of the framerate
|
||||
*
|
||||
* @param ticksPerSecond Amount of ticks per second
|
||||
*/
|
||||
constructor(ticksPerSecond) {
|
||||
this.MS_PER_SECOND = 1000;
|
||||
this.MAX_MS_PER_UPDATE = 1000;
|
||||
this.MAX_TICKS_PER_UPDATE = 100;
|
||||
|
||||
/**
|
||||
* Amount of ticks per second
|
||||
*/
|
||||
this.ticksPerSecond = ticksPerSecond;
|
||||
|
||||
/**
|
||||
* Last time updated in nano seconds
|
||||
*/
|
||||
this.lastTime = this._nanoTime();
|
||||
|
||||
/**
|
||||
* Scale the tick speed
|
||||
*/
|
||||
this.timeScale = 1.0;
|
||||
|
||||
/**
|
||||
* Framerate of the advanceTime update
|
||||
*/
|
||||
this.fps = 0.0;
|
||||
|
||||
/**
|
||||
* Passed time since last game update
|
||||
*/
|
||||
this.passedTime = 0.0;
|
||||
|
||||
/**
|
||||
* The amount of ticks for the current game update.
|
||||
* It's the passed time as an integer
|
||||
*/
|
||||
this.ticks = 0;
|
||||
|
||||
/**
|
||||
* The overflow of the current tick, caused by casting the passed time to an integer
|
||||
*/
|
||||
this.partialTicks = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function calculates the amount of ticks required to reach the ticksPerSecond.
|
||||
* Call this function in the main render loop of the game
|
||||
*/
|
||||
advanceTime() {
|
||||
let now = this._nanoTime();
|
||||
let passedMs = now - this.lastTime;
|
||||
|
||||
// Store nano time of this update
|
||||
this.lastTime = now;
|
||||
|
||||
// Maximum and minimum
|
||||
passedMs = Math.max(0, passedMs);
|
||||
passedMs = Math.min(this.MAX_MS_PER_UPDATE, passedMs);
|
||||
|
||||
// Calculate fps
|
||||
this.fps = this.MS_PER_SECOND / passedMs;
|
||||
|
||||
// Calculate passed time and ticks
|
||||
this.passedTime += passedMs * this.timeScale * this.ticksPerSecond / this.MS_PER_SECOND;
|
||||
this.ticks = parseInt(this.passedTime);
|
||||
|
||||
// Maximum ticks per update
|
||||
this.ticks = Math.min(this.MAX_TICKS_PER_UPDATE, this.ticks);
|
||||
|
||||
// Calculate the overflow of the current tick
|
||||
this.passedTime -= this.ticks;
|
||||
this.partialTicks = this.passedTime;
|
||||
}
|
||||
|
||||
_nanoTime() {
|
||||
return Date.now();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user