
Zdog – Pseudo-3D JavaScript engine for Canvas and SVG - tomek_zemla
https://zzz.dog/
======
dheera
Super-crude STL file reader I whipped up in 10 minutes:
[https://codepen.io/dheera/pen/zQJBrx](https://codepen.io/dheera/pen/zQJBrx)

~~~
ramon
nice stuff man!

------
nikkwong
So cool. I looked at a few projects and was turned off by how much code was
needed to render each result. However, when I looked closer I realized that
most of the code was simply to define the shapes in the illustration, which,
is nice, because it's not very logic heavy and means these scenes could be
whipped up relatively quickly without confusing the hell out of me. Nice! To
the author: you said you wanted to make it for a video game, would love to
hear if that idea is going anywhere because I could imagine something like
this as a game engine being super useful.

------
needle0
Remembering Dogz and digging through the Wikipedia rabbit hole, I just learned
that PF Magic [1], the developer for Dogz/Catz, were also responsible for the
SNES 3D fighting game Ballz [2], and its programmer later went on to develop
the open-ended experimental adventure game Facade [3]. I knew of the existence
of all of them but didn't knew they were all connected!

[1]:
[https://en.wikipedia.org/wiki/PF_Magic](https://en.wikipedia.org/wiki/PF_Magic)

[2]:
[https://en.wikipedia.org/wiki/Ballz](https://en.wikipedia.org/wiki/Ballz)

[3]:
[https://en.wikipedia.org/wiki/Fa%C3%A7ade_(video_game)](https://en.wikipedia.org/wiki/Fa%C3%A7ade_\(video_game\))

~~~
herbcso
Why wasn't the last one named Facadez?

------
overgard
I notice that there are some issues with depth sorting (which I guess would be
expected). It'd be complicated, but one way you could do the same effect
without that issue is to use signed distance fields in a shader:

[https://www.iquilezles.org/www/articles/distfunctions/distfu...](https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)

(Demo at the bottom of the page)

~~~
myfonj
It is addressed in
[https://zzz.dog/extras#z-fighting](https://zzz.dog/extras#z-fighting) as a
feature:

> Z-fighting in Zdog is the natural result of its pseudo-3D engine. Zdog’s 3D
> shapes are actually 2D projections, rendered without any accounting for
> collisions with other shapes. > Rather than fighting against this effect,
> the best course is to accept it. Z-fighting is one of Zdog’s charms. Embrace
> it.

~~~
reuben_scratton
This is such a glorious project. I wonder if intersecting shapes could be
detected and automatically decomposed into a set of non-intersecting shapes
that render separately...

------
ehsankia
Is it me, or that `addTo` api feels very strange. Creating new objects with no
assignments, with the side effects of adding it to an illustration.

~~~
dahart
The name is non-standard, but the concept is absolutely normal for a 2D or 3D
rendering API. You can think of the ‘addTo’ property as the item’s parent. In
3D APIs this is normally called an instance or transform node, and here the
transform is combined with the shape type. Sometimes those are separate
things, and they would each have a parent attribute. Some APIs do the
assignment the other way, by adding children to the parent. Either way, my
short answer is no, this doesn’t feel strange.

~~~
ehsankia
That makes sense, I'm just not used to constructors having side-effect, though
I can imagine wanting to skip the extra step of adding it to the illustration.
But wouldn't something like

illustration.addRect({}) look better?

~~~
dahart
Don't constructors always have side effects? That's the only reason to have
them.

I wouldn't think of this as a side-effect though, think of it as a graph
property. addTo is setting up a tree structure, the same way you might setup a
linked list. Think of the addTo property as a pointer to the parent, rather
than a side-effect.

A doubly-linked list has two pointers per node, one for next node and one for
previous. A tree node in a scene graph also has two pointers per node, one for
parent and one for child. A parent can have multiple children, and so might
arrange the children in an array. A child, however, can have only one parent.
This makes setting the parent simpler than setting a child, considering corner
cases like duplicate children.

Your suggestion is pointing at the addChild() form rather than addParent().
One of the other comments said that kind of call is available in Zdog, so
maybe you can just use that instead.

But, I wouldn't use addRect() I would prefer addChild(). A call like addRect()
is binding the type of shape and scene graph setup unnecessarily, so you'd
have to provide separate calls for each shape type.

~~~
ehsankia
> Don't constructors always have side effects?

The only side effect they should have is creating a new instance, no playing
around with some other object's hierarchy.

> think of it as a graph property. addTo is setting up a tree structure

The problem is that the hierarchy here is backwards. You usually add children
to the parent, not parent to the children. Having a link back to your parent
does help with navigating, but it shouldn't be how you "build" the tree.

When building a tree, do you think of it as building from children up to the
parent? I did see that addChild was a thing, and that makes much more sense to
me.

~~~
dahart
> The only side effect they should have is creating a new instance, no playing
> around with some other object’s hierarchy.

You might be making assumptions. The ‘addTo’ property does not imply the
constructor is touching any other object.

You might be getting confused because the name is a verb. Again, addTo isn’t
very standard naming, but what it represents is the parent property. You
should think of it as a property that can define the graph, not assume that
the name implies anything about the implementation. Even if the constructor
does do something external to the node, the implementation can change.

> The problem is that the hierarchy here is backwards. You usually add
> children to the parent... it shouldn’t be how you “build” the tree.

No, it’s bottom-up, not backwards. And bottom-up builders are common in
graphics, so I disagree with your assumption about how trees should be built.
I think of building trees from child to parent all the time, because, as I
mentioned before, it’s a simpler operation: all nodes have one and only one
parent, where nodes can have any number of children and complications managing
those children.

~~~
ehsankia
But the example calls render on `illo`, which is the parent. So at some point
the "double link" between illo and the child was created, which is a side-
effect, no?

~~~
dahart
Presumably updateGraph() and even render() can both tidy up linkages and
anything else that needs updating. The shape constructor might well have a
side-effect though, I don't know.

Hey I hear your point, this API is a little bit different. Maybe since it's
early your feedback is fully justified. Just from my perspective it didn't
strike me as "very strange", only perhaps a little bit. I don't think you're
wrong, it's just a matter of degree... which is subjective anyway, so take
this as lukewarm agreement with you. :)

------
The_Amp_Walrus
Does this library support dynamic rendering? I tried to add extra elements to
the illustration after rendering it to the canvas and it doesn't appear to
work. I might be using the API incorrectly though - is the idea that you can
use this library to produce a static model which can then be transformed (eg.
rotated), but can't be extended after the first render?

~~~
jmiskovic
Did you try to call updateGraph() after adding elements? It seems like it
should do the trick.

[] [https://zzz.dog/api#anchor-updategraph](https://zzz.dog/api#anchor-
updategraph)

~~~
The_Amp_Walrus
This was my initial attempt using an Illustration
[https://codepen.io/anon/pen/NVORrZ](https://codepen.io/anon/pen/NVORrZ)

This is my 2nd attempt using the docs you linked
[https://codepen.io/anon/pen/QRZKxy?editors=0010](https://codepen.io/anon/pen/QRZKxy?editors=0010)

What do you think - is updateGraph + render supposed to work more than once?

~~~
falsedan
No, the underlying flatgraph (which is used to generate the drawing commands)
is cached and only updated on first call. Reset it by calling

    
    
      scene.updateFlatGraph();
    

after adding new shapes, before updating the graph & rendering

(see
[https://github.com/metafizzy/zdog/blob/master/js/anchor.js#L...](https://github.com/metafizzy/zdog/blob/master/js/anchor.js#L126))

edit: made an issue
[https://github.com/metafizzy/zdog/issues/21](https://github.com/metafizzy/zdog/issues/21)

~~~
The_Amp_Walrus
Cheers!

------
anonu
Are there similar libraries for charting and plotting data? That would be
super useful for visualizing complex datasets - in a 3d space.

~~~
kejaed
I found vpython extremely helpful for visualizing an aerodynamic model of one
of our parachute systems at work

[https://vpython.org/](https://vpython.org/)

~~~
knolan
Is this something I can use locally or in Jupyter or do I have to use
GlowScript?

~~~
kejaed
This is a great question, the whole GlowScript vs. VPython thing is really
confusing and I feel presented in a complicated way on their site. It works
great in plain old Jupyter and also from plain old python. If you use it in
non-Jupyter Python, it'll launch a web server and browser to play the
animation.

~~~
knolan
Thank you, it really wasn’t clear.

------
tambourine_man
This is amazing. The examples are great and feel amost too easy.

I hope I get the chance to use it.

~~~
cstrat
Same. I kind of wish I had a need for this sort of thing.

Without this sort of library I would have zero chance of building this myself.
Amazing.

~~~
hombre_fatal
> I kind of wish I had a need for this sort of thing.

Just Do It. Over some coffee instead of loading HN.

Make a snowman. Three spheres. Progressively smaller. Make two eyes, then get
the snowman to rotate. Then add a carrot nose. Maybe two arms as extra credit.

Doesn't take long, you've dabbled enough to at least think of it if you _do_
ever need it. And best of all, you've replaced idle consumption with creation
which always is a more fulfilling use of time.

~~~
pencillr
You are the man. Took the advice. :D

------
JoeSloth
Been following this project on Twitter for a while through the creators (Dave
DeSandro). Looks great.. Used to use masonry all the time in projects, glad to
see he is still creating cool shit.

------
luminati
N00b question - why is it called pseudo-3d? It looks and feels very much 3d
like a three.js output.

~~~
undershirt
Submitted a clarifying description: [https://github.com/metafizzy/zdog-
docs/issues/4](https://github.com/metafizzy/zdog-docs/issues/4)

> Zdog is a pseudo-3D Vector Art engine. You define your geometry using 3D
> splines and blobs, which render as 2D SVG shapes for any arbitrary
> perspective.

> For nerds—this simple translation is made possible by assuming an
> orthographic projection (where drawing 3D splines becomes trivially
> reducible to flat 2D splines—not so with perspective projection). More
> obvious, the occlusion-culling is achieved with a trivial drawing order or
> by hiding entire 2D primitives when appropriate.

~~~
luminati
Thanks so much!

------
mlsarecmg
React bindings are ready for testing: [https://github.com/drcmda/react-
zdog](https://github.com/drcmda/react-zdog) :-)

------
airstrike
This is really nifty. Bonus points for suggesting tau rather than pi across
the whole set of examples. Use cases like this make it entirely obvious pi is
Just Bad

------
brunoff
Wow. Nice! I can imagine a plethora of things being built over this. Less
applicable in real life, but also fun:
[https://www.youtube.com/watch?v=qoxmyH7GezE](https://www.youtube.com/watch?v=qoxmyH7GezE)
[https://github.com/s0lly/Pseudo3DEngineInExcel](https://github.com/s0lly/Pseudo3DEngineInExcel)

------
dawhizkid
Nice. I've been playing around with 2D Canvas for audio visualizations and
looked into WebGL but was mortified by how complicated it was to render basic
3D shapes and just gave up.

~~~
Impossible
The answer is always start with Three.js. Especially if you have no 3D
graphics experience and just want to render basic shapes. Drawing a textured
cube is relatively straight forward
([https://github.com/mrdoob/three.js/blob/master/examples/webg...](https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_cube.html)).

------
maccam912
I'd love to see the old tensorflow logo built with this.

~~~
dankohn1
I was thinking of how cool it would look to be able to rotate all 600+ logos
in the CNCF Interactive Landscape into the third dimension.

[https://landscape.cncf.io/](https://landscape.cncf.io/)

------
ww520
Wow. This is a nice execution of an idea. Very well done.

------
jmiskovic
Very clean and fast. The API also looks good, I like hierarchical translation
and scaling. Is there anything preventing animation?

~~~
anentropic
Seems like there shouldn't be since the examples are interactive (can rotate
the move the shapes in 3D space with the mouse), but perhaps animation is a
DIY exercise on top of this library

------
andrei_says_
Feels light and fast. Thank you for creating and sharing. I’m wondering what
are some useful applications?

------
chrisweekly
Wow! This looks fantastic! Kudos / bravo / thank you for creating and sharing
this!! :)

------
rhengles
Awesome, congratulations to the creator! I started doing something a little
similar, to render pseudo 3d shapes to canvas, here is an example[0]. Try
clicking on the page and moving the mouse.

[0]
[http://jsquest.net/chagas/shift.html](http://jsquest.net/chagas/shift.html)

------
daveheq
But when will we get ray-tracing Electron apps for Windows Home tablets?

------
playpause
I love this. I think "pseudo-2D" might be more accurate.

------
swah
Does it work on IE11?

~~~
duncans
Just tried it. No it doesn't.

------
onemoresoop
This is delightful

------
tomglynch
Pop this on product hunt, you'll get your first few thousand users in no time.

> Zdog is directly inspired by Dogz, a virtual pet game by P.F. Magic released
> in 1995. It used flat 2D circle sprites to render the Dogz’ models, but in a
> 3D scene. See Dogz playthrough video here. Dogz were fully animated in real
> time, running, flopping, scratching (on Windows 3.1!). It was remarkable.

The new repeating the old. Love when someone looks historically, finds a great
idea and re-implements it for a new usecase!

~~~
oplav
I hadn't thought about Dogz in ages. This video brought back some nostalgic
memories.

[https://www.youtube.com/watch?v=6lKSn_cHw5k](https://www.youtube.com/watch?v=6lKSn_cHw5k)

~~~
manfredo
I remember playing its successor Petz:
[https://www.youtube.com/watch?v=Qw2tJj5IX5k](https://www.youtube.com/watch?v=Qw2tJj5IX5k)

Definitely have memories from 90s childhood gaming.

