2473 lines
65 KiB
JavaScript
2473 lines
65 KiB
JavaScript
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;
|
|
};
|
|
|
|
/**
|
|
* 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 = null;
|
|
}
|
|
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;
|
|
};
|
|
|
|
/**
|
|
* 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.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 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 GameLib.D3.Scene object into a ThreeJS Scene object
|
|
* @param blenderScene 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(blenderScene, onLoaded, computeNormals) {
|
|
|
|
console.log("loading scene " + blenderScene.name);
|
|
|
|
var meshQ = [];
|
|
|
|
for (var m = 0; m < blenderScene.meshes.length; m++) {
|
|
|
|
var mesh = blenderScene.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 < blenderScene.lights.length; sli++) {
|
|
|
|
var blenderLight = blenderScene.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);
|
|
});
|
|
};
|
|
|
|
if (typeof module != 'undefined') {
|
|
module.exports = GameLib.D3;
|
|
}
|