It loads a Gravatar image via an Image object and sets that on a PlayCanvas texture. The image URL is set on a script attribute.
The script is:
var LoadImage = pc.createScript('loadImage');
LoadImage.attributes.add('url', { type: 'string' });
// initialize code called once per entity
LoadImage.prototype.initialize = function() {
var self = this;
var image = new Image();
image.crossOrigin = "anonymous";
image.onload = function () {
var texture = new pc.Texture(self.app.graphicsDevice);
texture.setSource(image);
var material = self.entity.model.material;
material.diffuseMap = texture;
material.update();
};
image.src = this.url;
};
Notice how the Image is marked as being CORS-enabled (which is mandatory for passing images to WebGL) with the line:
image.crossOrigin = "anonymous";
Note that the server from where the image is served must be CORS-enabled.
Just as a side note, I notice this was also submitted to the Answers site. Best to chose one or the other rather than both. Personally, I’d recommend sticking to the forum. The Answers site will probably be retired at some point.
var LoadImage = pc.createScript('loadImage');
LoadImage.attributes.add('url', { type: 'string' });
// initialize code called once per entity
LoadImage.prototype.initialize = function() {
var self = this;
var image = new Image();
image.crossOrigin = "anonymous";
image.onload = function () {
/* var texture = new pc.Texture(self.app.graphicsDevice);
texture.setSource(image);
var material = self.entity.model.material;
material.diffuseMap = texture;
material.update();*/
var texture = asset._resources[0];
var entity = app.root.findByName("BSO");
entity.model.model.meshInstances[1].material.diffuseMap = texture;
entity.model.model.meshInstances[1].material.update();
};
image.src = this.url;
};
I tried as he said but either field did not appear. (Created a new script for it to example)
var Foo = pc.createScript('foo');
Foo.attributes.add("fooID", {type: "string"});
// initialize code called once per entity
Foo.prototype.initialize = function() {
};
...
Also there are 2 things i did not understand:
ok so now Will has an attribute called ‘url’ which is assigned externally - but i don’t see where he’s using it in the code.
graphicsDevice (self.app.graphicsDevice) - what’s this? and why didn’t he use loadfromURL?
var ChangeMaterial = pc.createScript('changeMaterial');
var URL_prefix ='https://s3-us-west-2.amazonaws.com/ticomsoft-image-repo/';
var ID = '1';
var URL_sufix = '.png';
var name;
var targetMaterial;
ChangeMaterial.prototype.initialize = function() {
var url = URL_prefix+ID+URL_sufix;
console.log(url);
name ="laptopFBX";
targetMaterial = 1;
/*
//phil165's offer - kinda works, no cors
app = pc.Application.getApplication();
app.assets.loadFromUrl(url, "texture", function (err, asset) {
var texture = asset._resources[0];
var entity = app.root.findByName(name);
entity.model.model.meshInstances[targetMaterial].material.diffuseMap = texture;
entity.model.model.meshInstances[targetMaterial].material.update();
});
*/
//will's offer - error 404;
var self = this;
var image = new Image();
image.crossOrigin = "anonymous";
image.onload = function () {
var texture = new pc.Texture(self.app.graphicsDevice);
texture.setSource(image);
var material = self.entity.model.material;
material.diffuseMap = texture;
material.update();
};
image.src = this.url;
};
in its spirit i managed to create a CORS based code that works
var ChangeMaterial2 = pc.createScript('changeMaterial2');
var URL_prefix ='https://s3-us-west-2.amazonaws.com/ticomsoft-image-repo/';
var ID = '1';
var URL_sufix = '.png';
ChangeMaterial2.attributes.add("targetMaterial", {targetMaterial: 'int'});
ChangeMaterial2.prototype.initialize = function() {
var self = this;
var imageUrl = URL_prefix+ID+URL_sufix;
console.log(imageUrl);
targetMaterial = 9;
// allow cross origin texture requests
this.app.loader.getHandler("texture").crossOrigin = "anonymous";
var asset = new pc.Asset("myTexture", "texture", {
url: imageUrl
});
this.app.assets.add(asset);
asset.on("load", function (asset) {
var material = self.entity.model.meshInstances[targetMaterial].material;
material.diffuseMap = asset.resource;
material.update();
});
this.app.assets.load(asset);
};
but a strange thing is that the attribute/variable ‘targetMaterial’ doesn’t appear externally, but the ‘url’ does even though it appears in a function scope;
why doesn’t targetMaterial appearing?
and why did ‘url’ appear?
TL;DR: For the editor to show the attributes of the scripts, it needs to ‘parse’ them to know what attributes have been added and this is a manual step.
the only question left is that i cic not see where is the url used in Will’s code
var self = this;
var image = new Image();
image.crossOrigin = "anonymous";
image.onload = function () {
var texture = new pc.Texture(self.app.graphicsDevice);
texture.setSource(image);
var material = self.entity.model.material;
material.diffuseMap = texture;
material.update();
};
image.src = this.url;
};
and what does the new pc.Texture(self.app.graphicsDevice); means? why didn’t he use loadFromUrl ?
var ChangeMaterial2 = pc.createScript('changeMaterial2');
var imageUrl ='https://s3-us-west-2.amazonaws.com/ticomsoft-image-repo/1.png';
ChangeMaterial2.attributes.add("targetMaterial", {type: 'number'});
ChangeMaterial2.prototype.initialize = function() {
var self = this;
console.log(imageUrl);
targetMaterial = 9;
// allow cross origin texture requests
this.app.loader.getHandler("texture").crossOrigin = "anonymous";
var asset = new pc.Asset("myTexture", "texture", {
url: imageUrl
});
this.app.assets.add(asset);
asset.on("load", function (asset) {
var material = self.entity.model.meshInstances[targetMaterial].material;
material.diffuseMap = asset.resource;
material.update();
});
this.app.assets.load(asset);
};
if i’m running this it all wors fine
but if i remove the line targetMaterial = 9; and assign 9 in the editor i get an error that material cannot be found.
printing targetMaterial yields undefined.
why? why didn’t it read the number from the scene?
He was creating a new PlayCanvas texture object that requires the graphics device object to be passed in. (See API reference: https://developer.playcanvas.com/en/api/pc.Texture.html). His way didn’t make use of the PlayCanvas asset system or registry.
I would say that Dave’s method would be the preferred method IMO.
Given the age of the post, perhaps the function didn’t exist then? Or maybe it doesn’t handle CORS?