Initial commit
This commit is contained in:
37071
HTML/ThreeJS/node_modules/three/examples/jsm/libs/OimoPhysics/OimoPhysics.js
generated
vendored
Normal file
37071
HTML/ThreeJS/node_modules/three/examples/jsm/libs/OimoPhysics/OimoPhysics.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
43
HTML/ThreeJS/node_modules/three/examples/jsm/libs/OimoPhysics/index.js
generated
vendored
Normal file
43
HTML/ThreeJS/node_modules/three/examples/jsm/libs/OimoPhysics/index.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import {oimo} from './OimoPhysics.js';
|
||||
|
||||
// dynamics
|
||||
export const World = oimo.dynamics.World;
|
||||
export const RigidBodyType = oimo.dynamics.rigidbody.RigidBodyType;
|
||||
export const RigidBodyConfig = oimo.dynamics.rigidbody.RigidBodyConfig;
|
||||
export const ShapeConfig = oimo.dynamics.rigidbody.ShapeConfig;
|
||||
export const RigidBody = oimo.dynamics.rigidbody.RigidBody;
|
||||
export const Shape = oimo.dynamics.rigidbody.Shape;
|
||||
export const SphericalJoint = oimo.dynamics.constraint.joint.SphericalJoint;
|
||||
export const RevoluteJointConfig = oimo.dynamics.constraint.joint.RevoluteJointConfig;
|
||||
export const UniversalJointConfig = oimo.dynamics.constraint.joint.UniversalJointConfig;
|
||||
export const CylindricalJoint = oimo.dynamics.constraint.joint.CylindricalJoint;
|
||||
export const PrismaticJoint = oimo.dynamics.constraint.joint.PrismaticJoint;
|
||||
export const PrismaticJointConfig = oimo.dynamics.constraint.joint.PrismaticJointConfig;
|
||||
export const RevoluteJoint = oimo.dynamics.constraint.joint.RevoluteJoint;
|
||||
export const RagdollJoint = oimo.dynamics.constraint.joint.RagdollJoint;
|
||||
export const CylindricalJointConfig = oimo.dynamics.constraint.joint.CylindricalJointConfig;
|
||||
export const SphericalJointConfig = oimo.dynamics.constraint.joint.SphericalJointConfig;
|
||||
export const RagdollJointConfig = oimo.dynamics.constraint.joint.RagdollJointConfig;
|
||||
export const SpringDamper = oimo.dynamics.constraint.joint.SpringDamper;
|
||||
export const TranslationalLimitMotor = oimo.dynamics.constraint.joint.TranslationalLimitMotor;
|
||||
export const RotationalLimitMotor = oimo.dynamics.constraint.joint.RotationalLimitMotor;
|
||||
export const UniversalJoint = oimo.dynamics.constraint.joint.UniversalJoint;
|
||||
|
||||
// common
|
||||
export const Vec3 = oimo.common.Vec3;
|
||||
export const Quat = oimo.common.Quat;
|
||||
export const Mat3 = oimo.common.Mat3;
|
||||
export const MathUtil = oimo.common.MathUtil;
|
||||
export const Transform = oimo.common.Transform;
|
||||
|
||||
// collision
|
||||
export const OCapsuleGeometry = oimo.collision.geometry.CapsuleGeometry;
|
||||
export const OConvexHullGeometry = oimo.collision.geometry.ConvexHullGeometry;
|
||||
export const OBoxGeometry = oimo.collision.geometry.BoxGeometry;
|
||||
export const OSphereGeometry = oimo.collision.geometry.SphereGeometry;
|
||||
export const OCylinderGeometry = oimo.collision.geometry.CylinderGeometry;
|
||||
export const OConeGeometry = oimo.collision.geometry.ConeGeometry;
|
||||
export const OGeometry = oimo.collision.geometry.Geometry;
|
||||
|
||||
// callback
|
||||
export const RayCastClosest = oimo.dynamics.callback.RayCastClosest;
|
||||
141
HTML/ThreeJS/node_modules/three/examples/jsm/libs/chevrotain.module.min.js
generated
vendored
Normal file
141
HTML/ThreeJS/node_modules/three/examples/jsm/libs/chevrotain.module.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1792
HTML/ThreeJS/node_modules/three/examples/jsm/libs/ecsy.module.js
generated
vendored
Normal file
1792
HTML/ThreeJS/node_modules/three/examples/jsm/libs/ecsy.module.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2474
HTML/ThreeJS/node_modules/three/examples/jsm/libs/fflate.module.js
generated
vendored
Normal file
2474
HTML/ThreeJS/node_modules/three/examples/jsm/libs/fflate.module.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4102
HTML/ThreeJS/node_modules/three/examples/jsm/libs/flow.module.js
generated
vendored
Normal file
4102
HTML/ThreeJS/node_modules/three/examples/jsm/libs/flow.module.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
HTML/ThreeJS/node_modules/three/examples/jsm/libs/ktx-parse.module.js
generated
vendored
Normal file
1
HTML/ThreeJS/node_modules/three/examples/jsm/libs/ktx-parse.module.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
8
HTML/ThreeJS/node_modules/three/examples/jsm/libs/lil-gui.module.min.js
generated
vendored
Normal file
8
HTML/ThreeJS/node_modules/three/examples/jsm/libs/lil-gui.module.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
113
HTML/ThreeJS/node_modules/three/examples/jsm/libs/meshopt_decoder.module.js
generated
vendored
Normal file
113
HTML/ThreeJS/node_modules/three/examples/jsm/libs/meshopt_decoder.module.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
11530
HTML/ThreeJS/node_modules/three/examples/jsm/libs/mmdparser.module.js
generated
vendored
Normal file
11530
HTML/ThreeJS/node_modules/three/examples/jsm/libs/mmdparser.module.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
397
HTML/ThreeJS/node_modules/three/examples/jsm/libs/motion-controllers.module.js
generated
vendored
Normal file
397
HTML/ThreeJS/node_modules/three/examples/jsm/libs/motion-controllers.module.js
generated
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
/**
|
||||
* @webxr-input-profiles/motion-controllers 1.0.0 https://github.com/immersive-web/webxr-input-profiles
|
||||
*/
|
||||
|
||||
const Constants = {
|
||||
Handedness: Object.freeze({
|
||||
NONE: 'none',
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right'
|
||||
}),
|
||||
|
||||
ComponentState: Object.freeze({
|
||||
DEFAULT: 'default',
|
||||
TOUCHED: 'touched',
|
||||
PRESSED: 'pressed'
|
||||
}),
|
||||
|
||||
ComponentProperty: Object.freeze({
|
||||
BUTTON: 'button',
|
||||
X_AXIS: 'xAxis',
|
||||
Y_AXIS: 'yAxis',
|
||||
STATE: 'state'
|
||||
}),
|
||||
|
||||
ComponentType: Object.freeze({
|
||||
TRIGGER: 'trigger',
|
||||
SQUEEZE: 'squeeze',
|
||||
TOUCHPAD: 'touchpad',
|
||||
THUMBSTICK: 'thumbstick',
|
||||
BUTTON: 'button'
|
||||
}),
|
||||
|
||||
ButtonTouchThreshold: 0.05,
|
||||
|
||||
AxisTouchThreshold: 0.1,
|
||||
|
||||
VisualResponseProperty: Object.freeze({
|
||||
TRANSFORM: 'transform',
|
||||
VISIBILITY: 'visibility'
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Static helper function to fetch a JSON file and turn it into a JS object
|
||||
* @param {string} path - Path to JSON file to be fetched
|
||||
*/
|
||||
async function fetchJsonFile(path) {
|
||||
const response = await fetch(path);
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
} else {
|
||||
return response.json();
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchProfilesList(basePath) {
|
||||
if (!basePath) {
|
||||
throw new Error('No basePath supplied');
|
||||
}
|
||||
|
||||
const profileListFileName = 'profilesList.json';
|
||||
const profilesList = await fetchJsonFile(`${basePath}/${profileListFileName}`);
|
||||
return profilesList;
|
||||
}
|
||||
|
||||
async function fetchProfile(xrInputSource, basePath, defaultProfile = null, getAssetPath = true) {
|
||||
if (!xrInputSource) {
|
||||
throw new Error('No xrInputSource supplied');
|
||||
}
|
||||
|
||||
if (!basePath) {
|
||||
throw new Error('No basePath supplied');
|
||||
}
|
||||
|
||||
// Get the list of profiles
|
||||
const supportedProfilesList = await fetchProfilesList(basePath);
|
||||
|
||||
// Find the relative path to the first requested profile that is recognized
|
||||
let match;
|
||||
xrInputSource.profiles.some((profileId) => {
|
||||
const supportedProfile = supportedProfilesList[profileId];
|
||||
if (supportedProfile) {
|
||||
match = {
|
||||
profileId,
|
||||
profilePath: `${basePath}/${supportedProfile.path}`,
|
||||
deprecated: !!supportedProfile.deprecated
|
||||
};
|
||||
}
|
||||
return !!match;
|
||||
});
|
||||
|
||||
if (!match) {
|
||||
if (!defaultProfile) {
|
||||
throw new Error('No matching profile name found');
|
||||
}
|
||||
|
||||
const supportedProfile = supportedProfilesList[defaultProfile];
|
||||
if (!supportedProfile) {
|
||||
throw new Error(`No matching profile name found and default profile "${defaultProfile}" missing.`);
|
||||
}
|
||||
|
||||
match = {
|
||||
profileId: defaultProfile,
|
||||
profilePath: `${basePath}/${supportedProfile.path}`,
|
||||
deprecated: !!supportedProfile.deprecated
|
||||
};
|
||||
}
|
||||
|
||||
const profile = await fetchJsonFile(match.profilePath);
|
||||
|
||||
let assetPath;
|
||||
if (getAssetPath) {
|
||||
let layout;
|
||||
if (xrInputSource.handedness === 'any') {
|
||||
layout = profile.layouts[Object.keys(profile.layouts)[0]];
|
||||
} else {
|
||||
layout = profile.layouts[xrInputSource.handedness];
|
||||
}
|
||||
if (!layout) {
|
||||
throw new Error(
|
||||
`No matching handedness, ${xrInputSource.handedness}, in profile ${match.profileId}`
|
||||
);
|
||||
}
|
||||
|
||||
if (layout.assetPath) {
|
||||
assetPath = match.profilePath.replace('profile.json', layout.assetPath);
|
||||
}
|
||||
}
|
||||
|
||||
return { profile, assetPath };
|
||||
}
|
||||
|
||||
/** @constant {Object} */
|
||||
const defaultComponentValues = {
|
||||
xAxis: 0,
|
||||
yAxis: 0,
|
||||
button: 0,
|
||||
state: Constants.ComponentState.DEFAULT
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Converts an X, Y coordinate from the range -1 to 1 (as reported by the Gamepad
|
||||
* API) to the range 0 to 1 (for interpolation). Also caps the X, Y values to be bounded within
|
||||
* a circle. This ensures that thumbsticks are not animated outside the bounds of their physical
|
||||
* range of motion and touchpads do not report touch locations off their physical bounds.
|
||||
* @param {number} x The original x coordinate in the range -1 to 1
|
||||
* @param {number} y The original y coordinate in the range -1 to 1
|
||||
*/
|
||||
function normalizeAxes(x = 0, y = 0) {
|
||||
let xAxis = x;
|
||||
let yAxis = y;
|
||||
|
||||
// Determine if the point is outside the bounds of the circle
|
||||
// and, if so, place it on the edge of the circle
|
||||
const hypotenuse = Math.sqrt((x * x) + (y * y));
|
||||
if (hypotenuse > 1) {
|
||||
const theta = Math.atan2(y, x);
|
||||
xAxis = Math.cos(theta);
|
||||
yAxis = Math.sin(theta);
|
||||
}
|
||||
|
||||
// Scale and move the circle so values are in the interpolation range. The circle's origin moves
|
||||
// from (0, 0) to (0.5, 0.5). The circle's radius scales from 1 to be 0.5.
|
||||
const result = {
|
||||
normalizedXAxis: (xAxis * 0.5) + 0.5,
|
||||
normalizedYAxis: (yAxis * 0.5) + 0.5
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the description of how the 3D model should visually respond to a specific user input.
|
||||
* This is accomplished by initializing the object with the name of a node in the 3D model and
|
||||
* property that need to be modified in response to user input, the name of the nodes representing
|
||||
* the allowable range of motion, and the name of the input which triggers the change. In response
|
||||
* to the named input changing, this object computes the appropriate weighting to use for
|
||||
* interpolating between the range of motion nodes.
|
||||
*/
|
||||
class VisualResponse {
|
||||
constructor(visualResponseDescription) {
|
||||
this.componentProperty = visualResponseDescription.componentProperty;
|
||||
this.states = visualResponseDescription.states;
|
||||
this.valueNodeName = visualResponseDescription.valueNodeName;
|
||||
this.valueNodeProperty = visualResponseDescription.valueNodeProperty;
|
||||
|
||||
if (this.valueNodeProperty === Constants.VisualResponseProperty.TRANSFORM) {
|
||||
this.minNodeName = visualResponseDescription.minNodeName;
|
||||
this.maxNodeName = visualResponseDescription.maxNodeName;
|
||||
}
|
||||
|
||||
// Initializes the response's current value based on default data
|
||||
this.value = 0;
|
||||
this.updateFromComponent(defaultComponentValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the visual response's interpolation weight based on component state
|
||||
* @param {Object} componentValues - The component from which to update
|
||||
* @param {number} xAxis - The reported X axis value of the component
|
||||
* @param {number} yAxis - The reported Y axis value of the component
|
||||
* @param {number} button - The reported value of the component's button
|
||||
* @param {string} state - The component's active state
|
||||
*/
|
||||
updateFromComponent({
|
||||
xAxis, yAxis, button, state
|
||||
}) {
|
||||
const { normalizedXAxis, normalizedYAxis } = normalizeAxes(xAxis, yAxis);
|
||||
switch (this.componentProperty) {
|
||||
case Constants.ComponentProperty.X_AXIS:
|
||||
this.value = (this.states.includes(state)) ? normalizedXAxis : 0.5;
|
||||
break;
|
||||
case Constants.ComponentProperty.Y_AXIS:
|
||||
this.value = (this.states.includes(state)) ? normalizedYAxis : 0.5;
|
||||
break;
|
||||
case Constants.ComponentProperty.BUTTON:
|
||||
this.value = (this.states.includes(state)) ? button : 0;
|
||||
break;
|
||||
case Constants.ComponentProperty.STATE:
|
||||
if (this.valueNodeProperty === Constants.VisualResponseProperty.VISIBILITY) {
|
||||
this.value = (this.states.includes(state));
|
||||
} else {
|
||||
this.value = this.states.includes(state) ? 1.0 : 0.0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unexpected visualResponse componentProperty ${this.componentProperty}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Component {
|
||||
/**
|
||||
* @param {Object} componentId - Id of the component
|
||||
* @param {Object} componentDescription - Description of the component to be created
|
||||
*/
|
||||
constructor(componentId, componentDescription) {
|
||||
if (!componentId
|
||||
|| !componentDescription
|
||||
|| !componentDescription.visualResponses
|
||||
|| !componentDescription.gamepadIndices
|
||||
|| Object.keys(componentDescription.gamepadIndices).length === 0) {
|
||||
throw new Error('Invalid arguments supplied');
|
||||
}
|
||||
|
||||
this.id = componentId;
|
||||
this.type = componentDescription.type;
|
||||
this.rootNodeName = componentDescription.rootNodeName;
|
||||
this.touchPointNodeName = componentDescription.touchPointNodeName;
|
||||
|
||||
// Build all the visual responses for this component
|
||||
this.visualResponses = {};
|
||||
Object.keys(componentDescription.visualResponses).forEach((responseName) => {
|
||||
const visualResponse = new VisualResponse(componentDescription.visualResponses[responseName]);
|
||||
this.visualResponses[responseName] = visualResponse;
|
||||
});
|
||||
|
||||
// Set default values
|
||||
this.gamepadIndices = Object.assign({}, componentDescription.gamepadIndices);
|
||||
|
||||
this.values = {
|
||||
state: Constants.ComponentState.DEFAULT,
|
||||
button: (this.gamepadIndices.button !== undefined) ? 0 : undefined,
|
||||
xAxis: (this.gamepadIndices.xAxis !== undefined) ? 0 : undefined,
|
||||
yAxis: (this.gamepadIndices.yAxis !== undefined) ? 0 : undefined
|
||||
};
|
||||
}
|
||||
|
||||
get data() {
|
||||
const data = { id: this.id, ...this.values };
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Poll for updated data based on current gamepad state
|
||||
* @param {Object} gamepad - The gamepad object from which the component data should be polled
|
||||
*/
|
||||
updateFromGamepad(gamepad) {
|
||||
// Set the state to default before processing other data sources
|
||||
this.values.state = Constants.ComponentState.DEFAULT;
|
||||
|
||||
// Get and normalize button
|
||||
if (this.gamepadIndices.button !== undefined
|
||||
&& gamepad.buttons.length > this.gamepadIndices.button) {
|
||||
const gamepadButton = gamepad.buttons[this.gamepadIndices.button];
|
||||
this.values.button = gamepadButton.value;
|
||||
this.values.button = (this.values.button < 0) ? 0 : this.values.button;
|
||||
this.values.button = (this.values.button > 1) ? 1 : this.values.button;
|
||||
|
||||
// Set the state based on the button
|
||||
if (gamepadButton.pressed || this.values.button === 1) {
|
||||
this.values.state = Constants.ComponentState.PRESSED;
|
||||
} else if (gamepadButton.touched || this.values.button > Constants.ButtonTouchThreshold) {
|
||||
this.values.state = Constants.ComponentState.TOUCHED;
|
||||
}
|
||||
}
|
||||
|
||||
// Get and normalize x axis value
|
||||
if (this.gamepadIndices.xAxis !== undefined
|
||||
&& gamepad.axes.length > this.gamepadIndices.xAxis) {
|
||||
this.values.xAxis = gamepad.axes[this.gamepadIndices.xAxis];
|
||||
this.values.xAxis = (this.values.xAxis < -1) ? -1 : this.values.xAxis;
|
||||
this.values.xAxis = (this.values.xAxis > 1) ? 1 : this.values.xAxis;
|
||||
|
||||
// If the state is still default, check if the xAxis makes it touched
|
||||
if (this.values.state === Constants.ComponentState.DEFAULT
|
||||
&& Math.abs(this.values.xAxis) > Constants.AxisTouchThreshold) {
|
||||
this.values.state = Constants.ComponentState.TOUCHED;
|
||||
}
|
||||
}
|
||||
|
||||
// Get and normalize Y axis value
|
||||
if (this.gamepadIndices.yAxis !== undefined
|
||||
&& gamepad.axes.length > this.gamepadIndices.yAxis) {
|
||||
this.values.yAxis = gamepad.axes[this.gamepadIndices.yAxis];
|
||||
this.values.yAxis = (this.values.yAxis < -1) ? -1 : this.values.yAxis;
|
||||
this.values.yAxis = (this.values.yAxis > 1) ? 1 : this.values.yAxis;
|
||||
|
||||
// If the state is still default, check if the yAxis makes it touched
|
||||
if (this.values.state === Constants.ComponentState.DEFAULT
|
||||
&& Math.abs(this.values.yAxis) > Constants.AxisTouchThreshold) {
|
||||
this.values.state = Constants.ComponentState.TOUCHED;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the visual response weights based on the current component data
|
||||
Object.values(this.visualResponses).forEach((visualResponse) => {
|
||||
visualResponse.updateFromComponent(this.values);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Builds a motion controller with components and visual responses based on the
|
||||
* supplied profile description. Data is polled from the xrInputSource's gamepad.
|
||||
* @author Nell Waliczek / https://github.com/NellWaliczek
|
||||
*/
|
||||
class MotionController {
|
||||
/**
|
||||
* @param {Object} xrInputSource - The XRInputSource to build the MotionController around
|
||||
* @param {Object} profile - The best matched profile description for the supplied xrInputSource
|
||||
* @param {Object} assetUrl
|
||||
*/
|
||||
constructor(xrInputSource, profile, assetUrl) {
|
||||
if (!xrInputSource) {
|
||||
throw new Error('No xrInputSource supplied');
|
||||
}
|
||||
|
||||
if (!profile) {
|
||||
throw new Error('No profile supplied');
|
||||
}
|
||||
|
||||
this.xrInputSource = xrInputSource;
|
||||
this.assetUrl = assetUrl;
|
||||
this.id = profile.profileId;
|
||||
|
||||
// Build child components as described in the profile description
|
||||
this.layoutDescription = profile.layouts[xrInputSource.handedness];
|
||||
this.components = {};
|
||||
Object.keys(this.layoutDescription.components).forEach((componentId) => {
|
||||
const componentDescription = this.layoutDescription.components[componentId];
|
||||
this.components[componentId] = new Component(componentId, componentDescription);
|
||||
});
|
||||
|
||||
// Initialize components based on current gamepad state
|
||||
this.updateFromGamepad();
|
||||
}
|
||||
|
||||
get gripSpace() {
|
||||
return this.xrInputSource.gripSpace;
|
||||
}
|
||||
|
||||
get targetRaySpace() {
|
||||
return this.xrInputSource.targetRaySpace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns a subset of component data for simplified debugging
|
||||
*/
|
||||
get data() {
|
||||
const data = [];
|
||||
Object.values(this.components).forEach((component) => {
|
||||
data.push(component.data);
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Poll for updated data based on current gamepad state
|
||||
*/
|
||||
updateFromGamepad() {
|
||||
Object.values(this.components).forEach((component) => {
|
||||
component.updateFromGamepad(this.xrInputSource.gamepad);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { Constants, MotionController, fetchProfile, fetchProfilesList };
|
||||
119
HTML/ThreeJS/node_modules/three/examples/jsm/libs/opentype.module.min.js
generated
vendored
Normal file
119
HTML/ThreeJS/node_modules/three/examples/jsm/libs/opentype.module.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
125
HTML/ThreeJS/node_modules/three/examples/jsm/libs/potpack.module.js
generated
vendored
Normal file
125
HTML/ThreeJS/node_modules/three/examples/jsm/libs/potpack.module.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* potpack - by [@mourner](https://github.com/mourner)
|
||||
*
|
||||
* A tiny JavaScript function for packing 2D rectangles into a near-square container,
|
||||
* which is useful for generating CSS sprites and WebGL textures. Similar to
|
||||
* [shelf-pack](https://github.com/mapbox/shelf-pack), but static (you can't add items
|
||||
* once a layout is generated), and aims for maximal space utilization.
|
||||
*
|
||||
* A variation of algorithms used in [rectpack2D](https://github.com/TeamHypersomnia/rectpack2D)
|
||||
* and [bin-pack](https://github.com/bryanburgers/bin-pack), which are in turn based
|
||||
* on [this article by Blackpawn](http://blackpawn.com/texts/lightmaps/default.html).
|
||||
*
|
||||
* @license
|
||||
* ISC License
|
||||
*
|
||||
* Copyright (c) 2018, Mapbox
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
* with or without fee is hereby granted, provided that the above copyright notice
|
||||
* and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
function potpack(boxes) {
|
||||
|
||||
// calculate total box area and maximum box width
|
||||
let area = 0;
|
||||
let maxWidth = 0;
|
||||
|
||||
for (const box of boxes) {
|
||||
area += box.w * box.h;
|
||||
maxWidth = Math.max(maxWidth, box.w);
|
||||
}
|
||||
|
||||
// sort the boxes for insertion by height, descending
|
||||
boxes.sort((a, b) => b.h - a.h);
|
||||
|
||||
// aim for a squarish resulting container,
|
||||
// slightly adjusted for sub-100% space utilization
|
||||
const startWidth = Math.max(Math.ceil(Math.sqrt(area / 0.95)), maxWidth);
|
||||
|
||||
// start with a single empty space, unbounded at the bottom
|
||||
const spaces = [{x: 0, y: 0, w: startWidth, h: Infinity}];
|
||||
|
||||
let width = 0;
|
||||
let height = 0;
|
||||
|
||||
for (const box of boxes) {
|
||||
// look through spaces backwards so that we check smaller spaces first
|
||||
for (let i = spaces.length - 1; i >= 0; i--) {
|
||||
const space = spaces[i];
|
||||
|
||||
// look for empty spaces that can accommodate the current box
|
||||
if (box.w > space.w || box.h > space.h) continue;
|
||||
|
||||
// found the space; add the box to its top-left corner
|
||||
// |-------|-------|
|
||||
// | box | |
|
||||
// |_______| |
|
||||
// | space |
|
||||
// |_______________|
|
||||
box.x = space.x;
|
||||
box.y = space.y;
|
||||
|
||||
height = Math.max(height, box.y + box.h);
|
||||
width = Math.max(width, box.x + box.w);
|
||||
|
||||
if (box.w === space.w && box.h === space.h) {
|
||||
// space matches the box exactly; remove it
|
||||
const last = spaces.pop();
|
||||
if (i < spaces.length) spaces[i] = last;
|
||||
|
||||
} else if (box.h === space.h) {
|
||||
// space matches the box height; update it accordingly
|
||||
// |-------|---------------|
|
||||
// | box | updated space |
|
||||
// |_______|_______________|
|
||||
space.x += box.w;
|
||||
space.w -= box.w;
|
||||
|
||||
} else if (box.w === space.w) {
|
||||
// space matches the box width; update it accordingly
|
||||
// |---------------|
|
||||
// | box |
|
||||
// |_______________|
|
||||
// | updated space |
|
||||
// |_______________|
|
||||
space.y += box.h;
|
||||
space.h -= box.h;
|
||||
|
||||
} else {
|
||||
// otherwise the box splits the space into two spaces
|
||||
// |-------|-----------|
|
||||
// | box | new space |
|
||||
// |_______|___________|
|
||||
// | updated space |
|
||||
// |___________________|
|
||||
spaces.push({
|
||||
x: space.x + box.w,
|
||||
y: space.y,
|
||||
w: space.w - box.w,
|
||||
h: box.h
|
||||
});
|
||||
space.y += box.h;
|
||||
space.h -= box.h;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
w: width, // container width
|
||||
h: height, // container height
|
||||
fill: (area / (width * height)) || 0 // space utilization
|
||||
};
|
||||
}
|
||||
|
||||
export { potpack };
|
||||
21
HTML/ThreeJS/node_modules/three/examples/jsm/libs/rhino3dm/rhino3dm.js
generated
vendored
Normal file
21
HTML/ThreeJS/node_modules/three/examples/jsm/libs/rhino3dm/rhino3dm.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
16
HTML/ThreeJS/node_modules/three/examples/jsm/libs/rhino3dm/rhino3dm.module.js
generated
vendored
Normal file
16
HTML/ThreeJS/node_modules/three/examples/jsm/libs/rhino3dm/rhino3dm.module.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
HTML/ThreeJS/node_modules/three/examples/jsm/libs/rhino3dm/rhino3dm.wasm
generated
vendored
Normal file
BIN
HTML/ThreeJS/node_modules/three/examples/jsm/libs/rhino3dm/rhino3dm.wasm
generated
vendored
Normal file
Binary file not shown.
167
HTML/ThreeJS/node_modules/three/examples/jsm/libs/stats.module.js
generated
vendored
Normal file
167
HTML/ThreeJS/node_modules/three/examples/jsm/libs/stats.module.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
var Stats = function () {
|
||||
|
||||
var mode = 0;
|
||||
|
||||
var container = document.createElement( 'div' );
|
||||
container.style.cssText = 'position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000';
|
||||
container.addEventListener( 'click', function ( event ) {
|
||||
|
||||
event.preventDefault();
|
||||
showPanel( ++ mode % container.children.length );
|
||||
|
||||
}, false );
|
||||
|
||||
//
|
||||
|
||||
function addPanel( panel ) {
|
||||
|
||||
container.appendChild( panel.dom );
|
||||
return panel;
|
||||
|
||||
}
|
||||
|
||||
function showPanel( id ) {
|
||||
|
||||
for ( var i = 0; i < container.children.length; i ++ ) {
|
||||
|
||||
container.children[ i ].style.display = i === id ? 'block' : 'none';
|
||||
|
||||
}
|
||||
|
||||
mode = id;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var beginTime = ( performance || Date ).now(), prevTime = beginTime, frames = 0;
|
||||
|
||||
var fpsPanel = addPanel( new Stats.Panel( 'FPS', '#0ff', '#002' ) );
|
||||
var msPanel = addPanel( new Stats.Panel( 'MS', '#0f0', '#020' ) );
|
||||
|
||||
if ( self.performance && self.performance.memory ) {
|
||||
|
||||
var memPanel = addPanel( new Stats.Panel( 'MB', '#f08', '#201' ) );
|
||||
|
||||
}
|
||||
|
||||
showPanel( 0 );
|
||||
|
||||
return {
|
||||
|
||||
REVISION: 16,
|
||||
|
||||
dom: container,
|
||||
|
||||
addPanel: addPanel,
|
||||
showPanel: showPanel,
|
||||
|
||||
begin: function () {
|
||||
|
||||
beginTime = ( performance || Date ).now();
|
||||
|
||||
},
|
||||
|
||||
end: function () {
|
||||
|
||||
frames ++;
|
||||
|
||||
var time = ( performance || Date ).now();
|
||||
|
||||
msPanel.update( time - beginTime, 200 );
|
||||
|
||||
if ( time >= prevTime + 1000 ) {
|
||||
|
||||
fpsPanel.update( ( frames * 1000 ) / ( time - prevTime ), 100 );
|
||||
|
||||
prevTime = time;
|
||||
frames = 0;
|
||||
|
||||
if ( memPanel ) {
|
||||
|
||||
var memory = performance.memory;
|
||||
memPanel.update( memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return time;
|
||||
|
||||
},
|
||||
|
||||
update: function () {
|
||||
|
||||
beginTime = this.end();
|
||||
|
||||
},
|
||||
|
||||
// Backwards Compatibility
|
||||
|
||||
domElement: container,
|
||||
setMode: showPanel
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
Stats.Panel = function ( name, fg, bg ) {
|
||||
|
||||
var min = Infinity, max = 0, round = Math.round;
|
||||
var PR = round( window.devicePixelRatio || 1 );
|
||||
|
||||
var WIDTH = 80 * PR, HEIGHT = 48 * PR,
|
||||
TEXT_X = 3 * PR, TEXT_Y = 2 * PR,
|
||||
GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR,
|
||||
GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR;
|
||||
|
||||
var canvas = document.createElement( 'canvas' );
|
||||
canvas.width = WIDTH;
|
||||
canvas.height = HEIGHT;
|
||||
canvas.style.cssText = 'width:80px;height:48px';
|
||||
|
||||
var context = canvas.getContext( '2d' );
|
||||
context.font = 'bold ' + ( 9 * PR ) + 'px Helvetica,Arial,sans-serif';
|
||||
context.textBaseline = 'top';
|
||||
|
||||
context.fillStyle = bg;
|
||||
context.fillRect( 0, 0, WIDTH, HEIGHT );
|
||||
|
||||
context.fillStyle = fg;
|
||||
context.fillText( name, TEXT_X, TEXT_Y );
|
||||
context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT );
|
||||
|
||||
context.fillStyle = bg;
|
||||
context.globalAlpha = 0.9;
|
||||
context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT );
|
||||
|
||||
return {
|
||||
|
||||
dom: canvas,
|
||||
|
||||
update: function ( value, maxValue ) {
|
||||
|
||||
min = Math.min( min, value );
|
||||
max = Math.max( max, value );
|
||||
|
||||
context.fillStyle = bg;
|
||||
context.globalAlpha = 1;
|
||||
context.fillRect( 0, 0, WIDTH, GRAPH_Y );
|
||||
context.fillStyle = fg;
|
||||
context.fillText( round( value ) + ' ' + name + ' (' + round( min ) + '-' + round( max ) + ')', TEXT_X, TEXT_Y );
|
||||
|
||||
context.drawImage( canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT );
|
||||
|
||||
context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT );
|
||||
|
||||
context.fillStyle = bg;
|
||||
context.globalAlpha = 0.9;
|
||||
context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round( ( 1 - ( value / maxValue ) ) * GRAPH_HEIGHT ) );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
export default Stats;
|
||||
3
HTML/ThreeJS/node_modules/three/examples/jsm/libs/tween.module.min.js
generated
vendored
Normal file
3
HTML/ThreeJS/node_modules/three/examples/jsm/libs/tween.module.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user