Why is my context.getImageData() call illegal? - html

I have been playing around with a very simple HTML5/Canvas based drawing app, just for the browser. I am setting it up as a proof of concept to play around with different programmatic drawing effects and such. However, I running into an issue, namely a SecurityError, when I try to grab the ImageData from the canvas 2d context.
Now, I know all about the security issues with cross-browser content and running on a webserver with local content and all that. This is not my issue. I am using no images. And the weirder thing is that I can grab the ImageData in some places in my code, but not others. Specifically, not within a function, which is where I want to.
Here is a fork of my code:
http://jsfiddle.net/grimertop90/77Z42/
Feel free to play around, and try drawing on the canvas.
(Note: I have been developing in Chrome and it works fine, but I just tried running it in Firefox and it seems to have issues. For my purposes, please just check it out in Chrome.)
If you look though the JavaScript, you should see three points marked "Case 1", "Case 2", and "Case 3". These are the three points in my code where I have attempted to grab the canvas's ImageData. Cases 1 and 3 work; Case 2, the important one, does not. Case 1 is during initialization. Case 3 is upon a user's button click. Case 2, the broken one, is fired when a certain number of points have been drawn on the canvas.
I have no clue what the issue might be, especially since it work in 2 out of 3 places.

Your code works fine, your only problem are the missing arguments in the arcSketch call. Currently you have:
if (points.length >= 100) { arcSketch(); }
Just change it for
if (points.length >= 100) { arcSketch(x,y); }
You were trying to call ctx.getImageData(Nan, Nan, 200, 200) which was throwing the error.
You can see it working here

Related

Changing materials in Forge

We are currently making the client retrieve the object states when the page loads (which will cause the 'pending' objects in the model to turn into different colors). Then we poll for changes to update the coloring (Firstly: pending object gets colored when the viewer loads, and then we keep polling to check and change state again, to make Forge render those in a different color and store their old color/material. When the polling received a change that an object should no longer be colored, it tells Forge to use the old color/material again.
The problem:
We've found out what the problem is, but we couldn't find out how to fix it. The problem is that changing materials in Forge doesn't work after startup anymore, it only works in the first ~3 seconds or so (the materials were used to show the colors).
However, setting overlays works even after the first ~3 seconds, (showing overlays instead of materials to show the colors).
This is not what we want to achieve. This looks unoptimized, because overlays will be shown through everything.
The materials, however, seem to be 'locked', as in, they cannot be changed anymore after the first ~3 seconds. It seems like they aren't refreshed or something
In the examples, we found they used viewer.impl.invalidate(true) to refresh the Forge viewer, but that doesn't do anything after ~3 seconds.
We've also tried every combination of viewer.impl.invalidate(true, true, true) as well as setting material.needsUpdate to true, as well as trying to re-render the entire scene.
We also found this: https://github.com/mrdoob/three.js/issues/790, but we couldn't find a good way to do that in Forge, we tried viewer.requestSilentRender() but that didn't do anything either.
Anyway, we've tried everything we could come up with and could find online to make the materials work, but nothing made a difference.
We are looking to find someone that's more experienced with how Forge works that can see what the material code is doing wrong.
As for the content, here is all the code you will need to understand what is happening:
DROPBOX LINK
And here is a small part of the "index.html" file that sets the color:
try
{
viewer.restoreAllColorOverlays(); //for materials instead of overlays: viewer.restoreAllColorMaterials();
$.each(colors, function(color, selectionIds)
{
viewer.setColorOverlay(selectionIds, color); //for materials instead of overlays: viewer.setColorMaterial(selectionIds, color);
});
}
catch(error)
{
console.error(error);
}
I have no idea how you implement your app, so I only tell what I found in your codes. If you want to resolve the issue you addressed, you can consider providing a reproducible case demonstrating that, I will gladly pass it to our dev team. Those following items should be in the reproducible case:
A short exact description of what you are trying to achieve. The behavior you observe versus what you expect, and why this is a problem.
A complete yet minimal sample source model to run a test in.
A complete yet minimal Forge app that can be run and debugged with a simple procedure to analyze its behavior lives in the sample model.
A complete yet minimal pure three.js app that can be run and demonstrated the shader effect you want. Note. Forge Viewer is using r71 three.js.
Detailed step-by-step instructions for reproducing the issue, e.g. which element to pick, what command to launch etc.
If your reproducible case could not be posted here publicly, please send it to the forge.help#autodesk.com and remove sensitive data or information before you send.
=== Something I found in your codes:
I found here are some wrong types and missing actions in your ColorMaterial extension. The color property of an material should the a type of the THREE.Color. Here is my modification:
Autodesk.Viewing.Viewer3D.prototype.setColorMaterial = function(objectIds, color)
{
if( !(color instanceof THREE.Color) ) throw 'Invalid argument: Color';
var material = new THREE.MeshPhongMaterial
({
color: color,
opacity: 0.8,
transparent: true
});
viewer.impl.matman().addMaterial( 'ColorMaterial-' + new Date().getTime(), material, true );
// ...........
};
Its' result is here:
In the ColorOverlay extension, The type of material color property is also wrong, it should be a type of THREE.Color, too. Changing it into THREE.Color should work fine. In addition, overlay is covers on 3D objects, so you should call viewer.hide() with your setColorOverlay() together. Otherwise, it won't look like a transparent object.
Without hidding 3D object of the wall:
hide 3D object of the wall:

THREE.js - morphTargetInfluences on an imported JSON mesh not getting results

I have a basic three.js scene in which I am attempting to get objects exported from Blender (as JSON files with embedded morphs) to function and update their shapes with user input.
Here is a test scene
http://onthez.com/temphosting/three-js-morph-test/morph-test.html
The slab is being resized without morphs by simply scaling a box, which is working just fine.
I must be missing something fundamental with the little monument on top. It has 3 morphs (width, depth, height) that are intended to allow it to resize.
I am using this code to implement the morph based on users dat.gui input.
folder1.add( params, 'width', 12, 100 ).step(1).name("Width").onChange( function () {
updateFoundation();
building.morphTargetInfluences['width'] = params.width/100;
roofL.morphTargetInfluences['width'] = params.width/100;
roofR.morphTargetInfluences['width'] = params.width/100;
building.updateMorphs();
});
The materials for building, roofL, and roofR each have morphTargets set as true.
I've been going over the three.js examples here:
http://threejs.org/examples/?q=morph#webgl_morphtargets_human
as well as #webgl_morphtargets and #webgl_morphtargets_horse
Any thoughts or input would be much appreciated!
I believe I've reached a solution for my question I was under the impression that the JSON loader was preserving the morph target names to be used in place of an index number with morphTargetInfluences
something like morphTargetInfluences['myMorphTargetName']
but, after closer inspection in the console it seems like they should be referred to by number like morphTargetInfluences[0]
Not the most intuitive, but I can work with it.

Cocos2D-X nodes loading in wrong positions have RemoveAllChildren()

I'm only using one scene object for my entire 2d sidescrolling platformer with two layers: There is a hudLayer for the controller, and the gameLayer for everything in the game.
When I control my character to walk into a door (sprite with a physicsBody that has a callback that takes me to the next level), the next level loads by these instructions:
remove all event listeners
stop all actions for both layers (the gameLayer typically has been doing a Follow action that follows the player, and is limited to the size of the backgroundSpriteNode)
remove all children from the gameLayer
set gameLayer position to Vec2(0,0)
load level 2 (a complete copy of what level 1 should look like... load the background sprite to gameLayer, playerSprite, add event listeners)
add event listeners back to the hudLayer
The only problem is that for whatever reason, the level only partially loads the way it should... For instance, coins appear in the spots they should, but platforms don't seem to. Neither that or the player, or other characters. Not sure really why these objects are specifically not loading in the correct positions, but maybe someone who has experienced this sort of problem before can help?
Most nodes (such as platforms) are appearing below the bottom of the screen when they should be fully shown at the bottom of the screen. Characters are appearing down there too when they should be appearing above the platforms.
P.S. After testing a bit more, I've come to realize that SOMETIMES some of the platforms are loading in the correct positions, but sometimes they aren't. Not sure why. A fix for this may be to load things one at a time with a delay between them. But I'd rather not have to put delays and just figure out what the deal is.
Figured it out: for whatever reason, I needed to add a delay in there. I think for whatever reason, by calling removeAllChildren(), something got messed up with the positions. It was my suspicion since SOME of the time, parts of the next level would load, but only some parts, and only sometimes.
Here's the code I added to run an action on the gameLayer once all children were removed, etc...
runAction(Sequence::createWithTwoActions(DelayTime::create(0.1), CallFunc::create( [&] ( ) {
loadLevel2(this);
})));

Transparency issues with 3d particles and 3d models, libgdx

I got some strange issues with transparency and 3d particles. A short vid to illustrate:
https://youtu.be/ZHKI1X3MjhY
As you can see I have a 3d particle effect, fire burning. Inside it is a 3 model with no alpha blending and it shows just fine. then in the far distance there is a small skeleton (with blending and alphatest turned on) and it also shows just fine through the fire. Then I turn camera and look at the warrior skeleton and it just disappear and instead you see what is behind him. I turn camera again and the mage skeleton also vanishes, but you can see the trees a bit further away just fine and they have the exact same settings for blending and alpha test. If I move the character say 20 yards away it also starts showing through the fire effect.
So it seems to have something to do with distance from the 3d particle effect...
The 3d particle batch is an extended BillboardParticleBatch like this:
protected Renderable allocRenderable(){
BlendingAttribute ba=new BlendingAttribute(GL20.GL_SRC_ALPHA, GL20.GL_ONE,1f);
Renderable r = super.allocRenderable();
r.material = new Material( ba,
// new DepthTestAttribute(GL20.GL_LEQUAL, 0.0f, 0.5f, true),
// r.material.set(new FloatAttribute(FloatAttribute.AlphaTest, 0.0f),
TextureAttribute.createDiffuse(texture));
return r;
}
All the characters and the trees are created with following attributes:
if (alpha) {
FloatAttribute floatAttribute = new FloatAttribute(FloatAttribute.AlphaTest, 0.5f);
BlendingAttribute blendingAttribute = new BlendingAttribute(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, 1f);
for (int i = 0; i < bulletEntity.modelInstance.materials.size; i++){
bulletEntity.modelInstance.materials.get(i).set(blendingAttribute);
bulletEntity.modelInstance.materials.get(i).set(floatAttribute);
}
}
The models are drawn first then the particles, I tried changing order but no difference. I have tried a lot of different setups for alphatest, depthtest and blendingattribute but can not find anything that works.
EDIT
I removed the Blending attribute from the 3d-models and now it looks as it should regarding the particle effect. However I need most materials on my character models to have blending set..
Anyone got any clue why this is happening when I enable blending?
I also tried to use the BillboardParticleBatch without extending it in case I had done something there but the effect then is even worse. All models with blending enabled appear in-front of the particle effect even though they stand behind it.
ModelBatch sorts your render calls (check this link, really, it is a must read), to avoid incorrect behavior (as you're experiencing). The actual sorting/rendering happens at the call to ModelBatch#end. By default it uses the DefaultRenderableSorter, which is a default implementation. Of course, because that implementation isn't aware of your scene, it might not fit exactly your needs.
The DefaultRenderableSorter tries to guess the location of each model based on their transformation matrix. Based on that location and the camera's location it will sort them so that:
First all opaque objects are rendered from front to back (because whatever is behind an opaque object isn't visible anyway, so that reduces unneeded calls to the fragment shader).
Secondly all transparent objects are rendered from back to front (because as soon as a transparent object is rendered then everything that is rendered after that and is behind it, will not be visible).
To decide whether an object is transparent, the BlendingAttribute#blended member is used. (So you could, if you really wanted to, set that member to false to force it to be treated (sorted) as if it was opaque)
So, the order in which you call ModelBatch#render is not necessarily the order in which they are actually executed. If you want to force to render whatever you've added to the batch in between, then call the ModelBatch#flush(). Of course, doing this a lot defeats some of the purpose of ModelBatch in the first place.
Instead you could implement your own RenderableSorter which has more knowledge about your scene and can therefor do a better job sorting than the default implementation. (however if flush() works for you and there's no other issue, then just flush might be the easiest solution for you).
That said, there a various other solutions you could try as well. E.g. the regions of the particles are fully transparent, so the fragment shader might as well discard those all together. Try adding FloatAttribute.AlphaTest with a value of 0.5f to the particles. If that messes with your blending then gradually reduce the value to e.g. 0.05f.
Also, you could add a DepthTestAttribute with depthMask set to false (new DepthTestAttribute(false)). This will prevent the particles from writing to the depth buffer. (but also might cause other things to show in front of the particles).

Example of Click Map is not working for me

Sorry by this dummy question! :D
I´m trying to make a clickable map with html5 canvas element, I find this good example: http://www.rubydesigner.com/blog/click-map-using-html5-canvas
But when a download it (CTRL+S) from Chrome it doesnt work. It download the html page and files folder with the JS a images, I checked the path to the images, but still the map doesnt appear. What is the problem?
UPDATE
Initial assumption about CORS turns out to not be the case here.
The code seemed to work in Chrome and although CORS typically is the cause when downloading files and using canvas with local (file://) file references. As localhost is used here via XAMMP this won't be the cause and it turns out there are more than one bugs in the online code.
Specifically the way it calculates the coordinates for the mouse:
var datapos = ((e.offsetY-2) * 300 * 4) + ((e.offsetX-1) * 4);
This will result in a NaN value due to offsetX/Y which of course cannot be used for any index.
The more appropriate way is something like this, here also compensating for canvas offset:
var rect = map_wrapper.getBoundingClientRect();
var datapos = ((e.clientY - (rect.top |0)) * 300 * 4) +
((e.clientX - (rect.left|0)) * 4);
However, I have never came across a floating point position for an element which seem to be case here (rect.top shows a float value in my browser, another little surprise) and therefor I am forcing the value to integer here (normally not necessarily.. I didn't dig deep into this). As debugging the whole code is a bit out of the scope here I will leave it with that and to OP to locate other bugs.
Correcting the position will at least give a usable index for the pixel array which in turn will return a valid (not necessarily correct it turns out, which leave checking of image, tolerane in case gamma/color correction is applied....) value for the red component (still issues when testing but as said, it's a bit out of the scope to do a full debug and correction).
Hopefully this can lead you to where the other errors are. I did not go through the html etc.