diff --git a/game-lib.js b/game-lib.js index e8d4022..11c3af1 100644 --- a/game-lib.js +++ b/game-lib.js @@ -1,64 +1,1777 @@ -function GameLib3d( - Q, - THREE, - BlenderNode, - config, - apiUrl, - editorUrl, - scenes, - worlds -) { - this.Q = Q; - this.THREE = THREE; - this.BlenderNode = BlenderNode; - this.editor = null; - - this.config = config; - - if (typeof apiUrl == 'undefined') { - apiUrl = this.config.api16.url; - } - this.apiUrl = apiUrl; - - if (typeof editorUrl == 'undefined') { - editorUrl = this.config.editor.url; - } - this.editorUrl = editorUrl; - - /** - * I disabled MultiMaterial for now - since it has 2 issues so far - * 1. Raycasting doesn't work for culled faces (https://github.com/mrdoob/three.js/issues/9694) - * 2. Warnings in console - three js breaks when intersecting with faces for which uvs arent defined - * @type {boolean} forceMultiMaterial - */ - this.forceMultiMaterial = false; - this.textureLoader = new THREE.TextureLoader(); -} +function GameLib() {} /** - * @param blenderTexture BlenderNode.Texture + * 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.promise|jQuery.promise|*|promise|Promise} + * @returns {Promise} */ -GameLib3d.prototype.loadMap = function(blenderTexture, threeMaterial, threeMaterialMapType) { +GameLib.D3.prototype.loadMap = function(gameLibTexture, threeMaterial, threeMaterialMapType) { var q = this.Q.defer(); var imagePath = null; - if (blenderTexture && blenderTexture.image && blenderTexture.image.apiPath && blenderTexture.image.filename) { + if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.apiPath && gameLibTexture.image.filename) { /** * Load the image from API here if apiPath is defined */ - imagePath = this.apiUrl + blenderTexture.image.uploadPath + '/' + blenderTexture.image.filename; + imagePath = this.apiUrl + gameLibTexture.image.uploadPath + '/' + gameLibTexture.image.filename; } - if (blenderTexture && blenderTexture.image && blenderTexture.image.uploadPath && blenderTexture.image.filename) { + if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.uploadPath && gameLibTexture.image.filename) { /** * Else, load from upload source */ - imagePath = this.editorUrl + blenderTexture.image.uploadPath + '/' + blenderTexture.image.filename; + imagePath = this.editorUrl + gameLibTexture.image.uploadPath + '/' + gameLibTexture.image.filename; } if (imagePath) { @@ -70,25 +1783,27 @@ GameLib3d.prototype.loadMap = function(blenderTexture, threeMaterial, threeMater * onLoad */ threeMaterial[threeMaterialMapType] = texture; - threeMaterial[threeMaterialMapType].name = blenderTexture.name; - threeMaterial[threeMaterialMapType].anisotropy = blenderTexture.anisotropy; - threeMaterial[threeMaterialMapType].encoding = blenderTexture.encoding; - threeMaterial[threeMaterialMapType].flipY = blenderTexture.flipY; - // threeMaterial[threeMaterialMapType].format = blenderTexture.format; - threeMaterial[threeMaterialMapType].generateMipmaps = blenderTexture.generateMipmaps; - threeMaterial[threeMaterialMapType].magFilter = blenderTexture.magFilter; - threeMaterial[threeMaterialMapType].minFilter = blenderTexture.minFilter; - threeMaterial[threeMaterialMapType].mapping = blenderTexture.mapping; - threeMaterial[threeMaterialMapType].mipmaps = blenderTexture.mipmaps; + 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( - blenderTexture.offset.x, - blenderTexture.offset.y + gameLibTexture.offset.x, + gameLibTexture.offset.y ); - threeMaterial[threeMaterialMapType].premultiplyAlpha = blenderTexture.premultiplyAlpha; - threeMaterial[threeMaterialMapType].textureType = blenderTexture.textureType; - threeMaterial[threeMaterialMapType].wrapS = blenderTexture.wrapS; - threeMaterial[threeMaterialMapType].wrapT = blenderTexture.wrapT; - threeMaterial[threeMaterialMapType].unpackAlignment = blenderTexture.unpackAlignment; + 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); }, @@ -117,26 +1832,27 @@ GameLib3d.prototype.loadMap = function(blenderTexture, threeMaterial, threeMater }; /** - * Creates a THREE Mesh from BlenderNode.Mesh - * @param mesh BlenderNode.Mesh - * @param geometry THREE.Geometry - * @param material THREE.Material + * Creates a THREE Mesh from GameLib.D3.Mesh + * @param gameLibMesh + * @param threeGeometry + * @param threeMaterial + * @returns {*} */ -GameLib3d.prototype.createThreeMesh = function(mesh, geometry, material) { +GameLib.D3.prototype.createThreeMesh = function(gameLibMesh, threeGeometry, threeMaterial) { var threeMesh = null; - if (mesh.meshType == this.BlenderNode.Mesh.TYPE_NORMAL) { - threeMesh = new this.THREE.Mesh(geometry, material); + if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_NORMAL) { + threeMesh = new this.THREE.Mesh(threeGeometry, threeMaterial); } - if (mesh.meshType == this.BlenderNode.Mesh.TYPE_SKINNED) { + if (gameLibMesh.meshType == GameLib.D3.Mesh.TYPE_SKINNED) { - var bones = mesh.skeleton.bones; + var bones = gameLibMesh.skeleton.bones; - var skinIndices = mesh.skinIndices; + var skinIndices = gameLibMesh.skinIndices; - var skinWeights = mesh.skinWeights; + var skinWeights = gameLibMesh.skinWeights; var threeBones = []; @@ -183,7 +1899,7 @@ GameLib3d.prototype.createThreeMesh = function(mesh, geometry, material) { * Setup bones (indexes) */ for (var si = 0; si < skinIndices.length; si++) { - geometry.skinIndices.push( + threeGeometry.skinIndices.push( new this.THREE.Vector4( skinIndices[si].x, skinIndices[si].y, @@ -197,7 +1913,7 @@ GameLib3d.prototype.createThreeMesh = function(mesh, geometry, material) { * Setup bones (weights) */ for (var sw = 0; sw < skinWeights.length; sw++) { - geometry.skinWeights.push( + threeGeometry.skinWeights.push( new this.THREE.Vector4( skinWeights[sw].x, skinWeights[sw].y, @@ -207,11 +1923,11 @@ GameLib3d.prototype.createThreeMesh = function(mesh, geometry, material) { ); } - threeMesh = new this.THREE.SkinnedMesh(geometry, material); + threeMesh = new this.THREE.SkinnedMesh(threeGeometry, threeMaterial); var skeleton = new this.THREE.Skeleton(threeBones); - skeleton.useVertexTexture = mesh.skeleton.useVertexTexture; + skeleton.useVertexTexture = gameLibMesh.skeleton.useVertexTexture; for (var i = 0; i < bones.length; i++) { if (bones[i].parentBoneId === null) { @@ -229,15 +1945,22 @@ GameLib3d.prototype.createThreeMesh = function(mesh, geometry, material) { } if (threeMesh == null) { - console.log('cannot handle meshes of type ' + mesh.meshType + ' yet.'); + console.log('cannot handle meshes of type ' + gameLibMesh.meshType + ' yet.'); } - mesh.threeMeshId = threeMesh.id; + gameLibMesh.threeMeshId = threeMesh.id; return threeMesh; }; -GameLib3d.prototype.loadMaps = function(blenderMaterial, blenderMaps, threeMaterial) { +/** + * 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 = []; @@ -315,10 +2038,10 @@ GameLib3d.prototype.loadMaps = function(blenderMaterial, blenderMaps, threeMater }; /** - * Creates a this.THREE Material from a this.BlenderNode.Material - * @param blenderMaterial this.BlenderNode.Material + * Creates a this.THREE.Material from a GameLib.D3.Material + * @param blenderMaterial GameLib.D3.Material */ -GameLib3d.prototype.createThreeMaterial = function(blenderMaterial) { +GameLib.D3.prototype.createThreeMaterial = function(blenderMaterial) { var defer = this.Q.defer(); @@ -326,7 +2049,7 @@ GameLib3d.prototype.createThreeMaterial = function(blenderMaterial) { var blenderMaps = []; - if (blenderMaterial.materialType == this.BlenderNode.Material.TYPE_MESH_STANDARD) { + if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_STANDARD) { threeMaterial = new this.THREE.MeshStandardMaterial({ name: blenderMaterial.name, @@ -392,7 +2115,7 @@ GameLib3d.prototype.createThreeMaterial = function(blenderMaterial) { 'alpha', 'environment' ); - } else if (blenderMaterial.materialType == this.BlenderNode.Material.TYPE_MESH_PHONG) { + } else if (blenderMaterial.materialType == GameLib.D3.Material.TYPE_MESH_PHONG) { threeMaterial = new this.THREE.MeshPhongMaterial({ name: blenderMaterial.name, @@ -487,12 +2210,12 @@ GameLib3d.prototype.createThreeMaterial = function(blenderMaterial) { }; /** - * Loads a this.BlenderNode.Scene object into a ThreeJS Scene object - * @param blenderScene this.BlenderNode.Scene + * 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 */ -GameLib3d.prototype.loadScene = function(blenderScene, onLoaded, computeNormals) { +GameLib.D3.prototype.loadScene = function(blenderScene, onLoaded, computeNormals) { console.log("loading scene " + blenderScene.name); @@ -648,17 +2371,10 @@ GameLib3d.prototype.loadScene = function(blenderScene, onLoaded, computeNormals) console.log("loaded all materials maps (" + materials.length + ")"); - var material = null; - - if (materials.length > 1 && gl3d.forceMultiMaterial) { - material = new gl3d.THREE.MultiMaterial(materials); - /** - * If I don't set the side of the MultiMaterial to DoubleSide, raycasting breaks - */ - //material.side = THREE.DoubleSide; - } else { - material = materials[0]; - } + /** + * 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; @@ -703,21 +2419,21 @@ GameLib3d.prototype.loadScene = function(blenderScene, onLoaded, computeNormals) var light = null; if (blenderLight.lightType == 'AmbientLight') { - light = new THREE.AmbientLight(blenderLight.color, blenderLight.intensity); + light = new this.THREE.AmbientLight(blenderLight.color, blenderLight.intensity); } if (blenderLight.lightType == 'DirectionalLight') { - light = new THREE.DirectionalLight(blenderLight.color, blenderLight.intensity); + light = new this.THREE.DirectionalLight(blenderLight.color, blenderLight.intensity); } if (blenderLight.lightType == 'PointLight') { - light = new THREE.PointLight(blenderLight.color, blenderLight.intensity); + light = new this.THREE.PointLight(blenderLight.color, blenderLight.intensity); light.distance = blenderLight.distance; light.decay = blenderLight.decay; } if (blenderLight.lightType == 'SpotLight') { - light = new THREE.SpotLight(blenderLight.color, blenderLight.intensity); + light = new this.THREE.SpotLight(blenderLight.color, blenderLight.intensity); light.distance = blenderLight.distance; light.angle = blenderLight.angle; light.penumbra = blenderLight.penumbra; @@ -751,7 +2467,6 @@ GameLib3d.prototype.loadScene = function(blenderScene, onLoaded, computeNormals) }); }; - -if (typeof module !== 'undefined') { - module.exports = GameLib3d; -} \ No newline at end of file +if (typeof module != 'undefined') { + module.exports = GameLib.D3; +}