0

A basic rotating question - How you can couple 2 figures (a box/cube with a sphere in it ANYWHERE in the cube, BUT in the center) so that these 2 are coupled ROTATIONALLY (that is why I don't want the sphere to be in the center of the cube) IN PERSPECTIVE.

In other words, when I rotate the cube with the mouse and "bring" the sphere closer to the front (say, make a 180-degree rotation), the perspective changes accordingly and the sphere gets bigger visually (compared to the position on the back)?

Asked a couple of ScalaFX experts - they both said it was a very good question and recommended to post it here.

Cheers:

Zar

>

Jarek
  • 1,513
  • 9
  • 16
zarpetkov
  • 9
  • 2
  • Please [edit] your question to show [what you have tried so far](http://whathaveyoutried.com). You should include a [mcve] of the code that you are having problems with, then we can try to help with the specific problem. You should also read [ask]. – Toby Speight Jan 31 '17 at 17:28

6 Answers6

1

I'm not entirely sure what you're trying to do, but you can can rotate multiple objects by applying a Rotate transform to the Group that contains all of those objects. If you only want to rotate some of the objects, but not all of them, you have to structure the scene so that the objects being rotated have a common parent Group - with none of the non-rotating objects belonging to it. Applying Rotate transforms to that parent Group will rotate all of its child objects too. Rotation will be about the origin of that parent Group.

Update: I forgot to mention how to address the issue of perspective. The 3D objects in a scene aren't directly affected by perspective, since perspective is a property of how the scene is rendered. This rendering is performed by Camera objects. To render the scene using perspective (as opposed to using orthogonal, or parallel, as it's referred to in JavaFX/ScalaFX), add a PerspectiveCamera to the scene and view the scene using that camera. For further information on this, refer to the following: Getting Started with JavaFX 3D Graphics: Camera

Update 2: I've created a gist on GitHub with a complete program for doing this.

Update 3: Made box transparent & moved sphere inside the box. Now left/primary mouse button rotates box + sphere when dragged; right/secondary mouse button moves camera dolly towards/away from boxes, changing perspective accordingly.

Update 4: So, if I understand you right, you want to transform the shapes in your 3D scene so that they look as though perspective has been applied to them. Do I have that right?

If so, the reason that this is not a "built-in" capability is for the reasons outlined below. Please forgive me if you already know all of this, incidentally - I'm just trying to provide a comprehensive answer. :-)

  • Scene graphs (as typically used by retained mode 3D systems, such as JavaFX) capture the geometry, location, rotation, color, etc. of a 3D scene in a hierarchical tree structure. The idea is that the modeler only need to worry about the content of the scene - ensuring dimensions, alignments, etc. are correct - and do not need to worry about how the scene is rendered.
  • Perspective can be applied when the scene is rendered as it would appear from a specific viewpoint; i.e. when the scene is translated into a 2D projection such as a GUI window. (The process of determining what the scene looks like in perspective is a part of the rendering algorithm - but does not require modification, deformation, etc. of the scene.) If perspective is not enabled, then the scene is typically rendered orthogonally, without any vanishing points, apparent scaling, etc. The key point here is that the scene itself is unaffected by how it is viewed.
  • With this arrangement, it's possible to have multiple views of the same scene. Not only can they each have a different viewpoint, but some can be orthogonal and some can use perspective - yet each can render the scene correctly without any confusing artifacts. If it worked the way you seem to think it does, then you could only ever have a single view of the scene at a time, as the scene would need to be deformed during rendering to look right from that sole viewpoint. When editing the scene, you'd need to remove those deformations to prevent mind-blowing confusion for the modeler.

In short, it's a very unusual requirement that the scene itself be deformed to show what it would look like in perspective. That's why there's no built-in capability to do this in any 3D system that I know of.

Assuming that you wish to proceed - using JavaFX - here's some points to bear in mind:

  1. I don't believe that the regular 3D primitives (namely Box, Sphere & Cylinder) can be deformed to represent a perspective view of them. You will have to construct the shapes using the TriangleMesh and MeshView objects (the former captures the geometry of the shape, the latter allows it to be treated as a 3D shape).
  2. To apply perspective, you would have to reposition the vertices in the TriangleMesh instances to deform the scene appropriately. If you need to be able to change the viewpoint, or rotate the box & sphere, then these changes would need to be dynamic, so that the calculated vertex coordinates react to the changing viewpoint and/or rotation. Because of fish-eye effects at high levels of perspective dilation, you might need more vertices than you might expect.
  3. Given your requirements, you still need a camera to view the scene. Clearly, you cannot use the PerspectiveCamera to render the scene, or it will treat the scene as unadjusted and will apply a second level of perspective, ruining your carefully calculated deformations. You will then need to use ParallelCamera to produce orthogonal views of your scene.
  4. Unfortunately, JavaFX's support for using ParallelCamera with 3D scenes is still very immature. (The ParallelCamera is primarily used to render 2D scenes, such as dialogs, buttons, menu's, sliders, etc.) You might find it difficult to use in practice. (You can approximate an orthogonal projection using the PerspectiveCamera by utilizing a very narrow field of view and moving the camera away from the scene by some distance. You would also need to adjust the clipping planes to avoid the image disappearing.)
  5. Finally, at some point, you will need to be able to position the camera at the same location as the viewpoint being used for the perspective deformation. When the camera is synchronized with that viewpoint, then your scene - although rendered orthogonally - will appear as a correct perspective projection of the intended scene. Whenever the camera and the viewpoint are separated, the scene will appear unnatural and distorted, which - I understand - is your intention.

In summary, I would say that what you intend to do is far from trivial, and the implementation is way beyond the scope of a StackOverflow answer. Good luck!

Mike Allen
  • 8,139
  • 2
  • 24
  • 46
0

Mike:

Sorry for the delay, I am finishing something for a client in a totally different application area and pulled-away from my "teaching perspective" toy ...

Just got the notification for the new answers and had a quick look - one thing I noticed right away was that the sphere is outside rather than inside the transparent box (haven’t looked at the code yet).

What I actually expected was a "built-in" perspective "argument" (either in the rotation transformation, or the scene definition, or a stand-alone function - in one way are another), which allows for different perspective to be rendered depending on the angle between the 2 (initially) parallel opposing edges at the bottom, for example. I understand of course that in reality it depends on the ViewPoint Position and you are not "allowed" to forcefully change this angle, but the goal here is simply a "cause-and-effect" toy in a 3D scene.

Controlling the camera will not allow for that, since it imposes the perspective very smoothly (as it would be in real life) rather than allowing the child to directly control the edges and immediately see how her action changes the perspective, rather than playing with the viewpoint.

As mentioned in the original question, I'd expect a function like the one sketched below (and I would expect it to be BUILT-IN in a sensible 3D-product since it is so basic, rather than forcing me or you to manually craft some code for something that should have been there from the get-go - perspective is simply a basic fundamental and hopefully will be covered by the rendering in some form in the next release):

def doPersepctive( myBox: MyBoxContainer, angle: Int, viewPoint: Point): Int = {
// Presents the perspective look in a way defined by the "angle" between the // (initially) parallel edges of myBoxContainer, from the viewPoint Point (3D). // Rotate everything within the boundaries of MyBoxContainer. The // bigger the angle, the smaller the sphere at the back, of course. // Returns the rotatedAngle after the mouseEvent to enable auto-replay later, so // the kid can examine what her actions were and see the effect of those actions. }

Tnx again for your entry, I will certainly have a look at the code, and reply - but you see the general picture above. Sorry for the delay again:

Z

>

zarpetkov
  • 9
  • 2
  • Transparency is problematic in JavaFX; I'll update the source to do that. Every 3D system I know has perspective as a rendering property, not a shape transformation. I's possible to have multiple views of a scene; if the scene itself is modified to represent perspective for one view, then all the others would look wrong. You can control how perspective appears by moving the camera towards & away from an object, and by changing the field of view. Doing it your way requires manipulating `TriangleMesh` objects - very fiddly. `Box` & `Sphere` would be too tough. Rendering is the way to go, IMHO. – Mike Allen Feb 05 '17 at 22:04
0

Mike:

This is more like the original intension - although I find merits in the first attempt too, actually.

I made the sphere (in the first version) transparent (via diffuseColor = Color.web("#ffff0080") ), so now she can play with both versions, and both are pretty much SIMILAR from a child's perspective (meaning one of the objects is transparent, moreover different objects in these versions).

Now - I tried to make the BOX transparent (where the sphere is outside) and I failed - is there a reason for that? In other words trying to make the object passing "behind" visible? One transparent object passing behind another transparent object, so to say?

In the second version I ALSO cannot see "behind the object", meaning I can NOT see the EDGE of the box passing behind the sphere. Not only that – I can NOT see the back edge EVEN when it is not behind the sphere (but only behind the front side of the box)!

My question in a sense is "CAN both objects be made transparent" - I guess this is the closest to what I am trying to ask. May be with different “transparency %”, but still transparent…

Tnx again:

Zar

>

zarpetkov
  • 9
  • 2
  • As I mentioned earlier, transparency in _JavaFX_ is problematic. The `opacity` property of `Box` & `Cylinder` appears to have no effect on 3D objects. Instead, the _alpha channel_ of the object's color denotes transparency. (This can be set using "web" colors using 4 pairs of hex digits for red, green, blue and alpha/opacity. Alternatively, there's a _JavaFX_ constructor that takes four `Double` arguments corresponding to each value. Finally, there's an `opacity` property of the color than can be manipulated directly. Refer to the _JavaFX_ API docs for further details. – Mike Allen Feb 07 '17 at 01:05
  • The main problem is that _JavaFX_ support for transparency is not fully implemented. Refer to [this post](http://stackoverflow.com/questions/29308397/javafx-3d-transparency/30213869#30213869) for further details. – Mike Allen Feb 07 '17 at 01:08
  • It appears that I've addressed your original question, so I'd be grateful if you could accept my original answer. If you have any further questions, you should raise them as new questions and tag them as relating to ScalaFX, JavaFX & JavaFX 3D as appropriate. I'd be happy to try answering them - and you may get better help from others too. :-) – Mike Allen Feb 07 '17 at 01:13
0

Yes, Mike - your answer was completely relevant and I do accept it with the thoughtfully-explained shortcomings of the current ScalaFX implementation. If I need to "click" somewhere to formally TAG this, please let me know - I am new to this group and don't know the formalities really.

Tnx again:

Zar

zarpetkov
  • 9
  • 2
  • Hi Zar. No worries. _Stack Overflow_ is a bit of a nuisance when you're first getting started. As you get more points, it starts to become usable... :-( If you scroll to my answer, there's a pair of arrows with a number (probably a zero) to the upper left. Underneath, you'll see a gray tickmark. Click on the tickmark - so that it goes green - to approve the answer. If you have any new _ScalaFX_ questions, please post them. tag them with ScalaFX, JavaFX, etc. and I'll do my best to help out. Thanks and good luck! – Mike Allen Feb 08 '17 at 02:35
  • Also, it might be worth mentioning _[Java3D](http://www.oracle.com/technetwork/java/javase/overview/index-jsp-138252.html)_. The last _official_ release was some time ago - it's dead as far as _Oracle_ are concerned. However, it is a very mature 3D scene graph, and there are some forks of it on GitHub (of which one of the better ones is [here](https://github.com/hharrison/java3d-core)). – Mike Allen Feb 08 '17 at 02:40
-1

I expected that there was a parameter that controls the Perspective during a Rotational Transformation, but cannot find one. The sample problem is clearly defined - you have a BOX/CUBE and a smaller sphere inside; now when you rotate the BOX, the sphere rotates WITH it but "in perspective", meaning that if you bring the sphere in front, it looks (draws) bigger correspondingly with the "perspective".

Zar

>

zarpetkov
  • 9
  • 2
  • Please read my answer. It exactly addresses your original question. Perspective is a rendering property and has nothing to do with the shapes or the transformations. Perspective will make anything look bigger as you get closer to it, but the size of the object doesn't change. You can rotate both objects that the same time, regardless of where they are located, by applying the rotation to a Group that they are both children of. Please let me know which part of this answer & comment you do not understand. – Mike Allen Feb 01 '17 at 21:37
  • BTW, if it were possible to add the Sphere as a child of the Box, then you could rotate the Sphere with the Box by rotating the Box, but you can't. So, you need to add both to a Group, and rotate the Group instead (or translate it - it will behave as you'd expect). Position the origin of the Group at the origin of the Box and you'll get what you want. – Mike Allen Feb 01 '17 at 21:49
-1

> BTW, if it were possible to add the Sphere as a child of the Box, then you ... <

That is not possible, but CAN I add the sphere AT RUN TIME rather than at compile time? In other words is there an "addObject" that adds the sphere after the kid has played with box for 1 min and 1 min after running the program, the sphere appears. Cannot see anything like that here:

http://www.scalafx.org/api/8.0/index.html#package

May be I am missing something ?

Zar

>

zarpetkov
  • 9
  • 2
  • In fact, you can only add elements to the scene at run-time - it's impossible at compile time. (The compiler merely translates the Scala code into JVM bytecode. The code initializing new objects executes at run-time, adding the shapes to groups, etc.) A scene graph has two types of `Node`: _group nodes_ that can contain other nodes (such as `Group` in _JavaFX_) and _leaf nodes_ that cannot (`Camera`, `Shape`, `Shape3D`, etc.). You can indeed add/remove children from a group node at run time. See `children` property of [`Group`](http://www.scalafx.org/api/8.0/index.html#scalafx.scene.Group). – Mike Allen Feb 09 '17 at 03:08
  • asking new questions as though they were answers to your original question is very confusing for other _Stack Overflow_ users. Can you please accept my original answer to your original question - as described in my earlier comment - and ask any further questions you may have as new _Stack Overflow_ questions? Please tag your new answers accordingly (someone else will probably do it for you if you don't know how, but it's best if you give that a try). This will also allow other users to provide answers as well. Thanks! – Mike Allen Feb 09 '17 at 03:21
  • Done, Mike - hope it is visible now (the acceptance). On the compile vs. runtime, I am afraid I didn't make my point clear. When I say 'at run time', I REALLY mean run-time :-) At RUNTIME I decide what the sphere's RADUIS is going to be, whathe POSITION of the sphere is going to be etc. – zarpetkov Feb 09 '17 at 03:32
  • Thanks, @Zar, I appreciate it. One further point, because it's not obvious: in _JavaFX_, the children of a `Group` are stored in an [`ObservableList`](http://docs.oracle.com/javase/8/javafx/api/javafx/collections/ObservableList.html). It's possible to add and remove nodes to/from this list directly (since these lists are _observable_, events can be triggered as a result). However, in _ScalaFX_, the corresponding class to `ObservableList` is [`ObservableBuffer`](http://www.scalafx.org/api/8.0/scalafx/collections/ObservableBuffer.html). You can change everying in a scene at run-time. :-) – Mike Allen Feb 09 '17 at 04:18
  • Yeah, one thing leads to another :-) Tnx again, Mike - you are as deep in this area as I have ever seen. – zarpetkov Feb 10 '17 at 03:56