Jump to content

Canvas2D Main Post


Nockawa
 Share

Recommended Posts

Ok, some update about Scale9Sprite

It can be used with SpriteAtlas/Sheet, whatever the name you use to describe a single texture containing many sprites to display.

For a picture like this one: 

H40VVlM.png

 (please note the red frame is just a representation of the Scale9's box area described by the scale9 setting in the Sprite2d constructor below, it doesn't not appear on the actual picture)

With the following code:

var sprite = new BABYLON.Sprite2D(texture, {
    parent: canvas, id: "sprite1", x: 100, y: 100, invertY: true,
    //scaleX: 2.0,
    //scaleY: 1.5,
    size: new BABYLON.Size(500, 200),
    scale9: new BABYLON.Vector4(122, 18, 169, 39),
    origin: BABYLON.Vector2.Zero(),
});

To enable the scale9 you have to set the scale9 setting which defines the left/bottom right/top corners of the box that will scale.

You can either use size or scaleX/Y to specify the size of your sprite in the Canvas. If it's scaleX/Y the final size will be based from the initial sprite's bitmap size.
In this case the initial sprite is 184x127 but I want it to be 500x200 in the Canvas.

For the code above, you have this result:

OJ9aG9K.png

A Scale9Sprite is rendered with two triangles, the computing of the texture's UV is made in the Fragment Shader to take into consideration of the Scale9 setting, so it's fast, there's not 18 tri and of course if you use a TextureAtlas and render many sprites using this texture, it will be done in one Draw Call if Instanced Array is supported on your web browser.

I will commit this shortly and work on TexturePacker right after, using the JSONArray DataFormat.

If you have comments/feedback about this feature, they're welcomed.

Link to comment
Share on other sites

33 minutes ago, MasterK said:

scale9: new BABYLON.Vector4(122, 18, 169, 39),

i think (0-1) is better. normal situation (0.5, 0.5, 0.5, 0.5) is ok.  estimate is enough.

 otherwise i should check picture size, very trouble.

Disagree here; pixel art is created with pixel-integer resolution, then converted to real numbers on rendering in GL. It seems unorthodox to have to convert from pixel to real numbers for artwork, but accuracy should be more desirable.

Link to comment
Share on other sites

Hi People,

Long time that I didn't develop new features but here we go:

You can play with the following PG:

Of course you can use Scale9Sprite for a Sprite generated from an AtlasPicture.

So @grayger @BitOfGold @jpdev and @MasterK you should be interested about these.

If anybody have question/feedback about these feature, please create dedicated forum topic and mention me, thanks.

Link to comment
Share on other sites

46 minutes ago, AlbertTJames said:

Hey guys, 

 

I recently got back to coding using Babylon, and updated the version using NPM. But the canvas2d file is not there, would it be possible to add it to the npm ?

 

Thanks !

A PR was submitted and merged to include it, but I don't think we rebuilt a package since. Maybe @Deltakosh or @RaananW can help about this.

Link to comment
Share on other sites

Hello people,

Few announcements:

  • We can now use BMFont to render text with Text2D PG here the documentation of the Text2D was update to explain the different techniques you can use to render text (normal, Super Sample, Signed Distance Field, BMFont) and which one you should use. (Thanks @MasterK for the idea and help)
  • There's a new page about how the Rendering is working, it will help people to understand how to get transparent sprites, for instance. (this page is currently only accessible by the link I gave before, because I've messed up the link in the Canvas2D Homepage, yeah, that's my special ability, DK loves it)
  • Some new Playgrounds are available at the bottom of the Home Page
  • I was ill during the release of the 2.5, so I couldn't update the doc and the what's new, so I've updated the what's new of the documentation web site, go take a look if you want. As a separate module, Canvas2D has its own section in the What's New.

So what now? Well, I try to recover from illness and not going back sick again, so I'm starting to code again, slowly... But I'll do the following things (in order, I guess)

  1. WorldSpaceCanvas with node tracking and billboard ability, for mister @royibernthal
  2. Primitives Intersection Manager for @ller the goal will be to provides at each render a list with for each entry two primitives that intersect. This manager will serve as the foundation for intersection, we will discuss/design/develop more handy stuff on the top of it. If you have idea/feedback/requirement, you can start a topic and mention me! :)
  3. I will try (but I should succeed) to develop a feature to clip the content of a Group2D, apparently it won't be harder to use a Shape as the Clipping geometry (if no shape then the whole rectangle surface will be used) to get more fancy stuff. But @MasterK and other, you will finally be able to develop scroll-view without relying on hacking! I was reluctant to develop this feature not because of its complexity (it's not a walk in the park anyway), but because if it's overused the performances may drop. But well, it has to be done and maybe the perf won't be that bad. For those who are familiar with the Canvas2D Architecture a Group2D that will Clip its content will be turned into a Renderable Group2D and basically I will draw the clipping geometry to the stencil buffer, then I'll draw the Group2D's content with a stencil check to clip away the pixels that are out of the geometry. So in theory: not hard to code...But there are so many cases, rendering types, that well...Future will tell!
  4. I will resume the work on the GUI Lib, I'm motivated as ever to make a good one!

Cheers!

Link to comment
Share on other sites

15 hours ago, MasterK said:

nice...

and you didn't say shadow and stroke of text2d... that's common too~~

and multiple color in text... and word-break...

then all hacking will be covered by your official code~~

I'm accepting PR from people, specially the ones I've spent countless hours to dev/fix bugs for them ;)

Link to comment
Share on other sites

10 hours ago, MasterK said:

I can say nothing...:ph34r:

But i know that's your joke~ you'll do them yourself right? hahaha....

If you have hacks that work, It might not be that difficult for you to clean your code up and integrate them to the framework.  When you submit a PR they can give you comments and suggestions.  

Link to comment
Share on other sites

On 2017/1/13 at 8:03 PM, adam said:

If you have hacks that work, It might not be that difficult for you to clean your code up and integrate them to the framework.  When you submit a PR they can give you comments and suggestions.  

i use pure js. not ts. so it'll be some difficult to do these.

and @Nockawa will code better than me and it won't take him much time to do these. i have gave him all my code, if he need read.

i told that he was joking.

Link to comment
Share on other sites

@Nabroski please create a dedicated topic.

But to answer your question, there's nothing about Canvas2D which makes it work, see here: http://www.babylonjs-playground.com/#1H7ZZH#4

Why does it works, well, it's specific to the bjs' pipeline: the scene is render, then you use this render to map a plane afterward, i guess.

Link to comment
Share on other sites

Hello people, here a little update.

WorldSpaceCanvas TrackNode feature

So I've developed the feature requested by @royibernthal to create WorldSpaceCanvas that track a 3D Scene Node with the optional feature for the WSC to always face the camera (billboard mode). You can find a demo in this playground.
It was truly missing to the whole "WorlSpace Canvas interacting with 3D Scene" scenario. Other users requested more about this specific scenario and it perfectly makes sense: C2D was develop to provide 2D support for the 3D Scene, I've been focus on the "2D stuff" by itself a lot, because, well, it's already a big task, but yes there should be more things to come on this area, I'll try to dev feature requests on this matter with a higher priority.

 

Primitive Collision Manager (PCM in short, work in progress)

TL;DR Primitive intersection is not easy/fast to code so it will take time. I have to introduce a breaking change in BoundingInfo2D to make the extent a Vector[2] to express an OBB instead of an AABB. I have to change the code using BoundingInfo2D transformation to rely on Vector2/number/Vector2 (Trans, Rot, Scale) instead of Matrix. I have to introduce an API to provide a Triangle List representation of a Primitive in order to develop a complete and accurate Prim vs Prim intersection algorithm. This will take time, as always, unplanned time...


It's unusual that I talk about a feature before it's done, but I wanted to share the progress and also some "discoveries" I've made...
You can see the in the screenshot below 150 primitives with 25 of them moving/rotating, all of them were created with a setting that make them Actor of the PCM. The blue box around them is the WorldAABB (AABB stands for Axis-Aligned Bounding Box), the dark pink cells are the PCM's Clusters.
I didn't want to make a very complex Collision Engine, so basically what I did is splitting the canvas into 2D Areas of the same size called "clusters", the number of clusters on horiz and vert will vary through time in order to respect a rule: there can't be more than 10 prim in a Cluster or less than 7 (numbers was empirically chose). When a Prim is moving, changing size or switching from hidden to visible then I compute in which cluster(s) it appears. This computation is quite fast. I will also tag this prim to recompute the list of the other prim (well, I should say "actor") it intersects with.
Then for all the prim that changed, I compute the intersection: for a given prim I build the list of all the other prim that are in the same cluster(s) and I make an intersection test with their respective WorldAABB (which is computed only when needed).
This is actually pretty fast: 0.25ms for the 150 prim with 25 moving, if 0 are moving/changing it would be 0ms because I keep all the intersection in a persistent manner.

So ok, if you're still here after all this talk (thank you for your effort!), here what I wanted to share:
Developing Canvas2D, like many "big" engine/library was at the beginning dealing with developing 20 little/medium things at the same time, with more or less care, because you can't focus on everything with the most care, you should in theory, but concretely: it's not possible (at least for me). When I came to the situation where I needed to deal with a Bounding Info object for a Primitive (I believe for interaction to build a list of all prim under the pointer, using the Bounding Info for fast rejection), I didn't think much and I came up with this kind of data:

  • center (Vector2): which is the computed center of the prim's bounding object
  • radius (number): a bounding circle where all the prim fits into, the circle's center is the center property above
  • extent (Vector2): an offset on the X and Y axes to get a corner of what would be an AABB in the local frame of reference of the prim.

The extent was I believe a mistake, storing an AABB at this level was fine, but the mistake is when I developed the transform() method to transform the BoundingInfo2D object with a matrix, the result being stored in another BoundingInfo2D object so in another AABB. It's a mistake because transforming an AABB is slower than transforming an OBB (Oriented Bounding Box). To transform an AABB you have to recompute the 4 corners of the box using the center and extent, then transform the 4 points with the matrix and then create a new AABB out of it. It's slow and you also loose precision, the resulted AABB will be bigger. On the other hand with an OBB all you have to do is translate the center, apply rotation/scale on the extent (which is 2 Vector2) and it's better to transform an OBB with a Vector2 (translation), number (Z Rotation), Vector2 (scale) rather than a matrix that you would be forced to decompose to extract these values...

Why am I realizing this now!? Because before I was fine with AABB transformation, I would down the road make a perfect point intersection with the Primitive (which was easy for sharp Rect2D, Ellipse2D, Sprite2D, Text2D, medium for Rect2D with round corners and definitely hard for Lines2D. Note that both Sprite2D and Text2D are considered as a rectangle...), point intersection always takes place in the local frame of reference of the BoundingInfo2D object, we applied an inverse transformation of the Prim's globalTransform matrix to the point: it's fast and convenient.
But now I'm no longer dealing with point, but with "another prim". There's no point to work in local frame of reference but we have to work with the frame of reference both prim share: the canvas' one. As stated above, most of the prim are shaped like a rectangle, the perfect representation is then dealing with OBB, it's a rectangle which can be oriented (so rotation applied due to transformation would be easy and possible).
I honestly don't plan to develop for the first release of the PCM dozen of intersection routines to support any kind of prim versus any kind of another prim. (e.g: Lines2D versus Ellipse2D, Ellipse2D versus RoundRect, Rect versus Sprite, etc.). So if I want to release something acceptable, not accurate, bu acceptable, my plan is to support two kind: OBB and Ellipse, that would covers: Rect2D (with an approximation when Round Corner is used), Ellipse2D, Sprite2D, Text2D, but not Lines2D...Oh, by the way, I've just realized that I forgot to mentioned that I've created a new kind of Prim: WireFrame2D: all the blue box are stored in one of this prim, same for the Clusters (I've could I have used one prim to store both of them, but the debug settings are separate, so...). Lines2D and WireFrame2D wouldn't operational for PCM (and WireFrame2D won't be for point intersection to at first).

If I wan to support all cases, then a possibility is to rely on an intermediate representation of a prim: using a triangle list. If any kind of prim can be converted in a tri list, then the intersection is just a matter of intersecting two set of triangles....Which is what I should do down the road because:

  1. That would be the way to support Ellipse2D, because the physical shape of the Ellipse is a triangle decomposition (using the subdivision setting), so using a perfect ellipse wouldn't be accurate in this case.
  2. That would be the way to support Lines2D: I already have a tri list for point intersection.
  3. That would be the way to support WireFrame2D, because we usually specify a intersectionThreshold (because selecting one pixel is hard!) which gives us no choice but to express a line's segment using a quad (then two triangles).

One could think I'm already creating these triangles for RoundedRect2D and Ellipse2D, but truth is: it's made by the Vertex Shader on the fly, triangles are not stored on the JS side in memory...The point intersection being fairly easy to solve without relying on a triangle list.

A whole journey in itself, thanks @ller ! :D

primIntersection02.png

Link to comment
Share on other sites

Hello everybody,

Some updates:

Primitive Collision Manager (PCM, @ller request) 

The PCM is finally done! Well, first release, I've already spotted some not supported cases... Anyway, you can check a PG demonstrating the feature here: http://babylonjs-playground.com/#1PXWLR#2 (I've commented the PG for you to see how it works)
Turned out that I didn't do what I wrote in the previous message, I didn't check for OOB and I've implemented a generic triangle set versus triangle set intersection algorithm right away.
Basically all primitive types now create/update a Tri2DArray which contains a list of triangles describing the primitives surface. It needed to be that way because an Ellipse with a intersection of 8 is graphically not shaped like a perfect ellipse: there's not enough polygons, so I couldn't use a intersection algorithm involving a true/perfect ellipse, same goes for the Rectangle2D with round corners. So I decided to go for the most generic and accurate way.
All primitive types are supported except the new WireFrame2D one.

Through the PCM object you have a list of all primitives intersecting with the Canvas' border (if you activate the feature), it's useful. You also have a list of all the pair of two colliding primitives.
From a given prim you have the intersectWithObservable and intersectWith properties to get notified of new/removed intersections and to access the full list of them.

New Text Alignment (vertical and horizontal) and word wrapping features for Text2D (coded by @adam, I'm very thankful to him! It's good to feel less alone on this whole coding...)

Basically now you can set a left/center/right text horizontal alignment and a top/center/bottom for the vertical one.
If you specify a size for your Text2D primitive you can now have auto word-wrapping if the line exceed the horizontal limit.

Maybe @adam could share a PG demonstrating the feature! :)

New Primitive Type: WireFrame2D

Well, I needed it to draw the debug World AABB and Cluster of the PCM, so I wrote it. The Primitive accept many WireFrameGroup2D, each one having a default color and contain a list of lines. Each stored vertex has its own color.
Basically you create a WireFrameGroup2D instance then use its method to fill it with vertices. Note: it's Line List, not line strip: each line is defined by two own vertices. You can use an API to start, fill, end a LineStrip but internally it will double the vertices for everything between the first and last vertex.

Right now this Primitive doesn't support any kind of intersection (point or prim-prim), I'll add an intersectionThreshold and implement the algo any time soon...It's not a priority right now...

Misc things

  • The BoundingInfo2D now support a WorldAABB with an efficient dirty/update, I obviously needed it for PCM
  • Each Prim Instance has now a uid property which is a unique id (a GUID), I use it as a key to store the prim or prim related data into a StringDictionary, it's an efficient way to retrieve a given prim without going O(n).
  • There's a Triangle versus Triangle intersection method in the Math2D.ts file, its implem is slow. If someone has the code for a Tri-Tri in 2D implemented using the Separating Axis Theorem (SAT) algo: I'm in !

What's next?

  • I will update the doc in the next few days with more PG and explaining the latest implemented features.
  • Fix the TrakNode bug reported by @royibernthal asap.
  • Well, the highly awaited Group clipping/masking feature. I won't have time to work most of the next week, so don't expect it soon.
  • Then I'll certainly make a break on C2D (except for bug fixing) to finally get back at the GUI coding!
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...