fixed image loading - tests passing

beta.r3js.org
Theunis J. Botha 2016-11-03 14:33:14 +01:00
parent 9b6c5d4348
commit c988516f8d
4 changed files with 440 additions and 434 deletions

View File

@ -0,0 +1,9 @@
ApiLib = function() {
};
ApiLib.Scene = function(
) {
};

View File

@ -407,11 +407,6 @@ GameLib.D3.Material = function(
envMapIntensity = 1.0;
}
this.envMapIntensity = envMapIntensity;
/**
* @type GameLib.D3.Material.ImageLoadedCallback[]
*/
this.OnImageLoadedCallbacks = [];
};
/**
@ -530,13 +525,115 @@ GameLib.D3.Material.TYPE_MULTI_MATERIAL= "MultiMaterial";
* Creates an instance Material from a GameLib.D3.Material
* @param apiMaterial GameLib.D3.Material
* @param graphics GameLib.D3.Graphics
* @param imageLoader GameLib.D3.Texture
* @param gameLibScene GameLib.D3.Scene
*/
GameLib.D3.Material.CreateInstanceMaterial = function(
apiMaterial,
graphics,
imageLoader
gameLibScene
) {
var maps = apiMaterial.maps;
var gameLibTextures = [];
for (var map in maps) {
if (maps.hasOwnProperty(map)) {
if (maps[map]) {
var instanceMapId = null;
if (map == 'alpha') {
instanceMapId = 'alhpaMap';
}
if (map == 'ao') {
instanceMapId = 'aoMap';
}
if (map == 'bump') {
instanceMapId = 'bumpMap';
}
if (map == 'displacement') {
instanceMapId = 'displacementMap';
}
if (map == 'emissive') {
instanceMapId = 'emissiveMap';
}
if (map == 'environment') {
instanceMapId = 'envMap';
}
if (map == 'light') {
instanceMapId = 'lightMap';
}
if (map == 'specular') {
instanceMapId = 'specularMap';
}
if (map == 'diffuse') {
instanceMapId = 'map';
}
if (map == 'roughness') {
instanceMapId = 'roughnessMap';
}
if (map == 'metalness') {
instanceMapId = 'metalnessMap';
}
if (instanceMapId == null) {
console.warn("unsupported map type : " + map);
}
var apiTexture = maps[map];
var apiImage = apiTexture.image;
var gameLibTexture = new GameLib.D3.Texture(
apiTexture.id,
apiTexture.name,
new GameLib.D3.Image(
apiImage.id,
apiImage.textureLink,
apiImage.filename,
apiImage.size,
apiImage.contentType
),
apiTexture.wrapS,
apiTexture.wrapT,
new GameLib.D3.Vector2(
apiTexture.repeat.x,
apiTexture.repeat.y
),
apiTexture.data,
apiTexture.format,
apiTexture.mapping,
apiTexture.magFilter,
apiTexture.minFilter,
apiTexture.textureType,
apiTexture.anisotropy,
new GameLib.D3.Vector2(
apiTexture.offset.x,
apiTexture.offset.y
),
apiTexture.generateMipmaps,
apiTexture.flipY,
apiTexture.mipmaps,
apiTexture.unpackAlignment,
apiTexture.premultiplyAlpha,
apiTexture.encoding,
instanceMapId
);
gameLibTextures.push(gameLibTexture);
}
}
}
var gameLibMaterial = new GameLib.D3.Material(
apiMaterial.id,
apiMaterial.name,
@ -544,7 +641,7 @@ GameLib.D3.Material.CreateInstanceMaterial = function(
apiMaterial.opacity,
apiMaterial.side,
apiMaterial.transparent,
apiMaterial.maps,
gameLibTextures,
new GameLib.D3.Color(
apiMaterial.specular.r,
apiMaterial.specular.g,
@ -614,156 +711,134 @@ GameLib.D3.Material.CreateInstanceMaterial = function(
var instanceMaterial = null;
var blenderMaps = [];
if (apiMaterial.materialType == GameLib.D3.Material.TYPE_MESH_STANDARD) {
if (gameLibMaterial.materialType == GameLib.D3.Material.TYPE_MESH_STANDARD) {
instanceMaterial = new graphics.instance.MeshStandardMaterial({
name: apiMaterial.name,
opacity: apiMaterial.opacity,
transparent: apiMaterial.transparent,
blending: apiMaterial.blending,
blendSrc: apiMaterial.blendSrc,
blendDst: apiMaterial.blendDst,
blendEquation: apiMaterial.blendEquation,
depthTest: apiMaterial.depthTest,
depthFunc: apiMaterial.depthFunc,
depthWrite: apiMaterial.depthWrite,
polygonOffset: apiMaterial.polygonOffset,
polygonOffsetFactor: apiMaterial.polygonOffsetFactor,
polygonOffsetUnits: apiMaterial.polygonOffsetUnits,
alphaTest: apiMaterial.alphaTest,
clippingPlanes: apiMaterial.clippingPlanes,
clipShadows: apiMaterial.clipShadows,
overdraw: apiMaterial.overdraw,
visible: apiMaterial.visible,
side: apiMaterial.side,
name: gameLibMaterial.name,
opacity: gameLibMaterial.opacity,
transparent: gameLibMaterial.transparent,
blending: gameLibMaterial.blending,
blendSrc: gameLibMaterial.blendSrc,
blendDst: gameLibMaterial.blendDst,
blendEquation: gameLibMaterial.blendEquation,
depthTest: gameLibMaterial.depthTest,
depthFunc: gameLibMaterial.depthFunc,
depthWrite: gameLibMaterial.depthWrite,
polygonOffset: gameLibMaterial.polygonOffset,
polygonOffsetFactor: gameLibMaterial.polygonOffsetFactor,
polygonOffsetUnits: gameLibMaterial.polygonOffsetUnits,
alphaTest: gameLibMaterial.alphaTest,
clippingPlanes: gameLibMaterial.clippingPlanes,
clipShadows: gameLibMaterial.clipShadows,
overdraw: gameLibMaterial.overdraw,
visible: gameLibMaterial.visible,
side: gameLibMaterial.side,
color: new graphics.instance.Color(
apiMaterial.color.r,
apiMaterial.color.g,
apiMaterial.color.b
gameLibMaterial.color.r,
gameLibMaterial.color.g,
gameLibMaterial.color.b
),
roughness: apiMaterial.roughness,
metalness: apiMaterial.metalness,
lightMapIntensity: apiMaterial.lightMapIntensity,
aoMapIntensity: apiMaterial.aoMapIntensity,
roughness: gameLibMaterial.roughness,
metalness: gameLibMaterial.metalness,
lightMapIntensity: gameLibMaterial.lightMapIntensity,
aoMapIntensity: gameLibMaterial.aoMapIntensity,
emissive: new graphics.instance.Color(
apiMaterial.emissive.r,
apiMaterial.emissive.g,
apiMaterial.emissive.b
gameLibMaterial.emissive.r,
gameLibMaterial.emissive.g,
gameLibMaterial.emissive.b
),
emissiveIntensity: apiMaterial.emissiveIntensity,
bumpScale: apiMaterial.bumpScale,
normalScale: apiMaterial.normalScale,
displacementScale: apiMaterial.displacementScale,
refractionRatio: apiMaterial.refractionRatio,
fog: apiMaterial.fog,
shading: apiMaterial.shading,
wireframe: apiMaterial.wireframe,
wireframeLinewidth: apiMaterial.wireframeLineWidth,
wireframeLinecap: apiMaterial.wireframeLineCap,
wireframeLinejoin: apiMaterial.wireframeLineJoin,
vertexColors: apiMaterial.vertexColors,
skinning: apiMaterial.skinning,
morphTargets: apiMaterial.morphTargets,
morphNormals: apiMaterial.morphNormals
emissiveIntensity: gameLibMaterial.emissiveIntensity,
bumpScale: gameLibMaterial.bumpScale,
normalScale: gameLibMaterial.normalScale,
displacementScale: gameLibMaterial.displacementScale,
refractionRatio: gameLibMaterial.refractionRatio,
fog: gameLibMaterial.fog,
shading: gameLibMaterial.shading,
wireframe: gameLibMaterial.wireframe,
wireframeLinewidth: gameLibMaterial.wireframeLineWidth,
wireframeLinecap: gameLibMaterial.wireframeLineCap,
wireframeLinejoin: gameLibMaterial.wireframeLineJoin,
vertexColors: gameLibMaterial.vertexColors,
skinning: gameLibMaterial.skinning,
morphTargets: gameLibMaterial.morphTargets,
morphNormals: gameLibMaterial.morphNormals
});
blenderMaps.push(
'diffuse',
'light',
'ao',
'emissive',
'bump',
'normal',
'displacement',
'roughness',
'metalness',
'alpha',
'environment'
);
} else if (apiMaterial.materialType == GameLib.D3.Material.TYPE_MESH_PHONG) {
} else if (gameLibMaterial.materialType == GameLib.D3.Material.TYPE_MESH_PHONG) {
instanceMaterial = new graphics.instance.MeshPhongMaterial({
name: apiMaterial.name,
opacity: apiMaterial.opacity,
transparent: apiMaterial.transparent,
blending: apiMaterial.blending,
blendSrc: apiMaterial.blendSrc,
blendDst: apiMaterial.blendDst,
blendEquation: apiMaterial.blendEquation,
depthTest: apiMaterial.depthTest,
depthFunc: apiMaterial.depthFunc,
depthWrite: apiMaterial.depthWrite,
polygonOffset: apiMaterial.polygonOffset,
polygonOffsetFactor: apiMaterial.polygonOffsetFactor,
polygonOffsetUnits: apiMaterial.polygonOffsetUnits,
alphaTest: apiMaterial.alphaTest,
clippingPlanes: apiMaterial.clippingPlanes,
clipShadows: apiMaterial.clipShadows,
overdraw: apiMaterial.overdraw,
visible: apiMaterial.visible,
side: apiMaterial.side,
name: gameLibMaterial.name,
opacity: gameLibMaterial.opacity,
transparent: gameLibMaterial.transparent,
blending: gameLibMaterial.blending,
blendSrc: gameLibMaterial.blendSrc,
blendDst: gameLibMaterial.blendDst,
blendEquation: gameLibMaterial.blendEquation,
depthTest: gameLibMaterial.depthTest,
depthFunc: gameLibMaterial.depthFunc,
depthWrite: gameLibMaterial.depthWrite,
polygonOffset: gameLibMaterial.polygonOffset,
polygonOffsetFactor: gameLibMaterial.polygonOffsetFactor,
polygonOffsetUnits: gameLibMaterial.polygonOffsetUnits,
alphaTest: gameLibMaterial.alphaTest,
clippingPlanes: gameLibMaterial.clippingPlanes,
clipShadows: gameLibMaterial.clipShadows,
overdraw: gameLibMaterial.overdraw,
visible: gameLibMaterial.visible,
side: gameLibMaterial.side,
color: new graphics.instance.Color(
apiMaterial.color.r,
apiMaterial.color.g,
apiMaterial.color.b
gameLibMaterial.color.r,
gameLibMaterial.color.g,
gameLibMaterial.color.b
),
specular: new graphics.instance.Color(
apiMaterial.specular.r,
apiMaterial.specular.g,
apiMaterial.specular.b
gameLibMaterial.specular.r,
gameLibMaterial.specular.g,
gameLibMaterial.specular.b
),
shininess: apiMaterial.shininess,
lightMapIntensity: apiMaterial.lightMapIntensity,
aoMapIntensity: apiMaterial.aoMapIntensity,
shininess: gameLibMaterial.shininess,
lightMapIntensity: gameLibMaterial.lightMapIntensity,
aoMapIntensity: gameLibMaterial.aoMapIntensity,
emissive: new graphics.instance.Color(
apiMaterial.emissive.r,
apiMaterial.emissive.g,
apiMaterial.emissive.b
gameLibMaterial.emissive.r,
gameLibMaterial.emissive.g,
gameLibMaterial.emissive.b
),
emissiveIntensity: apiMaterial.emissiveIntensity,
bumpScale: apiMaterial.bumpScale,
normalScale: apiMaterial.normalScale,
displacementScale: apiMaterial.displacementScale,
combine: apiMaterial.combine,
refractionRatio: apiMaterial.refractionRatio,
fog: apiMaterial.fog,
shading: apiMaterial.shading,
wireframe: apiMaterial.wireframe,
wireframeLinewidth: apiMaterial.wireframeLineWidth,
wireframeLinecap: apiMaterial.wireframeLineCap,
wireframeLinejoin: apiMaterial.wireframeLineJoin,
vertexColors: apiMaterial.vertexColors,
skinning: apiMaterial.skinning,
morphTargets: apiMaterial.morphTargets,
morphNormals: apiMaterial.morphNormals
emissiveIntensity: gameLibMaterial.emissiveIntensity,
bumpScale: gameLibMaterial.bumpScale,
normalScale: gameLibMaterial.normalScale,
displacementScale: gameLibMaterial.displacementScale,
combine: gameLibMaterial.combine,
refractionRatio: gameLibMaterial.refractionRatio,
fog: gameLibMaterial.fog,
shading: gameLibMaterial.shading,
wireframe: gameLibMaterial.wireframe,
wireframeLinewidth: gameLibMaterial.wireframeLineWidth,
wireframeLinecap: gameLibMaterial.wireframeLineCap,
wireframeLinejoin: gameLibMaterial.wireframeLineJoin,
vertexColors: gameLibMaterial.vertexColors,
skinning: gameLibMaterial.skinning,
morphTargets: gameLibMaterial.morphTargets,
morphNormals: gameLibMaterial.morphNormals
});
blenderMaps.push(
'diffuse',
'light',
'ao',
'emissive',
'bump',
'normal',
'displacement',
'specular',
'alpha',
'environment'
);
} else {
console.log("material type is not implemented yet: " + apiMaterial.materialType + " - material indexes could be screwed up");
}
if (blenderMaps.length > 0) {
imageLoader.setup(
gameLibMaterial,
instanceMaterial,
blenderMaps
);
/**
* Here we need to notify the scene of all the textures which need to be created once image loading for the
* textures are complete. (this download process will be started at a later stage)
* The Notification objects take care of applying the loaded instance texture(s) to the instance material
* once it is loaded
*/
for (var t = 0; t < gameLibTextures.length; t++) {
gameLibScene.notify(
new GameLib.D3.Texture.Notification(
gameLibTextures[t],
instanceMaterial
)
)
}
return instanceMaterial;

View File

@ -1,23 +1,27 @@
/**
* Scenes are objects putting meshes into 'world space'
* @param id
* @param id Mongo.ObjectId
* @param path String
* @param name String
* @param graphics GameLib.D3.Graphics
* @param meshes GameLib.D3.Mesh[]
* @param quaternion
* @param position
* @param rotation
* @param scale
* @param parentSceneId
* @param lights
* @param worlds
* @param entities
* @param quaternion GameLib.D3.Vector4
* @param position GameLib.D3.Vector3
* @param rotation GameLib.D3.Vector3
* @param scale GameLib.D3.Vector3
* @param parentSceneId String
* @param lights GameLib.D3.Light[]
* @param worlds GameLib.D3.World[]
* @param entities GameLib.D3.Entity[]
* @param progressCallback
* @param uploadUrl String
* @constructor
*/
GameLib.D3.Scene = function(
id,
path,
name,
graphics,
meshes,
quaternion,
position,
@ -26,12 +30,23 @@ GameLib.D3.Scene = function(
parentSceneId,
lights,
worlds,
entities
entities,
progressCallback,
uploadUrl
) {
this.id = id;
this.sceneId = GameLib.D3.Tools.RandomId();
this.path = path;
this.name = name;
this.graphics = graphics;
if (graphics) {
this.graphics.isNotThreeThrow();
this.textureLoader = new this.graphics.instance.TextureLoader();
this.textureLoader.crossOrigin = '';
}
if (this.name.trim() == "") {
this.name = 'unnamed';
}
@ -80,6 +95,142 @@ GameLib.D3.Scene = function(
entities = [];
}
this.entities = entities;
this.uploadUrl = uploadUrl;
this.progressCallback = progressCallback;
this.urls = [];
this.notifications = [];
};
/**
* Notification objects manage the links between image filenames, instance texture
* map IDs, and instance materials.
* @param notification GameLib.D3.Texture.Notificatio
* @constructor
*/
GameLib.D3.Scene.prototype.notify = function(
notification
) {
var url = this.uploadUrl + '/' + notification.gameLibTexture.image.filename;
if (this.urls.indexOf(url) == -1) {
this.urls.push(url);
}
this.notifications.push(notification);
};
/**
* Promises to loads a texture
* @param url
* @returns {promise.promise|jQuery.promise|*|promise|Promise}
*/
GameLib.D3.Scene.prototype.loadTexture = function(url) {
var defer = Q.defer();
this.textureLoader.load(
url,
function onLoad(textureInstance){
defer.resolve(textureInstance);
},
function onProgress(xhr){
if (this.progressCallback) {
this.progressCallback(Math.round(xhr.loaded / xhr.total * 100))
}
},
function onError() {
defer.resolve(null);
}
);
return defer.promise;
};
/**
* Starts a Image Loading Process - when all are done - executes all calbacks registered
* on materials listening for an image load to complete
* @param urls
* @param onLoadedCallback
* @returns {jQuery.promise|promise.promise|*|Promise|promise}
*/
GameLib.D3.Scene.prototype.loadTextures = function(urls, onLoadedCallback) {
var texturesToLoad = [];
for (var u = 0; u < urls.length; u++) {
texturesToLoad.push(this.loadTexture(urls[u]));
}
Q.all(texturesToLoad).then(
function onFulfilled(textureInstances) {
var loadedTexturesInstances = [];
for (var t = 0; t < textureInstances.length; t++) {
var instanceTexture = textureInstances[t];
if (!instanceTexture) {
continue;
}
for (var n = 0; n < this.notifications.length; n++) {
var notification = this.notifications[n];
var gameLibTexture = notification.gameLibTexture;
var instanceMaterial = notification.instanceMaterial;
var instanceMapId = gameLibTexture.instanceMapId;
var filename = gameLibTexture.image.filename;
if (instanceTexture.image.src.match(new RegExp(filename + '$'))) {
instanceMaterial[instanceMapId] = new this.graphics.instance.Texture(
instanceTexture.image,
gameLibTexture.mapping,
gameLibTexture.wrapS,
gameLibTexture.wrapT,
gameLibTexture.magFilter,
gameLibTexture.minFilter,
gameLibTexture.format,
gameLibTexture.textureType,
gameLibTexture.anisotropy
);
instanceMaterial[instanceMapId].name = gameLibTexture.name;
instanceMaterial[instanceMapId].flipY = gameLibTexture.flipY;
instanceMaterial[instanceMapId].encoding = gameLibTexture.encoding;
instanceMaterial[instanceMapId].flipY = gameLibTexture.flipY;
instanceMaterial[instanceMapId].offset.x = gameLibTexture.offset.x;
instanceMaterial[instanceMapId].offset.y = gameLibTexture.offset.y;
instanceMaterial[instanceMapId].mipmaps = gameLibTexture.mipmaps;
instanceMaterial[instanceMapId].unpackAlignment = gameLibTexture.unpackAlignment;
instanceMaterial[instanceMapId].premultiplyAlpha = gameLibTexture.premultiplyAlpha;
instanceMaterial[instanceMapId].needsUpdate = true;
instanceMaterial.needsUpdate = true;
loadedTexturesInstances.push(instanceMaterial[instanceMapId]);
}
}
}
onLoadedCallback(loadedTexturesInstances);
}.bind(this),
function onRejected(message){
console.log('Promise failed : ' + message);
},
function onProgress(){
console.log('progress');
}
);
};
/**
@ -126,7 +277,7 @@ GameLib.D3.Scene.LoadSceneFromApi = function(
var scene = response.scene[0];
var physics3ds = [];
var entities = [];
if (scene.worlds && scene.worlds.length > 0) {
console.warn('Implement physics worlds code here');
@ -192,6 +343,7 @@ GameLib.D3.Scene.LoadSceneFromApi = function(
scene._id || scene.id,
scene.path,
scene.name,
graphics,
scene.meshes,
new GameLib.D3.Vector4(
scene.quaternion.x,
@ -216,16 +368,17 @@ GameLib.D3.Scene.LoadSceneFromApi = function(
),
scene.parentSceneId,
lights3d,
physics3ds
entities,
uploadUrl,
progressCallback,
uploadUrl
);
GameLib.D3.Scene.LoadScene(
scene3d,
onLoaded,
false,
graphics,
uploadUrl,
progressCallback
graphics
);
}
}
@ -240,16 +393,12 @@ GameLib.D3.Scene.LoadSceneFromApi = function(
* @param onLoaded callback when all meshes have loaded
* @param computeNormals set to true to compute new face and vertex normals during load
* @param graphics GameLib.D3.Graphics
* @param uploadUrl
* @param progressCallback
*/
GameLib.D3.Scene.LoadScene = function(
gameLibScene,
onLoaded,
computeNormals,
graphics,
uploadUrl,
progressCallback
graphics
) {
console.log("loading scene " + gameLibScene.name);
@ -263,12 +412,6 @@ GameLib.D3.Scene.LoadScene = function(
var instanceMeshes = [];
var gameLibTexture = new GameLib.D3.Texture(
graphics,
uploadUrl,
progressCallback
);
for (var m = 0; m < gameLibScene.meshes.length; m++) {
var mesh = gameLibScene.meshes[m];
@ -407,7 +550,7 @@ GameLib.D3.Scene.LoadScene = function(
var instanceMaterial = GameLib.D3.Material.CreateInstanceMaterial(
materials[0],
graphics,
gameLibTexture
gameLibScene
);
var instanceMesh = GameLib.D3.Mesh.CreateInstanceMesh(
@ -519,23 +662,43 @@ GameLib.D3.Scene.LoadScene = function(
instanceScene.add(instanceLights[l]);
}
gameLibTexture.start.then(
function onFullfilled() {
onLoaded(
gameLibScene,
{
scene: instanceScene,
lights: instanceLights,
meshes: instanceMeshes
}
);
},
function onRejected(message) {
console.log('Image loading failed with the following message: ' + message);
},
function onProgress() {
console.log('loading images...');
}
);
gameLibScene.loadTextures(gameLibScene.urls, function(loadedTextures) {
console.log('Found image data and applied it to ' + loadedTextures.length + ' textures');
onLoaded(
gameLibScene,
{
scene: instanceScene,
lights: instanceLights,
meshes: instanceMeshes
}
);
});
};
GameLib.D3.Scene.FromAPIScene = function(
apiScene,
graphics,
progressCallback,
uploadUrl
) {
return new GameLib.D3.Scene(
apiScene.id,
apiScene.path,
apiScene.name,
graphics,
apiScene.meshes,
apiScene.quaternion,
apiScene.position,
apiScene.rotation,
apiScene.scale,
apiScene.parentSceneId,
apiScene.lights,
apiScene.worlds,
apiScene.entities,
progressCallback,
uploadUrl
)
};

View File

@ -20,6 +20,7 @@
* @param unpackAlignment
* @param premultiplyAlpha
* @param encoding
* @param instanceMapId
* @constructor
*/
GameLib.D3.Texture = function(
@ -42,7 +43,8 @@ GameLib.D3.Texture = function(
mipmaps,
unpackAlignment,
premultiplyAlpha,
encoding
encoding,
instanceMapId
) {
this.id = id;
this.name = name;
@ -132,6 +134,8 @@ GameLib.D3.Texture = function(
encoding = GameLib.D3.Texture.TYPE_LINEAR_ENCODING;
}
this.encoding = encoding;
this.instanceMapId = instanceMapId;
};
/**
@ -204,263 +208,18 @@ GameLib.D3.Texture.TYPE_RGBM16_ENCODING = 3005;
GameLib.D3.Texture.TYPE_RGBD_ENCODING = 3006; // MAXRANGE IS 256.
/**
* Defers loading of an image and resolves once image is loaded
* @param gameLibTexture GameLib.D3.Texture
* A Notification object stores an association between a gameLibTexture and a instance material map.
* @param instanceMaterial
* @param instanceMaterialMapType
* @param graphics GameLib.D3.Graphics
* @param uploadUrl String
* @param progressCallback
* @returns {Promise}
* @param gameLibTexture
* @constructor
*/
GameLib.D3.Texture.LoadMap = function(
GameLib.D3.Texture.Notification = function(
gameLibTexture,
instanceMaterial,
instanceMaterialMapType,
graphics,
uploadUrl,
progressCallback
instanceMaterial
) {
var defer = Q.defer();
var imagePath = null;
var textureLoader = new graphics.instance.TextureLoader();
if (gameLibTexture && gameLibTexture.image && gameLibTexture.image.filename) {
/**
* Else, load from upload source
*/
imagePath = uploadUrl + '/' + gameLibTexture.image.filename;
}
if (!imagePath) {
defer.reject("No image path");
return defer.promise;
}
return defer.promise;
};
/**
* Image Loader - attempts to reduce image loading calls by only loading the necessary images once - and setting
* them up per material later.
* @param graphics GameLib.D3.Graphics
* @param uploadUrl String
* @param progressCallback
* @constructor
*/
GameLib.D3.Texture = function(
graphics,
uploadUrl,
progressCallback
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
this.textureLoader = new this.graphics.instance.TextureLoader();
this.textureLoader.crossOrigin = '';
this.uploadUrl = uploadUrl;
this.progressCallback = progressCallback;
this.urls = [];
this.gameLibMaterials = [];
this.gameLibTexture = gameLibTexture;
this.instanceMaterial = instanceMaterial;
};
/**
* Sets up the Texture Loader by Notifying it of any images that we intend to download soon
* Instead of starting the download immediately - we should collect all the image URLs and attempt
* to download them only once - then after they have downloaded, we execute any pending OnImageLoaded callbacks
* on the Material
* @param gameLibMaterial
* @param instanceMaterial
* @param blenderMaps
*/
GameLib.D3.Texture.prototype.setup = function(
gameLibMaterial,
instanceMaterial,
blenderMaps
) {
for (var ti = 0; ti < blenderMaps.length; ti++) {
var map = blenderMaps[ti];
if (gameLibMaterial.maps.hasOwnProperty(map)) {
var blenderTexture = gameLibMaterial.maps[map];
if (
blenderTexture &&
blenderTexture.image &&
blenderTexture.image.filename
) {
var instanceMapId = null;
if (map == 'alpha') {
instanceMapId = 'alhpaMap';
}
if (map == 'ao') {
instanceMapId = 'aoMap';
}
if (map == 'bump') {
instanceMapId = 'bumpMap';
}
if (map == 'displacement') {
instanceMapId = 'displacementMap';
}
if (map == 'emissive') {
instanceMapId = 'emissiveMap';
}
if (map == 'environment') {
instanceMapId = 'envMap';
}
if (map == 'light') {
instanceMapId = 'lightMap';
}
if (map == 'specular') {
instanceMapId = 'specularMap';
}
if (map == 'diffuse') {
instanceMapId = 'map';
}
if (map == 'roughness') {
instanceMapId = 'roughnessMap';
}
if (map == 'metalness') {
instanceMapId = 'metalnessMap';
}
if (instanceMapId == null) {
console.warn("unsupported map type : " + map);
}
gameLibMaterial.OnImageLoadedCallbacks.push(
new GameLib.D3.Material.ImageLoadedCallback(
instanceMaterial,
instanceMapId
)
);
this.notify(
gameLibMaterial,
blenderTexture.image.filename
);
}
}
}
};
/**
* Notifies the texture loader to load the image (if not already started)
* @param gameLibMaterial
* @param fileName
* @constructor
*/
GameLib.D3.Texture.prototype.notify = function(
gameLibMaterial,
fileName
) {
this.gameLibMaterials.push(gameLibMaterial);
this.urls.push(this.uploadUrl + '/' + fileName);
};
GameLib.D3.Texture.prototype.loadTexture = function(url, gameLibTexture) {
var defer = Q.defer();
this.textureLoader.load(
url,
function onLoad(textureInstance){
textureInstance.name = gameLibTexture.name;
textureInstance.anisotropy = gameLibTexture.anisotropy;
textureInstance.encoding = gameLibTexture.encoding;
textureInstance.flipY = gameLibTexture.flipY;
/**
* We don't restore the format since this changing from OS to OS and breaks the implementation sometimes
*/
textureInstance.generateMipmaps = gameLibTexture.generateMipmaps;
textureInstance.magFilter = gameLibTexture.magFilter;
textureInstance.minFilter = gameLibTexture.minFilter;
textureInstance.mapping = gameLibTexture.mapping;
textureInstance.mipmaps = gameLibTexture.mipmaps;
textureInstance.offset = new this.graphics.instance.Vector2(
gameLibTexture.offset.x,
gameLibTexture.offset.y
);
textureInstance.premultiplyAlpha = gameLibTexture.premultiplyAlpha;
textureInstance.textureType = gameLibTexture.textureType;
textureInstance.wrapS = gameLibTexture.wrapS;
textureInstance.wrapT = gameLibTexture.wrapT;
textureInstance.unpackAlignment = gameLibTexture.unpackAlignment;
textureInstance.needsUpdate = true;
defer.resolve(textureInstance);
},
function onProgress(xhr){
if (this.progressCallback) {
this.progressCallback(Math.round(xhr.loaded / xhr.total * 100))
}
},
function onError() {
defer.resolve(null);
}
);
return defer.promise;
};
/**
* Starts a Image Loading Process - when all are done - executes all calbacks registered
* on materials listening for an image load to complete
* @returns {promise.promise|jQuery.promise|*|Promise|promise}
*/
GameLib.D3.Texture.prototype.start = function() {
var defer = Q.defer();
var texturesToLoad = [];
for (var u = 0; u < this.urls.length; u++) {
texturesToLoad.push(this.loadTexture(url, this.gameLibMaterials[u]));
}
Q.all(texturesToLoad).then(
function(texture) {
return function onFulfilled(results) {
for (var r = 0; r < results.length; r++) {
for (var t = 0; t < texture.gameLibMaterials.length; t++) {
for (var cb = 0; cb < texture.gameLibMaterials[t].OnImageLoadedCallbacks.length; cb++) {
texture.gameLibMaterials[t].OnImageLoadedCallbacks(results[r]);
}
}
}
defer.resolve(results);
};
}(this),
function onRejected(message){
defer.reject(message);
},
function onProgress(){
console.log('progress');
}
);
return defer.promise;
};