r3-legacy/game-lib.js

2813 lines
74 KiB
JavaScript

if (typeof require != 'undefined') {
var Maths3D = require('./game-lib-maths.js');
}
if (typeof require != 'undefined') {
var Controls = require('./game-lib-controls.js');
}
function GameLib() {}
/**
* GameLib.D3 connects our GameLib.D3 assets to a graphics library like THREE.js, but could technically be any graphics
* lib
* @param config
* @param Q Q
* @param THREE THREE.js
* @param apiUrl
* @param editorUrl
* @constructor
*/
GameLib.D3 = function(
config,
Q,
THREE,
apiUrl,
editorUrl
){
this.config = config;
this.Q = Q;
this.THREE = THREE;
this.textureLoader = new this.THREE.TextureLoader();
this.apiUrl = apiUrl || this.config.api16.url;
this.editorUrl = editorUrl || this.config.editor.url;
};
if (typeof require == 'undefined' &&
typeof Maths3D == 'undefined') {
console.warn("You need a proper Maths3D library in order to use this library");
}
if (typeof require == 'undefined' &&
typeof Controls == 'undefined') {
console.warn("You need a proper Control library in order to use this library");
}
GameLib.D3.Controls = Controls;
GameLib.D3.Vector2 = Maths3D.Vector2;
GameLib.D3.Vector3 = Maths3D.Vector3;
GameLib.D3.Vector4 = Maths3D.Vector4;
GameLib.D3.Matrix4 = Maths3D.Matrix4;
GameLib.D3.Color = Maths3D.Color;
/**
* Texture Superset
* @param id
* @param path
* @param name
* @param image
* @param wrapS
* @param wrapT
* @param repeat
* @param data
* @param format
* @param mapping
* @param magFilter
* @param minFilter
* @param textureType
* @param anisotropy
* @param offset
* @param generateMipmaps
* @param flipY
* @param mipmaps
* @param unpackAlignment
* @param premultiplyAlpha
* @param encoding
* @constructor
*/
GameLib.D3.Texture = function(
id,
path,
name,
image,
wrapS,
wrapT,
repeat,
data,
format,
mapping,
magFilter,
minFilter,
textureType,
anisotropy,
offset,
generateMipmaps,
flipY,
mipmaps,
unpackAlignment,
premultiplyAlpha,
encoding
) {
this.id = id;
this.path = path;
this.name = name;
this.image = image;
if (typeof wrapS == 'undefined') {
wrapS = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING;
}
this.wrapS = wrapS;
if (typeof wrapT == 'undefined') {
wrapT = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING;
}
this.wrapT = wrapT;
if (typeof repeat == 'undefined') {
repeat = new GameLib.D3.Vector2(1, 1);
}
this.repeat = repeat;
if (typeof data == 'undefined') {
data = null;
}
this.data = data;
if (typeof format == 'undefined') {
format = GameLib.D3.Texture.TYPE_RGBA_FORMAT;
}
this.format = format;
if (typeof mapping == 'undefined') {
mapping = GameLib.D3.Texture.TYPE_UV_MAPPING;
}
this.mapping = mapping;
if (typeof magFilter == 'undefined') {
magFilter = GameLib.D3.Texture.TYPE_LINEAR_FILTER;
}
this.magFilter = magFilter;
if (typeof minFilter == 'undefined') {
minFilter = GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER;
}
this.minFilter = minFilter;
if (typeof textureType == 'undefined') {
textureType = GameLib.D3.Texture.TYPE_UNSIGNED_BYTE;
}
this.textureType = textureType;
if (typeof anisotropy == 'undefined') {
anisotropy = 1;
}
this.anisotropy = anisotropy;
if (typeof offset == 'undefined') {
offset = new GameLib.D3.Vector2(0, 0);
}
this.offset = offset;
if (typeof generateMipmaps == 'undefined') {
generateMipmaps = true;
}
this.generateMipmaps = generateMipmaps;
if (typeof flipY == 'undefined') {
flipY = true;
}
this.flipY = flipY;
if (typeof mipmaps == 'undefined') {
mipmaps = [];
}
this.mipmaps = mipmaps;
if (typeof unpackAlignment == 'undefined') {
unpackAlignment = 4;
}
this.unpackAlignment = unpackAlignment;
if (typeof premultiplyAlpha == 'undefined') {
premultiplyAlpha = false;
}
this.premultiplyAlpha = premultiplyAlpha;
if (typeof encoding == 'undefined') {
encoding = GameLib.D3.Texture.TYPE_LINEAR_ENCODING;
}
this.encoding = encoding;
};
/**
* Texture Formats
* @type {number}
*/
GameLib.D3.Texture.TYPE_ALPHA_FORMAT = 1019;
GameLib.D3.Texture.TYPE_RGB_FORMAT = 1020;
GameLib.D3.Texture.TYPE_RGBA_FORMAT = 1021;
GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT = 1022;
GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT = 1023;
GameLib.D3.Texture.TYPE_DEPTH_FORMAT = 1026;
/**
* Mapping modes
* @type {number}
*/
GameLib.D3.Texture.TYPE_UV_MAPPING = 300;
GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING = 301;
GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING = 302;
GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING = 303;
GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING = 304;
GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING = 305;
GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING = 306;
GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING = 307;
/**
* Wrapping Modes
* @type {number}
*/
GameLib.D3.Texture.TYPE_REPEAT_WRAPPING = 1000;
GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING = 1001;
GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING = 1002;
/**
* Mipmap Filters
* @type {number}
*/
GameLib.D3.Texture.TYPE_NEAREST_FILTER = 1003;
GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER = 1004;
GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER = 1005;
GameLib.D3.Texture.TYPE_LINEAR_FILTER = 1006;
GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER = 1007;
GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER = 1008;
/**
* Texture Data Types
* @type {number}
*/
GameLib.D3.Texture.TYPE_UNSIGNED_BYTE = 1009;
GameLib.D3.Texture.TYPE_BYTE = 1010;
GameLib.D3.Texture.TYPE_SHORT = 1011;
GameLib.D3.Texture.TYPE_UNSIGNED_SHORT = 1012;
GameLib.D3.Texture.TYPE_INT = 1013;
GameLib.D3.Texture.TYPE_UNSIGNED_INT = 1014;
GameLib.D3.Texture.TYPE_FLOAT = 1015;
GameLib.D3.Texture.TYPE_HALF_FLOAT = 1025;
/**
* Encoding Modes
* @type {number}
*/
GameLib.D3.Texture.TYPE_LINEAR_ENCODING = 3000; // NO ENCODING AT ALL.
GameLib.D3.Texture.TYPE_SRGB_ENCODING = 3001;
GameLib.D3.Texture.TYPE_GAMMA_ENCODING = 3007; // USES GAMMA_FACTOR, FOR BACKWARDS COMPATIBILITY WITH WEBGLRENDERER.GAMMAINPUT/GAMMAOUTPUT
GameLib.D3.Texture.TYPE_RGBE_ENCODING = 3002; // AKA RADIANCE.
GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING = 3003;
GameLib.D3.Texture.TYPE_RGBM7_ENCODING = 3004;
GameLib.D3.Texture.TYPE_RGBM16_ENCODING = 3005;
GameLib.D3.Texture.TYPE_RGBD_ENCODING = 3006; // MAXRANGE IS 256.
/**
* Light Superset
* @param id
* @param lightType
* @param name
* @param color
* @param intensity
* @param position
* @param targetPosition
* @param quaternion
* @param rotation
* @param scale
* @param distance
* @param decay
* @param power
* @param angle
* @param penumbra
* @constructor
*/
GameLib.D3.Light = function(
id,
lightType,
name,
color,
intensity,
position,
targetPosition,
quaternion,
rotation,
scale,
distance,
decay,
power,
angle,
penumbra
) {
this.id = id;
this.lightType = lightType;
this.name = name;
this.color = color;
this.intensity = intensity;
if (typeof position == 'undefined') {
position = new GameLib.D3.Vector3(0,0,0);
}
this.position = position;
if (typeof targetPosition == 'undefined') {
targetPosition = new GameLib.D3.Vector3(0,0,0);
}
this.targetPosition = targetPosition;
if (typeof quaternion == 'undefined'){
quaternion = new GameLib.D3.Vector4();
}
this.quaternion = quaternion;
if (typeof rotation == 'undefined'){
rotation = new GameLib.D3.Vector3(0,0,0);
}
this.rotation = rotation;
if (typeof scale == 'undefined'){
scale = new GameLib.D3.Vector3(1,1,1);
}
this.scale = scale;
if (typeof distance == 'undefined'){
distance = 0;
}
this.distance = distance;
if (typeof decay == 'undefined'){
decay = 1;
}
this.decay = decay;
if (typeof power == 'undefined'){
power = 4 * Math.PI;
}
this.power = power;
if (typeof angle == 'undefined'){
angle = Math.PI / 3;
}
this.angle = angle;
if (typeof penumbra == 'undefined'){
penumbra = 0;
}
this.penumbra = penumbra;
};
/**
* Material Superset
* @param id
* @param path
* @param name
* @param materialType
* @param opacity
* @param side
* @param transparent
* @param maps
* @param specular
* @param lightMapIntensity
* @param aoMapIntensity
* @param color
* @param emissive
* @param emissiveIntensity
* @param combine
* @param shininess
* @param reflectivity
* @param refractionRatio
* @param fog
* @param wireframe
* @param wireframeLineWidth
* @param wireframeLineCap
* @param wireframeLineJoin
* @param vertexColors
* @param skinning
* @param morphTargets
* @param morphNormals
* @param lineWidth
* @param lineCap
* @param lineJoin
* @param dashSize
* @param gapWidth
* @param blending
* @param blendSrc
* @param blendDst
* @param blendEquation
* @param depthTest
* @param depthFunc
* @param depthWrite
* @param polygonOffset
* @param polygonOffsetFactor
* @param polygonOffsetUnits
* @param alphaTest
* @param clippingPlanes
* @param clipShadows
* @param visible
* @param overdraw
* @param shading
* @param bumpScale
* @param normalScale
* @param displacementScale
* @param displacementBias
* @param roughness
* @param metalness
* @param pointSize
* @param pointSizeAttenuation
* @param spriteRotation
* @param envMapIntensity
* @constructor
*/
GameLib.D3.Material = function(
id,
path,
name,
materialType,
opacity,
side,
transparent,
maps,
specular,
lightMapIntensity,
aoMapIntensity,
color,
emissive,
emissiveIntensity,
combine,
shininess,
reflectivity,
refractionRatio,
fog,
wireframe,
wireframeLineWidth,
wireframeLineCap,
wireframeLineJoin,
vertexColors,
skinning,
morphTargets,
morphNormals,
lineWidth,
lineCap,
lineJoin,
dashSize,
gapWidth,
blending,
blendSrc,
blendDst,
blendEquation,
depthTest,
depthFunc,
depthWrite,
polygonOffset,
polygonOffsetFactor,
polygonOffsetUnits,
alphaTest,
clippingPlanes,
clipShadows,
visible,
overdraw,
shading,
bumpScale,
normalScale,
displacementScale,
displacementBias,
roughness,
metalness,
pointSize,
pointSizeAttenuation,
spriteRotation,
envMapIntensity
) {
this.id = id;
this.path = path;
this.name = name;
if (typeof materialType == 'undefined') {
materialType = GameLib.D3.Material.TYPE_MESH_STANDARD;
}
this.materialType = materialType;
if (typeof opacity == 'undefined') {
opacity = 1.0;
}
this.opacity = opacity;
if (typeof side == 'undefined') {
side = GameLib.D3.Material.TYPE_FRONT_SIDE;
}
this.side = side;
if (typeof transparent == 'undefined') {
transparent = false;
}
this.transparent = transparent;
if (typeof maps == 'undefined') {
maps = {
alpha: null,
ao: null,
bump: null,
diffuse: null,
displacement: null,
emissive: null,
environment: null,
light: null,
metalness: null,
normal: null,
roughness: null,
specular: null
};
}
this.maps = maps;
if (typeof specular == 'undefined') {
specular = new GameLib.D3.Color(0.06, 0.06, 0.06, 0.06);
}
this.specular = specular;
if (typeof lightMapIntensity == 'undefined') {
lightMapIntensity = 1;
}
this.lightMapIntensity = lightMapIntensity;
if (typeof aoMapIntensity == 'undefined') {
aoMapIntensity = 1;
}
this.aoMapIntensity = aoMapIntensity;
if (typeof color == 'undefined') {
color = new GameLib.D3.Color(1, 1, 1, 1)
}
this.color = color;
if (typeof emissive == 'undefined') {
emissive = new GameLib.D3.Color(0, 0, 0, 0);
}
this.emissive = emissive;
if (typeof emissiveIntensity == 'undefined') {
emissiveIntensity = 1;
}
this.emissiveIntensity = emissiveIntensity;
if (typeof combine == 'undefined') {
combine = GameLib.D3.Material.TYPE_MULTIPLY_OPERATION;
}
this.combine = combine;
if (typeof shininess == 'undefined') {
shininess = 30;
}
this.shininess = shininess;
if (typeof reflectivity == 'undefined') {
reflectivity = 1;
}
this.reflectivity = reflectivity;
if (typeof refractionRatio == 'undefined') {
refractionRatio = 0.98;
}
this.refractionRatio = refractionRatio;
if (typeof fog == 'undefined') {
fog = true;
}
this.fog = fog;
if (typeof wireframe == 'undefined') {
wireframe = false;
}
this.wireframe = wireframe;
if (typeof wireframeLineWidth == 'undefined') {
wireframeLineWidth = 1;
}
this.wireframeLineWidth = wireframeLineWidth;
if (typeof wireframeLineCap == 'undefined') {
wireframeLineCap = 'round';
}
this.wireframeLineCap = wireframeLineCap;
if (typeof wireframeLineJoin == 'undefined') {
wireframeLineJoin = 'round';
}
this.wireframeLineJoin = wireframeLineJoin;
if (typeof vertexColors == 'undefined') {
vertexColors = GameLib.D3.Material.TYPE_NO_COLORS;
}
this.vertexColors = vertexColors;
if (typeof skinning == 'undefined') {
skinning = false;
}
this.skinning = skinning;
if (typeof morphTargets == 'undefined') {
morphTargets = false;
}
this.morphTargets = morphTargets;
if (typeof morphNormals == 'undefined') {
morphNormals = false;
}
this.morphNormals = morphNormals;
if (typeof overdraw == 'undefined') {
overdraw = 0;
}
this.overdraw = overdraw;
if (typeof lineWidth == 'undefined') {
lineWidth = 1;
}
this.lineWidth = lineWidth;
if (typeof lineCap == 'undefined') {
lineCap = 'round';
}
this.lineCap = lineCap;
if (typeof lineJoin == 'undefined') {
lineJoin = 'round';
}
this.lineJoin = lineJoin;
if (typeof dashSize == 'undefined') {
dashSize = 3;
}
this.dashSize = dashSize;
if (typeof gapWidth == 'undefined') {
gapWidth = 1;
}
this.gapWidth = gapWidth;
if (typeof blending == 'undefined') {
blending = GameLib.D3.Material.TYPE_NORMAL_BLENDING;
}
this.blending = blending;
if (typeof blendSrc == 'undefined') {
blendSrc = GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR;
}
this.blendSrc = blendSrc;
if (typeof blendDst == 'undefined') {
blendDst = GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR;
}
this.blendDst = blendDst;
if (typeof blendEquation == 'undefined') {
blendEquation = GameLib.D3.Material.TYPE_ADD_EQUATION;
}
this.blendEquation = blendEquation;
if (typeof depthTest == 'undefined') {
depthTest = true;
}
this.depthTest = depthTest;
if (typeof depthFunc == 'undefined') {
depthFunc = GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH;
}
this.depthFunc = depthFunc;
if (typeof depthWrite == 'undefined') {
depthWrite = true;
}
this.depthWrite = depthWrite;
if (typeof polygonOffset == 'undefined') {
polygonOffset = false;
}
this.polygonOffset = polygonOffset;
if (typeof polygonOffsetFactor == 'undefined') {
polygonOffsetFactor = 1;
}
this.polygonOffsetFactor = polygonOffsetFactor;
if (typeof polygonOffsetUnits == 'undefined') {
polygonOffsetUnits = 1;
}
this.polygonOffsetUnits = polygonOffsetUnits;
if (typeof alphaTest == 'undefined') {
alphaTest = 0;
}
this.alphaTest = alphaTest;
if (typeof clippingPlanes == 'undefined') {
clippingPlanes = [];
}
this.clippingPlanes = clippingPlanes;
if (typeof clipShadows == 'undefined') {
clipShadows = false;
}
this.clipShadows = clipShadows;
if (typeof visible == 'undefined') {
visible = true;
}
this.visible = visible;
if (typeof shading == 'undefined') {
shading = GameLib.D3.Material.TYPE_FLAT_SHADING;
}
this.shading = shading;
if (typeof bumpScale == 'undefined') {
bumpScale = 1;
}
this.bumpScale = bumpScale;
if (typeof normalScale == 'undefined') {
normalScale = 1;
}
this.normalScale = normalScale;
if (typeof displacementScale == 'undefined') {
displacementScale = 1;
}
this.displacementScale = displacementScale;
if (typeof displacementBias == 'undefined') {
displacementBias = 0;
}
this.displacementBias = displacementBias;
if (typeof roughness == 'undefined') {
roughness = 0.5;
}
this.roughness = roughness;
if (typeof metalness == 'undefined') {
metalness = 0.5;
}
this.metalness = metalness;
if (typeof pointSize == 'undefined') {
pointSize = 1;
}
this.pointSize = pointSize;
if (typeof pointSizeAttenuation == 'undefined') {
pointSizeAttenuation = true;
}
this.pointSizeAttenuation = pointSizeAttenuation;
if (typeof spriteRotation == 'undefined') {
spriteRotation = 0;
}
this.spriteRotation = spriteRotation;
if (typeof envMapIntensity == 'undefined') {
envMapIntensity = 1.0;
}
this.envMapIntensity = envMapIntensity;
};
/**
* Combine Method
* @type {number}
*/
GameLib.D3.Material.TYPE_MULTIPLY_OPERATION = 0;
GameLib.D3.Material.TYPE_MIX_OPERATION = 1;
GameLib.D3.Material.TYPE_ADD_OPERATION = 2;
/**
* Vertex Color Mode
* @type {number}
*/
GameLib.D3.Material.TYPE_NO_COLORS = 0;
GameLib.D3.Material.TYPE_FACE_COLORS = 1;
GameLib.D3.Material.TYPE_VERTEX_COLORS = 2;
/**
* Blending Mode
* @type {number}
*/
GameLib.D3.Material.TYPE_NORMAL_BLENDING = 1;
GameLib.D3.Material.TYPE_ADDITIVE_BLENDING = 2;
GameLib.D3.Material.TYPE_SUBTRACTIVE_BLENDING = 3;
GameLib.D3.Material.TYPE_MULTIPLY_BLENDING = 4;
GameLib.D3.Material.TYPE_CUSTOM_BLENDING = 5;
/**
* Blend Source and Destination
* @type {number}
*/
GameLib.D3.Material.TYPE_ZERO_FACTOR = 200;
GameLib.D3.Material.TYPE_ONE_FACTOR = 201;
GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR = 202;
GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR = 203;
GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR = 204;
GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR = 205;
GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR = 206;
GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR = 207;
GameLib.D3.Material.TYPE_DST_COLOR_FACTOR = 208;
GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR = 209;
GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR = 210;
/**
* Blend Operation
* @type {number}
*/
GameLib.D3.Material.TYPE_ADD_EQUATION = 100;
GameLib.D3.Material.TYPE_SUBTRACT_EQUATION = 101;
GameLib.D3.Material.TYPE_REVERSE_SUBTRACT_EQUATION = 102;
GameLib.D3.Material.TYPE_MIN_EQUATION = 103;
GameLib.D3.Material.TYPE_MAX_EQUATION = 104;
/**
* Depth Function
* @type {number}
*/
GameLib.D3.Material.TYPE_NEVER_DEPTH = 0;
GameLib.D3.Material.TYPE_ALWAYS_DEPTH = 1;
GameLib.D3.Material.TYPE_LESS_DEPTH = 2;
GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH = 3;
GameLib.D3.Material.TYPE_EQUAL_DEPTH = 4;
GameLib.D3.Material.TYPE_GREATER_EQUAL_DEPTH = 5;
GameLib.D3.Material.TYPE_GREATER_DEPTH = 6;
GameLib.D3.Material.TYPE_NOT_EQUAL_DEPTH = 7;
/**
* Culling Mode
* @type {number}
*/
GameLib.D3.Material.TYPE_FRONT_SIDE = 0;
GameLib.D3.Material.TYPE_BACK_SIDE = 1;
GameLib.D3.Material.TYPE_DOUBLE_SIDE = 2;
/**
* Shading Type
* @type {number}
*/
GameLib.D3.Material.TYPE_FLAT_SHADING = 1;
GameLib.D3.Material.TYPE_SMOOTH_SHADING = 2;
/**
* Material Type
* @type {string}
*/
GameLib.D3.Material.TYPE_LINE_BASIC = "LineBasicMaterial";
GameLib.D3.Material.TYPE_LINE_DASHED = "LineDashedMaterial";
GameLib.D3.Material.TYPE_MESH_BASIC = "MeshBasicMaterial";
GameLib.D3.Material.TYPE_MESH_DEPTH = "MeshDepthMaterial";
GameLib.D3.Material.TYPE_MESH_LAMBERT = "MeshLambertMaterial";
GameLib.D3.Material.TYPE_MESH_NORMAL = "MeshNormalMaterial";
GameLib.D3.Material.TYPE_MESH_PHONG = "MeshPhongMaterial";
GameLib.D3.Material.TYPE_MESH_STANDARD = "MeshStandardMaterial";
GameLib.D3.Material.TYPE_POINTS = "PointsMaterial";
GameLib.D3.Material.TYPE_SPRITE = "SpriteMaterial";
GameLib.D3.Material.TYPE_MULTI_MATERIAL= "MultiMaterial";
/**
* Skeleton Superset
* @param id
* @param bones GameLib.D3.Bone
* @param boneInverses
* @param useVertexTexture
* @param boneTextureWidth
* @param boneTextureHeight
* @param boneMatrices
* @param boneTexture
* @constructor
*/
GameLib.D3.Skeleton = function(
id,
bones,
boneInverses,
useVertexTexture,
boneTextureWidth,
boneTextureHeight,
boneMatrices,
boneTexture
) {
this.id = id;
this.bones = bones;
/**
* An array of Matrix4s that represent the inverse of the matrixWorld of the individual bones.
* @type GameLib.D3.Matrix4[]
*/
if (typeof boneInverses == 'undefined') {
boneInverses = [];
}
this.boneInverses = boneInverses;
/**
* Use a vertex texture in the shader - allows for more than 4 bones per vertex, not supported by all devices
* @type {boolean}
*/
if (typeof useVertexTexture == 'undefined') {
useVertexTexture = false;
}
this.useVertexTexture = useVertexTexture;
if (this.useVertexTexture == true) {
console.warn('support for vertex texture bones is not supported yet - something could break somewhere');
}
if (typeof boneTextureWidth == 'undefined') {
boneTextureWidth = 0;
}
this.boneTextureWidth = boneTextureWidth;
if (typeof boneTextureHeight == 'undefined') {
boneTextureHeight = 0;
}
this.boneTextureHeight = boneTextureHeight;
if (typeof boneMatrices == 'undefined') {
boneMatrices = [];
}
this.boneMatrices = boneMatrices;
if (typeof boneTexture == 'undefined') {
boneTexture = [];
}
this.boneTexture = boneTexture;
};
/**
* Mesh Superset
* @param id
* @param path
* @param name
* @param meshType
* @param vertices
* @param faces
* @param skeleton
* @param faceVertexUvs
* @param skinIndices
* @param skinWeights
* @param materials
* @param position
* @param quaternion
* @param rotation
* @param scale
* @param up
* @param physics
* @param parentMeshId
* @param parentSceneId
* @param rawData
* @constructor
*/
GameLib.D3.Mesh = function(
id,
path,
name,
meshType,
vertices,
faces,
skeleton,
faceVertexUvs,
skinIndices,
skinWeights,
materials,
position,
quaternion,
rotation,
scale,
up,
physics,
parentMeshId,
parentSceneId,
rawData
) {
this.id = id;
this.path = path;
this.name = name;
this.meshType = meshType;
this.vertices = vertices;
this.faces = faces;
if (typeof skeleton == 'undefined') {
skeleton = null;
}
this.skeleton = skeleton;
if (typeof faceVertexUvs == 'undefined') {
faceVertexUvs = [];
}
this.faceVertexUvs = faceVertexUvs;
if (typeof skinIndices == 'undefined') {
skinIndices = [];
}
this.skinIndices = skinIndices;
if (typeof skinWeights == 'undefined') {
skinWeights = [];
}
this.skinWeights = skinWeights;
if (typeof materials == 'undefined') {
materials = [];
}
this.materials = materials;
if (typeof position == 'undefined') {
position = new GameLib.D3.Vector3(0,0,0);
}
this.position = position;
if (typeof quaternion == 'undefined') {
new GameLib.D3.Vector4();
}
this.quaternion = quaternion;
if (typeof rotation == 'undefined') {
rotation = new GameLib.D3.Vector3(0,0,0);
}
this.rotation = rotation;
if (typeof scale == 'undefined') {
scale = new GameLib.D3.Vector3(1,1,1);
}
this.scale = scale;
if (typeof up == 'undefined') {
up = new GameLib.D3.Vector3(0,1,0);
}
this.up = up;
this.physics = physics;
this.parentMeshId = parentMeshId;
this.parentSceneId = parentSceneId;
this.rawData = null;// rawData;
};
/**
* Mesh Type
* @type {number}
*/
GameLib.D3.Mesh.TYPE_NORMAL = 0;
GameLib.D3.Mesh.TYPE_SKINNED = 1;
/**
* Bone Superset
* @param id
* @param name string
* @param boneId
* @param childBoneIds
* @param parentBoneId
* @param quaternion
* @param position
* @param rotation
* @param scale GameLib.D3.Vector3
* @param up
* @param rawData
* @constructor
*/
GameLib.D3.Bone = function(
id,
boneId,
name,
childBoneIds,
parentBoneId,
quaternion,
position,
rotation,
scale,
up,
rawData
) {
this.id = id;
this.name = name;
this.boneId = boneId;
if (typeof childBoneIds == 'undefined') {
childBoneIds = [];
}
this.childBoneIds = childBoneIds;
if (typeof parentBoneId == 'undefined') {
parentBoneId = null;
}
this.parentBoneId = parentBoneId;
if (typeof quaternion == 'undefined') {
quaternion = new GameLib.D3.Vector4();
}
this.quaternion = quaternion;
if (typeof position == 'undefined') {
position = new GameLib.D3.Vector3(0,0,0);
}
this.position = position;
if (typeof rotation == 'undefined') {
rotation = new GameLib.D3.Vector3(0,0,0);
}
this.rotation = rotation;
if (typeof scale == 'undefined') {
scale = new GameLib.D3.Vector3(1,1,1);
}
this.scale = scale;
if (typeof up == 'undefined') {
up = new GameLib.D3.Vector3(0,1,0);
}
this.up = up;
this.rawData = null;//rawData;
};
GameLib.D3.Physics = function() {};
/**
* Physics Engine Superset
* @param id
* @param name
* @param engineType
* @param engine
* @constructor
*/
GameLib.D3.Physics.Engine = function(
id,
name,
engineType,
engine
) {
this.id = id;
this.name = name;
this.engineType = engineType;
this.engine = engine;
};
/**
* Physics Engine Types
* @type {number}
*/
GameLib.D3.Physics.Engine.TYPE_CANNON = 0x1;
GameLib.D3.Physics.Engine.TYPE_AMMO = 0x2;
GameLib.D3.Physics.Engine.TYPE_GOBLIN = 0x3;
/**
* Physics World Superset
* @param id
* @param name
* @param gravity
* @param rigidBodies GameLib.D3.Physics.RigidBody[]
* @param engine GameLib.D3.Physics.Engine
* @constructor
*/
GameLib.D3.Physics.World = function(
id,
name,
engine,
gravity,
rigidBodies
) {
this.id = id;
this.name = name;
this.engine = engine;
if (typeof gravity == 'undefined'){
gravity = 9.8;
}
this.gravity = gravity;
if (typeof rigidBodies == 'undefined'){
rigidBodies = [];
}
this.rigidBodies = rigidBodies;
};
/**
* Physics Rigid Body Superset
* @param id
* @param name
* @param position
* @param rotation
* @param scale
* @param shapes GameLib.D3.Physics.Shape[]
* @constructor
*/
GameLib.D3.Physics.RigidBody = function(
id,
name,
position,
rotation,
scale,
shapes
) {
this.position = new this.Vector3(0,0,0);
};
/**
* Physics Rigid Body Vehicle Superset
* @constructor
*/
GameLib.D3.Physics.RigidBody.Vehicle = function() {
};
/**
* Physics Shape Superset
* @constructor
*/
GameLib.D3.Physics.Shape = function() {};
/**
* Physics Convex Hull Shape Superset
* @param id
* @param name
* @constructor
*/
GameLib.D3.Physics.Shape.ConvexHull = function(
id,
name
) {
this.id = id;
this.name = name;
};
/**
* Physics Triangle Mesh Shape Superset
* @param id
* @param name
* @constructor
*/
GameLib.D3.Physics.Shape.TriangleMesh = function(
id,
name
) {
this.id = id;
this.name = name;
};
/**
* TriangleFace
* @param v0
* @param v1
* @param v2
* @param materialIndex
* @param v0uv
* @param v1uv
* @param v2uv
* @param color
* @param vertexColors
* @param vertexNormals
* @param normal
* @constructor
*/
GameLib.D3.TriangleFace = function(
v0,
v1,
v2,
materialIndex,
v0uv,
v1uv,
v2uv,
color,
vertexColors,
vertexNormals,
normal
) {
this.v0 = v0;
this.v1 = v1;
this.v2 = v2;
this.materialIndex = materialIndex;
this.v0uv = v0uv;
this.v1uv = v1uv;
this.v2uv = v2uv;
if (!color) {
color = new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff);
}
this.color = color;
if (!vertexColors) {
vertexColors = [
new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff),
new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff),
new GameLib.D3.Color(0xff, 0xff, 0xff, 0xff)
];
}
this.vertexColors = vertexColors;
if (!vertexNormals) {
vertexNormals = [
new GameLib.D3.Vector3(),
new GameLib.D3.Vector3(),
new GameLib.D3.Vector3()
]
}
this.vertexNormals = vertexNormals;
if (!normal) {
normal = new GameLib.D3.Vector3(0);
}
this.normal = normal;
};
/**
* TriangleEdge
* @param triangle
* @param edge
* @constructor
*/
GameLib.D3.TriangleEdge = function(
triangle,
edge
) {
this.triangle = triangle;
this.edge = edge;
};
/**
* Contains a Poly vertex data structure
* @param localIndex
* @param mvertIndex
* @param uv GameLib.D3.Vector2
* @param materialIndex
* @param edgeIndex
* @constructor
*/
GameLib.D3.PolyVertex = function(
localIndex,
mvertIndex,
uv,
materialIndex,
edgeIndex
) {
this.localIndex = localIndex;
this.mvertIndex = mvertIndex;
this.uv = uv;
this.materialIndex = materialIndex;
this.edgeIndex = edgeIndex;
};
/**
* BoneWeight object - associates a vertex to a bone with some weight
* @param boneIndex int
* @param weight float
* @constructor
*/
GameLib.D3.BoneWeight = function(
boneIndex,
weight
) {
this.boneIndex = boneIndex;
this.weight = weight;
};
/**
* The normal gets assigned when the face calculates its normal
* @param position
* @param boneWeights GameLib.D3.BoneWeight[]
* @constructor
*/
GameLib.D3.Vertex = function(
position,
boneWeights
) {
this.position = position;
this.boneWeights = boneWeights;
};
/**
* Image
* @param id
* @param textureLink
* @param filename
* @param uploadPath
* @param apiPath
* @param size
* @param contentType
* @constructor
*/
GameLib.D3.Image = function(
id,
textureLink,
filename,
uploadPath,
apiPath,
size,
contentType
) {
this.id = id;
this.filename = filename;
this.textureLink = textureLink;
if (typeof uploadPath == 'undefined') {
uploadPath = null;
}
this.uploadPath = uploadPath;
if (typeof apiPath == 'undefined') {
apiPath = null;
}
this.apiPath = apiPath;
if (typeof size == 'undefined') {
size = 0;
}
this.size = size;
if (typeof contentType == 'undefined') {
contentType = 'application/octet-stream';
if (this.filename.match(/(png)$/i)) {
contentType = 'image/png';
}
if (this.filename.match(/(jpg|jpeg)$/i)) {
contentType = 'image/jpeg';
}
if (this.filename.match(/(gif)$/i)) {
contentType = 'image/gif';
}
}
this.contentType = contentType;
};
/**
* Scenes are objects putting meshes into 'world space'
* @param id
* @param path String
* @param name String
* @param meshes GameLib.D3.Mesh[]
* @param quaternion
* @param position
* @param rotation
* @param scale
* @param parentSceneId
* @param lights
* @constructor
*/
GameLib.D3.Scene = function(
id,
path,
name,
meshes,
quaternion,
position,
rotation,
scale,
parentSceneId,
lights
) {
this.id = id;
this.path = path;
this.name = name;
if (this.name.trim() == "") {
this.name = 'unnamed';
}
this.meshes = meshes;
if (typeof quaternion == 'undefined') {
quaternion = new GameLib.D3.Vector4();
}
this.quaternion = quaternion;
if (typeof position == 'undefined') {
position = new GameLib.D3.Vector3(0,0,0);
}
this.position = position;
if (typeof rotation == 'undefined') {
rotation = new GameLib.D3.Vector3(0,0,0);
}
this.rotation = rotation;
if (typeof scale == 'undefined') {
scale = new GameLib.D3.Vector3(1,1,1);
}
this.scale = scale;
if (typeof parentSceneId == 'undefined') {
parentSceneId = null;
}
this.parentSceneId = parentSceneId;
if (typeof lights == 'undefined') {
lights = [];
}
this.lights = lights;
};
/**
* Clone a PolyVertex
* @returns {GameLib.D3.PolyVertex}
*/
GameLib.D3.PolyVertex.prototype.clone = function() {
return new GameLib.D3.PolyVertex(
this.localIndex,
this.mvertIndex,
this.uv.copy(),
this.materialIndex,
this.edgeIndex
)
};
/**
* Clone a TriangleFace
* @returns {GameLib.D3.TriangleFace}
*/
GameLib.D3.TriangleFace.prototype.clone = function(){
return new GameLib.D3.TriangleFace(
this.v0,
this.v1,
this.v2,
this.materialIndex,
this.v0uv.copy(),
this.v1uv.copy(),
this.v2uv.copy()
);
};
/**
* Associates bones with their child bones, based on parent bone references
*/
GameLib.D3.prototype.createChildBoneIds = function() {
for (var bi = 0; bi < this.bones.length; bi++) {
var childBoneIds = [];
for (var sbi = 0; sbi < this.bones.length; sbi++) {
if (this.bones[sbi] == this.bones[bi]) {
continue;
}
if (this.bones[sbi].parentBoneId !== null &&
this.bones[sbi].parentBoneId == this.bones[bi].boneId)
{
childBoneIds.push(this.bones[sbi].boneId);
}
}
this.bones[bi].childBoneIds = childBoneIds;
}
};
/**
* This is a work-around function to fix polys which don't triangulate because
* they could lie on Z-plane (XZ or YZ)) - we translate the poly to the origin, systematically rotate the poly around
* Z then Y axis
* @param verticesFlat []
* @param grain is the amount to systematically rotate the poly by - a finer grain means a more accurate maximum XY
* @return []
*/
GameLib.D3.prototype.fixPolyZPlane = function(verticesFlat, grain) {
if ((verticesFlat.length % 3) != 0 && !(verticesFlat.length > 9)) {
console.log("The vertices are not in the right length : " + verticesFlat.length);
}
var vertices = [];
var points = new GameLib.D3.Vector4.Points();
for (var i = 0; i < verticesFlat.length; i += 3) {
points.add(new GameLib.D3.Vector3(
verticesFlat[i],
verticesFlat[i + 1],
verticesFlat[i + 2]
));
}
points.toOrigin();
points.maximizeXDistance(grain);
points.maximizeYDistance(grain);
for (i = 0; i < points.vectors.length; i++) {
vertices.push(
[
points.vectors[i].x,
points.vectors[i].y
]
);
}
return vertices;
};
/**
* This function resets the winding order for triangles in faces, given an initial triangle and orientation edge
* used pseudocode from
* http://stackoverflow.com/questions/17036970/how-to-correct-winding-of-triangles-to-counter-clockwise-direction-of-a-3d-mesh
* We need to use a graph traversal algorithm,
* lets assume we have method that returns neighbor of triangle on given edge
*
* neighbor_on_egde( next_tria, edge )
*
* to_process = set of pairs triangle and orientation edge, initial state is one good oriented triangle with any edge on it
* processed = set of processed triangles; initial empty
*
* while to_process is not empty:
* next_tria, orientation_edge = to_process.pop()
* add next_tria in processed
* if next_tria is not opposite oriented than orientation_edge:
* change next_tria (ABC) orientation (B<->C)
* for each edge (AB) in next_tria:
* neighbor_tria = neighbor_on_egde( next_tria, edge )
* if neighbor_tria exists and neighbor_tria not in processed:
* to_process add (neighbor_tria, edge opposite oriented (BA))
* @param faces GameLib.D3.TriangleFace[]
* @param orientationEdge GameLib.D3.Vector2
* @returns {Array}
*/
GameLib.D3.prototype.fixWindingOrder = function(faces, orientationEdge) {
/**
* Checks if a TriangleFace belonging to a TriangleEdge has already been processed
* @param processed TriangleEdge[]
* @param triangle TriangleFace
* @returns {boolean}
*/
function inProcessed(processed, triangle) {
for (var i = 0; i < processed.length; i++) {
if (processed[i].triangle.equals(triangle)) {
return true;
}
}
return false;
}
/**
* Returns a neighbouring triangle on a specific edge - preserving the edge orientation
* @param edge GameLib.D3.Vector2
* @param faces GameLib.D3.TriangleFace[]
* @param currentTriangle
* @returns {*}
*/
function neighbourOnEdge(edge, faces, currentTriangle) {
for (var i = 0; i < faces.length; i++) {
if (
(faces[i].v0 == edge.x && faces[i].v1 == edge.y) ||
(faces[i].v1 == edge.x && faces[i].v2 == edge.y) ||
(faces[i].v2 == edge.x && faces[i].v0 == edge.y) ||
(faces[i].v0 == edge.y && faces[i].v1 == edge.x) ||
(faces[i].v1 == edge.y && faces[i].v2 == edge.x) ||
(faces[i].v2 == edge.y && faces[i].v0 == edge.x)
) {
var triangle = new GameLib.D3.TriangleFace(
faces[i].v0,
faces[i].v1,
faces[i].v2,
faces[i].materialIndex,
faces[i].v0uv,
faces[i].v1uv,
faces[i].v2uv
);
if (triangle.equals(currentTriangle)) {
continue;
}
return new GameLib.D3.TriangleEdge(
triangle,
edge
);
}
}
return null;
}
var toProcess = [
new GameLib.D3.TriangleEdge(
new GameLib.D3.TriangleFace(
faces[0].v0,
faces[0].v1,
faces[0].v2,
faces[0].materialIndex,
faces[0].v0uv,
faces[0].v1uv,
faces[0].v2uv
),
orientationEdge
)
];
var processed = [];
while (toProcess.length > 0) {
var triangleEdge = toProcess.pop();
/**
* If edge is the same orientation (i.e. the edge order is the same as the given triangle edge) it needs to be reversed
* to have the same winding order)
*/
if (
(triangleEdge.triangle.v0 == triangleEdge.edge.x &&
triangleEdge.triangle.v1 == triangleEdge.edge.y) ||
(triangleEdge.triangle.v1 == triangleEdge.edge.x &&
triangleEdge.triangle.v2 == triangleEdge.edge.y) ||
(triangleEdge.triangle.v2 == triangleEdge.edge.x &&
triangleEdge.triangle.v0 == triangleEdge.edge.y)
) {
var backupV = triangleEdge.triangle.v1;
triangleEdge.triangle.v1 = triangleEdge.triangle.v2;
triangleEdge.triangle.v2 = backupV;
var backupUV = triangleEdge.triangle.v1uv;
triangleEdge.triangle.v1uv = triangleEdge.triangle.v2uv;
triangleEdge.triangle.v2uv = backupUV;
}
processed.push(triangleEdge);
var edges = [
new GameLib.D3.Vector2(
triangleEdge.triangle.v0,
triangleEdge.triangle.v1
),
new GameLib.D3.Vector2(
triangleEdge.triangle.v1,
triangleEdge.triangle.v2
),
new GameLib.D3.Vector2(
triangleEdge.triangle.v2,
triangleEdge.triangle.v0
)
];
for (var j = 0; j < edges.length; j++) {
var neighbour = neighbourOnEdge(edges[j], faces, triangleEdge.triangle);
if (neighbour && !inProcessed(processed, neighbour.triangle)) {
toProcess.push(neighbour);
}
}
}
/**
* In processed - we will have some duplicates - only add the unique ones
* @type {Array}
*/
var triangles = [];
for (var i = 0; i < processed.length; i++) {
var found = false;
for (var k = 0; k < triangles.length; k++) {
if (triangles[k].equals(processed[i].triangle)){
found = true;
break;
}
}
if (!found) {
triangles.push(processed[i].triangle);
}
}
return triangles;
};
/**
* Returns true if two triangles are equal (their vertex indices match in some order)
* @param triangle
* @returns {boolean}
*/
GameLib.D3.TriangleFace.prototype.equals = function(triangle) {
return !!(
(
(this.v0 == triangle.v0) &&
(this.v1 == triangle.v1) &&
(this.v2 == triangle.v2)
)
||
(
(this.v0 == triangle.v0) &&
(this.v1 == triangle.v2) &&
(this.v2 == triangle.v1)
)
||
(
(this.v0 == triangle.v1) &&
(this.v1 == triangle.v0) &&
(this.v2 == triangle.v2)
)
||
(
(this.v0 == triangle.v1) &&
(this.v1 == triangle.v2) &&
(this.v2 == triangle.v0)
)
||
(
(this.v0 == triangle.v2) &&
(this.v1 == triangle.v0) &&
(this.v2 == triangle.v1)
)
||
(
(this.v0 == triangle.v2) &&
(this.v1 == triangle.v1) &&
(this.v2 == triangle.v0)
));
};
GameLib.D3.prototype.invertWindingOrder = function(triangles) {
for (var i = 0; i < triangles.length; i++) {
var v1 = triangles[i].v1;
triangles[i].v1 = triangles[i].v2;
triangles[i].v2 = v1;
var backupUV = triangles[i].triangle.v1uv;
triangles[i].triangle.v1uv = triangles[i].triangle.v2uv;
triangles[i].triangle.v2uv = backupUV;
}
return triangles;
};
/**
* This function resets a the winding order of a mesh from a reference point V (the average center of the mesh)
*/
GameLib.D3.prototype.resetWindingOrder = function(faces, vertices) {
var vertexList = new GameLib.D3.Vector3.Points();
for (var v = 0; v < vertices.length; v++) {
vertexList.add(new GameLib.D3.Vector3(
vertices[v].position.x,
vertices[v].position.y,
vertices[v].position.z
));
}
var V = vertexList.average();
var triangles = [];
for (var s = 0; s < faces.length; s += 3) {
var v0 = faces[s];
var v1 = faces[s+1];
var v2 = faces[s+2];
triangles.push(
{
v0 : v0,
v1 : v1,
v2 : v2,
edges : [
{v0: v0, v1: v1},
{v0: v1, v1: v2},
{v0: v2, v1: v0}
],
winding : 0,
edgeIndex : -1,
processed : false
}
);
}
for (var i = 0; i < triangles.length; i++) {
if (
GameLib.D3.Vector3.clockwise(
vertices[triangles[i].v0].position,
vertices[triangles[i].v1].position,
vertices[triangles[i].v2].position,
V
)
) {
console.log('clockwise');
var bv1 = triangles[i].v1;
triangles[i].v1 = triangles[i].v2;
triangles[i].v2 = bv1;
} else {
console.log('not clockwise');
}
}
return triangles;
};
/**
* Defers loading of an image and resolves once image is loaded
* @param gameLibTexture
* @param threeMaterial
* @param threeMaterialMapType
* @returns {Promise}
*/
GameLib.D3.prototype.loadMap = function(gameLibTexture, threeMaterial, threeMaterialMapType) {
var q = this.Q.defer();
var imagePath = null;
if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.apiPath && gameLibTexture.image.filename) {
/**
* Load the image from API here if apiPath is defined
*/
imagePath = this.apiUrl + gameLibTexture.image.uploadPath + '/' + gameLibTexture.image.filename;
}
if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.uploadPath && gameLibTexture.image.filename) {
/**
* Else, load from upload source
*/
imagePath = this.editorUrl + gameLibTexture.image.uploadPath + '/' + gameLibTexture.image.filename;
}
if (imagePath) {
this.textureLoader.crossOrigin = '';
this.textureLoader.load(
imagePath,
function(texture) {
/**
* onLoad
*/
threeMaterial[threeMaterialMapType] = texture;
threeMaterial[threeMaterialMapType].name = gameLibTexture.name;
threeMaterial[threeMaterialMapType].anisotropy = gameLibTexture.anisotropy;
threeMaterial[threeMaterialMapType].encoding = gameLibTexture.encoding;
threeMaterial[threeMaterialMapType].flipY = gameLibTexture.flipY;
/**
* We don't restore the format since this changing from OS to OS and breaks the implementation sometimes
*/
threeMaterial[threeMaterialMapType].generateMipmaps = gameLibTexture.generateMipmaps;
threeMaterial[threeMaterialMapType].magFilter = gameLibTexture.magFilter;
threeMaterial[threeMaterialMapType].minFilter = gameLibTexture.minFilter;
threeMaterial[threeMaterialMapType].mapping = gameLibTexture.mapping;
threeMaterial[threeMaterialMapType].mipmaps = gameLibTexture.mipmaps;
threeMaterial[threeMaterialMapType].offset = new this.THREE.Vector2(
gameLibTexture.offset.x,
gameLibTexture.offset.y
);
threeMaterial[threeMaterialMapType].premultiplyAlpha = gameLibTexture.premultiplyAlpha;
threeMaterial[threeMaterialMapType].textureType = gameLibTexture.textureType;
threeMaterial[threeMaterialMapType].wrapS = gameLibTexture.wrapS;
threeMaterial[threeMaterialMapType].wrapT = gameLibTexture.wrapT;
threeMaterial[threeMaterialMapType].unpackAlignment = gameLibTexture.unpackAlignment;
threeMaterial.needsUpdate = true;
q.resolve(true);
},
function(xhr) {
/**
* onProgress
*/
if (this.editor) {
this.editor.setServerStatus(Math.round(xhr.loaded / xhr.total * 100) + '% complete', 'success');
}
},
function(error) {
/**
* onError
*/
console.log("an error occurred while trying to load the image : " + imagePath);
q.resolve(null);
}
);
} else {
q.resolve(null);
}
return q.promise;
};
/**
* Creates a THREE Mesh from GameLib.D3.Mesh
* @param gameLibMesh
* @param threeGeometry
* @param threeMaterial
* @returns {*}
*/
GameLib.D3.prototype.createThreeMesh = function(gameLibMesh, threeGeometry, threeMaterial) {
var threeMesh = null;
if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_NORMAL) {
threeMesh = new this.THREE.Mesh(threeGeometry, threeMaterial);
}
if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_SKINNED) {
var bones = gameLibMesh.skeleton.bones;
var skinIndices = gameLibMesh.skinIndices;
var skinWeights = gameLibMesh.skinWeights;
var threeBones = [];
for (var bi = 0; bi < bones.length; bi++) {
var bone = new this.THREE.Bone();
bone.name = bones[bi].name;
bone.position.x = bones[bi].position.x;
bone.position.y = bones[bi].position.y;
bone.position.z = bones[bi].position.z;
bone.rotation.x = bones[bi].rotation.x;
bone.rotation.y = bones[bi].rotation.y;
bone.rotation.z = bones[bi].rotation.z;
bone.quaternion.x = bones[bi].quaternion.x;
bone.quaternion.y = bones[bi].quaternion.y;
bone.quaternion.z = bones[bi].quaternion.z;
bone.quaternion.w = bones[bi].quaternion.w;
bone.scale.x = bones[bi].scale.x;
bone.scale.y = bones[bi].scale.y;
bone.scale.z = bones[bi].scale.z;
bone.up.x = bones[bi].up.x;
bone.up.y = bones[bi].up.y;
bone.up.z = bones[bi].up.z;
threeBones.push(bone);
}
/**
* Setup the bone relationships
*/
for (var br = 0; br < bones.length; br++) {
for (var cbi = 0; cbi < bones[br].childBoneIds.length; cbi++) {
threeBones[br].add(threeBones[bones[br].childBoneIds[cbi]]);
}
}
/**
* Setup bones (indexes)
*/
for (var si = 0; si < skinIndices.length; si++) {
threeGeometry.skinIndices.push(
new this.THREE.Vector4(
skinIndices[si].x,
skinIndices[si].y,
skinIndices[si].z,
skinIndices[si].w
)
);
}
/**
* Setup bones (weights)
*/
for (var sw = 0; sw < skinWeights.length; sw++) {
threeGeometry.skinWeights.push(
new this.THREE.Vector4(
skinWeights[sw].x,
skinWeights[sw].y,
skinWeights[sw].z,
skinWeights[sw].w
)
);
}
threeMesh = new this.THREE.SkinnedMesh(threeGeometry, threeMaterial);
var skeleton = new this.THREE.Skeleton(threeBones);
skeleton.useVertexTexture = gameLibMesh.skeleton.useVertexTexture;
for (var i = 0; i < bones.length; i++) {
if (bones[i].parentBoneId === null) {
threeMesh.add(threeBones[i]);
break;
}
}
threeMesh.bind(skeleton);
threeMesh.pose();
threeMesh.skeleton.skeletonHelper = new this.THREE.SkeletonHelper(threeMesh);
threeMesh.skeleton.skeletonHelper.material.linewidth = 5;
}
if (threeMesh == null) {
console.log('cannot handle meshes of type ' + gameLibMesh.meshType + ' yet.');
}
gameLibMesh.threeMeshId = threeMesh.id;
return threeMesh;
};
/**
* Returns an array of image loading Promises
* @param blenderMaterial
* @param blenderMaps
* @param threeMaterial
* @returns Q[]
*/
GameLib.D3.prototype.loadMaps = function(blenderMaterial, blenderMaps, threeMaterial) {
var textureMaps = [];
for (var ti = 0; ti < blenderMaps.length; ti++) {
var map = blenderMaps[ti];
if (blenderMaterial.maps.hasOwnProperty(map)) {
var blenderTexture = blenderMaterial.maps[map];
if (
blenderTexture &&
blenderTexture.image &&
blenderTexture.image.filename &&
blenderTexture.image.uploadPath
) {
var threeMap = null;
if (map == 'alpha') {
threeMap = 'alhpaMap';
}
if (map == 'ao') {
threeMap = 'aoMap';
}
if (map == 'bump') {
threeMap = 'bumpMap';
}
if (map == 'displacement') {
threeMap = 'displacementMap';
}
if (map == 'emissive') {
threeMap = 'emissiveMap';
}
if (map == 'environment') {
threeMap = 'envMap';
}
if (map == 'light') {
threeMap = 'lightMap';
}
if (map == 'specular') {
threeMap = 'specularMap';
}
if (map == 'diffuse') {
threeMap = 'map';
}
if (map == 'roughness') {
threeMap = 'roughnessMap';
}
if (map == 'metalness') {
threeMap = 'metalnessMap';
}
if (threeMap == null) {
console.warn("unsupported map type : " + map);
}
textureMaps.push(this.loadMap(blenderMaterial.maps[map], threeMaterial, threeMap));
}
}
}
return textureMaps;
};
/**
* Creates a this.THREE.Material from a GameLib.D3.Material
* @param blenderMaterial GameLib.D3.Material
*/
GameLib.D3.prototype.createThreeMaterial = function(blenderMaterial) {
var defer = this.Q.defer();
var threeMaterial = null;
var blenderMaps = [];
if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_STANDARD) {
threeMaterial = new this.THREE.MeshStandardMaterial({
name: blenderMaterial.name,
opacity: blenderMaterial.opacity,
transparent: blenderMaterial.transparent,
blending: blenderMaterial.blending,
blendSrc: blenderMaterial.blendSrc,
blendDst: blenderMaterial.blendDst,
blendEquation: blenderMaterial.blendEquation,
depthTest: blenderMaterial.depthTest,
depthFunc: blenderMaterial.depthFunc,
depthWrite: blenderMaterial.depthWrite,
polygonOffset: blenderMaterial.polygonOffset,
polygonOffsetFactor: blenderMaterial.polygonOffsetFactor,
polygonOffsetUnits: blenderMaterial.polygonOffsetUnits,
alphaTest: blenderMaterial.alphaTest,
clippingPlanes: blenderMaterial.clippingPlanes,
clipShadows: blenderMaterial.clipShadows,
overdraw: blenderMaterial.overdraw,
visible: blenderMaterial.visible,
side: blenderMaterial.side,
color: new this.THREE.Color(
blenderMaterial.color.r,
blenderMaterial.color.g,
blenderMaterial.color.b
),
roughness: blenderMaterial.roughness,
metalness: blenderMaterial.metalness,
lightMapIntensity: blenderMaterial.lightMapIntensity,
aoMapIntensity: blenderMaterial.aoMapIntensity,
emissive: new this.THREE.Color(
blenderMaterial.emissive.r,
blenderMaterial.emissive.g,
blenderMaterial.emissive.b
),
emissiveIntensity: blenderMaterial.emissiveIntensity,
bumpScale: blenderMaterial.bumpScale,
normalScale: blenderMaterial.normalScale,
displacementScale: blenderMaterial.displacementScale,
refractionRatio: blenderMaterial.refractionRatio,
fog: blenderMaterial.fog,
shading: blenderMaterial.shading,
wireframe: blenderMaterial.wireframe,
wireframeLinewidth: blenderMaterial.wireframeLineWidth,
wireframeLinecap: blenderMaterial.wireframeLineCap,
wireframeLinejoin: blenderMaterial.wireframeLineJoin,
vertexColors: blenderMaterial.vertexColors,
skinning: blenderMaterial.skinning,
morphTargets: blenderMaterial.morphTargets,
morphNormals: blenderMaterial.morphNormals
});
blenderMaps.push(
'diffuse',
'light',
'ao',
'emissive',
'bump',
'normal',
'displacement',
'roughness',
'metalness',
'alpha',
'environment'
);
} else if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_PHONG) {
threeMaterial = new this.THREE.MeshPhongMaterial({
name: blenderMaterial.name,
opacity: blenderMaterial.opacity,
transparent: blenderMaterial.transparent,
blending: blenderMaterial.blending,
blendSrc: blenderMaterial.blendSrc,
blendDst: blenderMaterial.blendDst,
blendEquation: blenderMaterial.blendEquation,
depthTest: blenderMaterial.depthTest,
depthFunc: blenderMaterial.depthFunc,
depthWrite: blenderMaterial.depthWrite,
polygonOffset: blenderMaterial.polygonOffset,
polygonOffsetFactor: blenderMaterial.polygonOffsetFactor,
polygonOffsetUnits: blenderMaterial.polygonOffsetUnits,
alphaTest: blenderMaterial.alphaTest,
clippingPlanes: blenderMaterial.clippingPlanes,
clipShadows: blenderMaterial.clipShadows,
overdraw: blenderMaterial.overdraw,
visible: blenderMaterial.visible,
side: blenderMaterial.side,
color: new this.THREE.Color(
blenderMaterial.color.r,
blenderMaterial.color.g,
blenderMaterial.color.b
),
specular: new this.THREE.Color(
blenderMaterial.specular.r,
blenderMaterial.specular.g,
blenderMaterial.specular.b
),
shininess: blenderMaterial.shininess,
lightMapIntensity: blenderMaterial.lightMapIntensity,
aoMapIntensity: blenderMaterial.aoMapIntensity,
emissive: new this.THREE.Color(
blenderMaterial.emissive.r,
blenderMaterial.emissive.g,
blenderMaterial.emissive.b
),
emissiveIntensity: blenderMaterial.emissiveIntensity,
bumpScale: blenderMaterial.bumpScale,
normalScale: blenderMaterial.normalScale,
displacementScale: blenderMaterial.displacementScale,
combine: blenderMaterial.combine,
refractionRatio: blenderMaterial.refractionRatio,
fog: blenderMaterial.fog,
shading: blenderMaterial.shading,
wireframe: blenderMaterial.wireframe,
wireframeLinewidth: blenderMaterial.wireframeLineWidth,
wireframeLinecap: blenderMaterial.wireframeLineCap,
wireframeLinejoin: blenderMaterial.wireframeLineJoin,
vertexColors: blenderMaterial.vertexColors,
skinning: blenderMaterial.skinning,
morphTargets: blenderMaterial.morphTargets,
morphNormals: blenderMaterial.morphNormals
});
blenderMaps.push(
'diffuse',
'light',
'ao',
'emissive',
'bump',
'normal',
'displacement',
'specular',
'alpha',
'environment'
);
} else {
console.log("material type is not implemented yet: " + blenderMaterial.materialType + " - material indexes could be screwed up");
}
if (blenderMaps.length > 0) {
var textureMaps = this.loadMaps(blenderMaterial, blenderMaps, threeMaterial);
Q.all(textureMaps).then(
function(){
defer.resolve(threeMaterial);
}
).catch(
function(error){
console.log(error);
defer.reject(error);
}
)
} else {
defer.resolve(threeMaterial);
}
return defer.promise;
};
/**
* Loads a scene directly from the API
* @param sceneName
* @param onLoaded callback
*/
GameLib.D3.prototype.loadSceneFromApi = function(sceneName, onLoaded) {
/**
* First check if this is a client or server side request
*/
if (typeof XMLHttpRequest == 'undefined') {
console.warn('implement server side loading from API here');
return onLoaded(null, new Error('not implemented'));
}
var xhr = new XMLHttpRequest();
xhr.open(
'GET',
this.apiUrl + '/scene/' + sceneName
);
xhr.onreadystatechange = function(xhr, gameLibD3) {
return function() {
if (xhr.readyState == 4) {
var response = JSON.parse(xhr.responseText);
gameLibD3.loadScene(response.scene[0], onLoaded, false);
}
}
}(xhr, this);
xhr.send();
};
/**
* Loads a GameLib.D3.Scene object into a ThreeJS Scene object
* @param gameLibScene GameLib.D3.Scene
* @param onLoaded callback when all meshes have loaded
* @param computeNormals set to true to compute new face and vertex normals during load
*/
GameLib.D3.prototype.loadScene = function(gameLibScene, onLoaded, computeNormals) {
console.log("loading scene " + gameLibScene.name);
var meshQ = [];
for (var m = 0; m < gameLibScene.meshes.length; m++) {
var mesh = gameLibScene.meshes[m];
console.log("loading mesh " + mesh.name);
var geometry = new this.THREE.Geometry();
var vertices = mesh.vertices;
var faces = mesh.faces;
var faceVertexUvs = mesh.faceVertexUvs;
var materials = mesh.materials;
/**
* Setup vertices
*/
for (var v = 0; v < vertices.length; v++) {
geometry.vertices.push(
new this.THREE.Vector3(
vertices[v].position.x,
vertices[v].position.y,
vertices[v].position.z
)
)
}
/**
* Setup faces
*/
for (var f = 0; f < faces.length; f++) {
var face = new this.THREE.Face3(
faces[f].v0,
faces[f].v1,
faces[f].v2,
new this.THREE.Vector3(
faces[f].normal.x,
faces[f].normal.y,
faces[f].normal.z
),
new this.THREE.Color(
faces[f].color.r,
faces[f].color.g,
faces[f].color.b
),
faces[f].materialIndex
);
face.vertexColors = [
new this.THREE.Color(
faces[f].vertexColors[0].r,
faces[f].vertexColors[0].g,
faces[f].vertexColors[0].b
),
new this.THREE.Color(
faces[f].vertexColors[1].r,
faces[f].vertexColors[1].g,
faces[f].vertexColors[1].b
),
new this.THREE.Color(
faces[f].vertexColors[2].r,
faces[f].vertexColors[2].g,
faces[f].vertexColors[2].b
)
];
face.normal = new this.THREE.Vector3(
faces[f].normal.x,
faces[f].normal.y,
faces[f].normal.z
);
face.vertexNormals = [
new this.THREE.Vector3(
faces[f].vertexNormals[0].x,
faces[f].vertexNormals[0].y,
faces[f].vertexNormals[0].z
),
new this.THREE.Vector3(
faces[f].vertexNormals[1].x,
faces[f].vertexNormals[1].y,
faces[f].vertexNormals[1].z
),
new this.THREE.Vector3(
faces[f].vertexNormals[2].x,
faces[f].vertexNormals[2].y,
faces[f].vertexNormals[2].z
)
];
geometry.faces.push(face);
}
geometry.faceVertexUvs = [];
/**
* Setup face UVs
*/
for (var fm = 0; fm < faceVertexUvs.length; fm++) {
var faceMaterialVertexUvs = faceVertexUvs[fm];
geometry.faceVertexUvs[fm] = [];
for (var fuv = 0; fuv < faceMaterialVertexUvs.length; fuv++) {
geometry.faceVertexUvs[fm][fuv] = [];
geometry.faceVertexUvs[fm][fuv].push(
new this.THREE.Vector2(
faceMaterialVertexUvs[fuv][0].x,
faceMaterialVertexUvs[fuv][0].y
),
new this.THREE.Vector2(
faceMaterialVertexUvs[fuv][1].x,
faceMaterialVertexUvs[fuv][1].y
),
new this.THREE.Vector2(
faceMaterialVertexUvs[fuv][2].x,
faceMaterialVertexUvs[fuv][2].y
)
);
}
}
/**
* Re-calculate normals (if we have to)
* @type {Array}
*/
if (computeNormals) {
geometry.computeFaceNormals();
geometry.computeVertexNormals();
}
var threeMaterialLoaders = [];
/**
* Setup materials
*/
for (var mi = 0; mi < materials.length; mi++) {
threeMaterialLoaders.push(this.createThreeMaterial(materials[mi]));
}
var result = this.Q.all(threeMaterialLoaders).then(
function(gl3d, mesh, geometry) {
return function(materials) {
console.log("loaded all materials maps (" + materials.length + ")");
/**
* We don't support MultiMaterial atm - it doesn't work with raycasting
*/
var material = materials[0];
var threeMesh = gl3d.createThreeMesh(mesh, geometry, material);
threeMesh.name = mesh.name;
threeMesh.position.x = mesh.position.x;
threeMesh.position.y = mesh.position.y;
threeMesh.position.z = mesh.position.z;
threeMesh.rotation.x = mesh.rotation.x;
threeMesh.rotation.y = mesh.rotation.y;
threeMesh.rotation.z = mesh.rotation.z;
threeMesh.scale.x = mesh.scale.x;
threeMesh.scale.y = mesh.scale.y;
threeMesh.scale.z = mesh.scale.z;
threeMesh.quaternion.x = mesh.quaternion.x;
threeMesh.quaternion.y = mesh.quaternion.y;
threeMesh.quaternion.z = mesh.quaternion.z;
threeMesh.quaternion.w = mesh.quaternion.w;
return threeMesh;
};
}(this, mesh, geometry)
).catch(function(error){
console.log(error);
});
meshQ.push(result);
}
this.Q.all(meshQ).then(function(threeMeshes){
console.log("all meshes have loaded");
if (typeof onLoaded != 'undefined') {
var threeLights = [];
for (var sli = 0; sli < gameLibScene.lights.length; sli++) {
var blenderLight = gameLibScene.lights[sli];
var light = null;
if (blenderLight.lightType == 'AmbientLight') {
light = new this.THREE.AmbientLight(blenderLight.color, blenderLight.intensity);
}
if (blenderLight.lightType == 'DirectionalLight') {
light = new this.THREE.DirectionalLight(blenderLight.color, blenderLight.intensity);
}
if (blenderLight.lightType == 'PointLight') {
light = new this.THREE.PointLight(blenderLight.color, blenderLight.intensity);
light.distance = blenderLight.distance;
light.decay = blenderLight.decay;
}
if (blenderLight.lightType == 'SpotLight') {
light = new this.THREE.SpotLight(blenderLight.color, blenderLight.intensity);
light.distance = blenderLight.distance;
light.angle = blenderLight.angle;
light.penumbra = blenderLight.penumbra;
light.decay = blenderLight.decay;
}
light.position.x = blenderLight.position.x;
light.position.y = blenderLight.position.y;
light.position.z = blenderLight.position.z;
light.rotation.x = blenderLight.rotation.x;
light.rotation.y = blenderLight.rotation.y;
light.rotation.z = blenderLight.rotation.z;
// light.scale.x = blenderLight.scale.x;
// light.scale.y = blenderLight.scale.y;
// light.scale.z = blenderLight.scale.z;
if (light == null) {
console.warn('Does not support lights of type :' + blenderLight.lightType + ', not imported');
} else {
light.name = blenderLight.name;
threeLights.push(light);
}
}
onLoaded(threeMeshes, threeLights);
}
}).catch(function(error){
console.log(error);
});
};
// ---------------
// Physics
// ---------------
GameLib.D3.Physics.World.GetIndexedVertices = function(
triangleMeshShape
) {
if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) {
return {
vertices : triangleMeshShape.vertices,
indices : triangleMeshShape.indices
};
} else {
// todo: implement this for other physics engines.
return null;
}
};
GameLib.D3.Physics.World.GenerateWireframeViewMesh = function(
triangleMeshShape,
normalLength,
scale,
opacity,
wireframeColor
) {
var geometryTHREE = new THREE.Geometry();
var wireframeTHREEMesh = new THREE.Mesh
(
geometryTHREE,
new THREE.MeshBasicMaterial({
color: wireframeColor ? wireframeColor : 0xfefefe,
wireframe: true,
opacity: opacity ? opacity : 0.5
})
);
var data = this.GetIndexedVertices(triangleMeshShape);
for(var i = 0, l = data.vertices.length / 3; i < l; i++) {
geometryTHREE.vertices.push(new THREE.Vector3(data.vertices[i * 3], data.vertices[i * 3 + 1], data.vertices[i * 3 + 2]));
}
for(var i = 0, l = data.indices.length / 3; i < l; i++) {
var i0 = data.indices[i * 3];
var i1 = data.indices[i * 3 + 1];
var i2 = data.indices[i * 3 + 2];
geometryTHREE.faces.push(new THREE.Face3(i0, i1, i2));
// Create debug view for normals
// Center point on the mesh itself
var centroid = new THREE.Vector3()
.add(geometryTHREE.vertices[i0])
.add(geometryTHREE.vertices[i1])
.add(geometryTHREE.vertices[i2])
.divideScalar(3);
var normal = null;
if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) {
var normal = new CANNON.Vec3();
triangleMeshShape.getNormal(i, normal);
} else {
// todo: calculate the normal for v0, v1 & v2 here.
}
var arrow = new THREE.ArrowHelper(new THREE.Vector3(normal.x, normal.y, normal.z), centroid, normalLength, new THREE.Color(normal.x, normal.y, normal.z));
wireframeTHREEMesh.add( arrow );
}
wireframeTHREEMesh.scale.x = scale.x;
wireframeTHREEMesh.scale.y = scale.y;
wireframeTHREEMesh.scale.z = scale.z;
return wireframeTHREEMesh;
};
GameLib.D3.Physics.World.GenerateTriangleCollisionMesh = function(
threeMesh,
mass, // default = 0
friction, // default = 10
createCollisionSubMeshes, // boolean. default = false
facesPerSubsection, // int. default = 0
subsectionsToMerge // int. default = 0
) {
var processedFaces = 0;
var facesPerSubSection = facesPerSubsection || 0;
var subMeshesToMerge = subsectionsToMerge || 0;
var totalAmtFaces = threeMesh.geometry.faces.length;
var facesToProcess = createCollisionSubMeshes ? (subMeshesToMerge * facesPerSubSection) : totalAmtFaces;
var pairs = []; // output
var vertices = [];
var indicies = [];
for(var i = 0; i <= totalAmtFaces; i++) {
if(processedFaces == facesToProcess || i == totalAmtFaces) {
var body = null;
if(this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_CANNON) {
var meshShape = new CANNON.Trimesh(vertices, indicies);
meshShape.setScale(new CANNON.Vec3(threeMesh.scale.x, threeMesh.scale.y, threeMesh.scale.z));
meshShape.updateAABB();
meshShape.updateNormals();
meshShape.updateEdges();
meshShape.updateBoundingSphereRadius();
meshShape.updateTree();
body = new CANNON.Body({ mass: mass ? mass : 0, friction: friction ? friction : 10 });
body.addShape(meshShape);
} else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_AMMO) {
} else if (this.engine.engineType == GameLib.D3.Physics.Engine.TYPE_GOBLIN) {
}
pairs.push({
threeObject : createCollisionSubMeshes ? null : threeMesh,
physicsObject : body
});
vertices = [];
indicies = [];
processedFaces = 0;
if(i == totalAmtFaces) {
return pairs;
}
}
var face = threeMesh.geometry.faces[i];
indicies.push(indicies.length);
indicies.push(indicies.length);
indicies.push(indicies.length);
var v0 = threeMesh.geometry.vertices[face.a];
var v1 = threeMesh.geometry.vertices[face.b];
var v2 = threeMesh.geometry.vertices[face.c];
vertices.push(v0.x, v0.y, v0.z);
vertices.push(v1.x, v1.y, v1.z);
vertices.push(v2.x, v2.y, v2.z);
processedFaces++;
}
};
if (typeof module != 'undefined') {
module.exports = GameLib.D3;
}