Targeting HTML5 in OpenFL is easy, however, I could not add glowing effects to sprites, I am thinking of a work around, that is using JavaScript library to add webGL effects to the sprites in Canvas.
But, the question is, how would I access the sprites inCanvas using JavaScript? and what tool to use to inspect sprites in Canvas ?
First of, since version 4.0 openfl uses webgl renderer by default and adding glow effect in that case requires a 'deep dive' into openfl/lime source code and i can't give you that.
But if that's suitable for you, force openfl to use canvas fallback with
<haxedef name="canvas"/>
and then you can create custom Bitmap class (for example) with glow effect like so
import openfl.display.Bitmap;
import openfl.display.BitmapData;
import openfl.display.PixelSnapping;
import openfl._internal.renderer.cairo.CairoBitmap;
import openfl._internal.renderer.canvas.CanvasBitmap;
import openfl._internal.renderer.dom.DOMBitmap;
import openfl._internal.renderer.opengl.GLBitmap;
import openfl._internal.renderer.RenderSession;
class HackyBitmap extends Bitmap
{
/**
* Custom property for tweening
*/
public var glowBlur:Float = 0.0;
public function new(bitmapData:BitmapData=null, pixelSnapping:PixelSnapping=null, smoothing:Bool=false)
{
super(bitmapData, pixelSnapping, smoothing);
}
public override function __renderCanvas (renderSession:RenderSession):Void {
var context = renderSession.context;
if (glowBlur > 0)
{
context.save();
context.shadowBlur = glowBlur;
context.shadowColor = "white";
}
CanvasBitmap.render (this, renderSession);
if (glowBlur > 0)
{
context.restore();
}
}
}
Usage
var data = Assets.getBitmapData("img/berry.png");
var hacky = new HackyBitmap(data);
hacky.x = hacky.y = 20;
addChild(hacky);
//to animate glow property
Actuate.tween(hacky, 1.0, { glowBlur: 50 }).repeat().reflect();
OpenFL/Lime versions
lime 3.2.0
openfl 4.2.0
How it looks
As said in my comment, Sprites don't exist in JS/HTML, it's an abstraction on top of Canvas that ends up calling .drawImage, thus, you won't find it in any browser developer tools. The only way you can 'access' these sprites is just by using what OpenFL provides - your sprite objects, BitmapData, etc.
The method you tried to get a glow was probably through the GlowFilter class, which is wrongly described as 'Avaliable on all platforms' in the docs. This class isn't implemented with the Canvas element yet, but could have been.
However, WebGL exists for OpenFL, it isn't all canvas. That's why shaders are possible. There is a sort of glow filter for webgl, inbuilt into openfl, first shown in this commit of this pull request. So using shaders might be your best bet.
Unfortunatly, shaders don't work with Canvas. I feel like doing glows in canvas would be your best approach, but it's not yet implemented.
Related
Goal
I'm stuck since yesterday with an issue on modifying a JeelizFilterFace example. My goal is to create my own filters, so I started the the luffy's hat tutorial, which explains that : https://jeeliz.com/blog/creating-a-snapchat-like-filter-with-jeelizs-facefilter-api-part-1-creating-your-first-filter/
Quick description of the problem
My problem is simple : I can't have the glTF example working with glTF models. It always show me a black shape, without the texture.
Details of the problem
The tutorial explains that the model have to be generated with a Blender exporter addons, in order to create the json file which is the model. But the Blender exporter is not supported anymore.
This is why I try to use ThreeJS with the GLTF loader (which is the best solution according to all the tutorials).
My problem is that I can't see any texture on any of my models, when I load it with JeelizFaceFilter/Threejs. I only have the black shape.
Here is what I did :
First, I did all the tutorial to be sure I can run the FilterFace tool, except for the exporting model from Blender part. So, I just copied the exported resources from the Jeeliz repo. The FilterFace works well : the hat is visible, with the texture and I can play with the THREEJS params.
Because I couldn't export the JSON from blender, i wanted to try to use the GLTF 2.0 model, I tried this model, which is working in the gltf-viewer tool (see picture below) : https://s3.eu-west-3.amazonaws.com/com.julianlecalvez/LuffysHat.zip
So far everything seems ok, but when I try to use this glTF loader example in the glTF demos (https://github.com/jeeliz/jeelizFaceFilter/tree/master/demos/threejs/gltf_fullScreen), it displays my hat in black. I have the good shape, but no texture (or no light?). I just replaced the model URL in this file. And I'm not even sure that the default model (the helmet) is displaying any texture.
I tried with a model from SketchFab, and I have the same : Black shape, no texture.
I put here the code to init the view, when I was trying to redo it outside of the demo file :
let init_view = function(spec) {
const threeStuffs = THREE.JeelizHelper.init(spec, null);
const SETTINGS = {
gltfModelURL: 'objects/luffys_hat_gltf/luffys_hat.gltf',
offsetYZ: [1,0],
scale: 2.2
};
// const loader = new THREE.GLTFLoader();
const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load( SETTINGS.gltfModelURL, function ( gltf ) {
gltf.scene.frustumCulled = false;
// center and scale the object:
const bbox = new THREE.Box3().expandByObject(gltf.scene);
// center the model:
const centerBBox = bbox.getCenter(new THREE.Vector3());
gltf.scene.position.add(centerBBox.multiplyScalar(-1));
gltf.scene.position.add(new THREE.Vector3(0,SETTINGS.offsetYZ[0], SETTINGS.offsetYZ[1]));
// scale the model according to its width:
const sizeX = bbox.getSize(new THREE.Vector3()).x;
gltf.scene.scale.multiplyScalar(SETTINGS.scale / sizeX);
// dispatch the model:
threeStuffs.faceObject.add(gltf.scene);
});
// CREATE THE CAMERA
THREECAMERA = THREE.JeelizHelper.create_camera();
}
I'm pretty new to aframe and the ECS-modeling technique, so I probably didn't fully grasp how the architecture should be used.
I want to model something like a robotic arm: in a simplified version that is a base, on top of that a rotator and the arm itself. The model is loaded from a single json-file and consist of several nested objects for the different parts.
How would something like this be implemented in aframe if I want to be able to control the different degrees of freedom independently (which means setting object.rotation-values on the different childs of the object itself)?
One thing I thought of was to implement the loading of the model-file as one component and each degree-of-freedom as a seperate component. So basically something like this:
<a-entity robot-model="..." base-rotation="123" arm-pitch="10" />
Or would it be a better way to use registerPrimitive for something like this?
My first take on it looks like this:
registerComponent('robot', {
schema: {type: 'asset'},
update() {
// - load and parse model using THREE.ObjectLoader
// - once ready, assign property this.parts with the various
// parts of the robot-arm
}
});
registerComponent('dof-1', {
schema: {type: 'number'},
dependencies: ['robot'],
init() {
this.robot = this.el.components.robot;
},
tick(t, dt) {
if (!this.robot.parts) { return; } // not ready yet
// update values (left out here: acceleration etc)
this.robot.parts.dof1.rotation.x = this.data;
}
});
// more parts / dof implemented likewise
I'm assuming you've already created and rigged a 3D model using software like Blender, Maya, or Cinema4D. If not, the article Animation from Blender to three.js is a good starting point.
Once you've done that, you can import the model into A-Frame with any format that supports skinning/rigging. THREE.ObjectLoader (.json) or THREE.GLTFLoader (.gltf) are good options, and there are already A-Frame components that wrap these loaders. Assuming you're using JSON and the object-model component from A-Frame Extras, you could do:
<a-entity object-model="src: url(my-model.json)"></a-entity>
At this point you should see a model in the scene, without having written any JavaScript, but it won't be animating yet. If you know what animation you want up front, you can create the animations in keyframes or morph targets using the same modeling software: Blender, Maya, or Cinema4D. Assuming you included the animations when you exported the model, you can use the animation-mixer component (also from A-Frame Extras) as follows:
<a-entity object-model="src: url(my-model.json)"
animation-mixer="clip: *;"></a-entity>
This will play all animations at once. You could use a clip name, instead of *, to play a specific animation.
If your animations need to be computed at runtime, and can't be baked into the model, you'll need to write a custom component. This gets complicated quickly, but the basics aren't too bad:
<a-entity object-model="src: url(my-model.json)"
custom-animation></a-entity>
And the JS:
AFRAME.registerComponent('custom-animation', {
tick: function (t, dt) {
var mesh = this.el.getObject3D('mesh');
// With complex models, you may need to loop over `mesh.children`
// in case the mesh you want to animate is a child of another
// object in your model file.
if (!mesh || !mesh.isSkinnedMesh) { return; }
mesh.traverse(function (node) {
if (node.isBone && node.name === 'arm') {
node.rotation.x += dt * Math.PI / 1000;
}
});
}
});
I have a Button (Canvas>Panel>Button) with a complex image (is not square), the issue here is that I want it to execute the on click event when i click on the IMAGE (excluding parts of the image with no opacity) but since the new UI doesn't work with colliders I can't achieve the same click behaviour that could be achieved with a polygon collider, and its feels completely wrong to click outside the button (image) where the alpha is cero (0) and still execute the click events..
I hope my problem is clear enough and someone can help me, thanks in advance.
I found a solution, Unity should have an option to achieve this but at least this works perfectly: http://forum.unity3d.com/threads/none-rectangle-shaped-button.263684/#post-1744521
I found another (probably better) solution for this problem. I used a Collider2D (PolygonCollider2D) to define the clickable shape and then used this RaycastFilter:
using UnityEngine;
using UnityEngine.UI;
[RequireComponent (typeof (RectTransform), typeof (Collider2D))]
public class Collider2DRaycastFilter : MonoBehaviour, ICanvasRaycastFilter
{
Collider2D myCollider;
RectTransform rectTransform;
void Awake ()
{
myCollider = GetComponent<Collider2D>();
rectTransform = GetComponent<RectTransform>();
}
#region ICanvasRaycastFilter implementation
public bool IsRaycastLocationValid (Vector2 screenPos, Camera eventCamera)
{
var worldPoint = Vector3.zero;
var isInside = RectTransformUtility.ScreenPointToWorldPointInRectangle(
rectTransform,
screenPos,
eventCamera,
out worldPoint
);
if (isInside)
isInside = myCollider.OverlapPoint(worldPoint);
return isInside;
}
#endregion
}
Using a collider for this is a bit hacky but the result is much simpler, probably faster and makes it much easier to adjust the clickable shape.
This could be improved by creating a custom alternative to replace the Collider2D but that's a bit too much work for what I need.
I read that the latest threejs exporter added support for multiple animations so I created a quick experiment and exported a model with the latest plugin..after a bit of playing around with the code I managed to get each of the animations within the model playing, however the geometry is getting skewed horribly.
I'm pretty sure the issue is related to the following error: "gl.getProgramInfoLog() WARNING: Could not find vertex shader attribute 'position' to match BindAttributeLocation request." but not positive. Maybe I'm just not aware of something, such as a particular blender export flag configuration or something else that needs to be set within the code. Here's the important parts:
for (var i = 0; i < materials.length; i++) {
var mat = materials[i];
mat.skinning = true;
}
scene.add(mesh);
// add animation data to the animation handler
var animations = [];
for(var a in mesh.geometry.animations) {
THREE.AnimationHandler.add(mesh.geometry.animations[a]);
var animation = new THREE.Animation(mesh,mesh.geometry.animations[a].name);
animations.push(animation);
}
animations[0].play();
Any ideas guys? Here's a screenshot: https://drive.google.com/file/d/0B6zdGNflpdJLSVVHemszWWFTTHc/edit?usp=sharing
I need to change the transparency of a file. Dae (collada), by my code with the library Three.js with dat.gui. I'm using:
$gui = new DAT.GUI();
gui.add(opacity_pele, 'pele').onChange(function(){
if ( opacity_pele.pele ) {
material[pele].transparency = 1.0;
} else {
material[pele].transparency = 0.0;
}
});
gui.close();
Have you tried seting the transparency right in your 3D editor program?
E.g. in Blender you can adjust the transparency of your object on the panels (please see below). I'm using this method for displaying transparent objects and this works perfectly for me.