Wrapping image around objects in web app - asp.net

I'm creating a web app in ASP.NET like this one:
http://www.zazzle.com/cr/design/pt-mug
I know how to do everything except wrapping an image around an object.
It would be a simple task to do if I would only have to stack an image on
top of the other, if they were flat, but if it is a round object, as this mug
is, it's kinda tricky.
My first guess was to create some sort of algorithm for GDI+ that would
simulate "wrapping" image around an object (actualy it wouldn't be an 3d object,
it would just be a screenshot of it).
I figured it would be to raw approach and it would result in very bad quality,
if I could ever make it work.
So, my second guess was to implement somekind of 3d renderer to whom I would
give an image map for some object, it would render me that image onto an object
and in real time return me rendered image. Is that posible?
Is there any other way? Where do I start?

If you are willing to try a commercial product, my company makes a raster processing SDK for .NET called DotImage. If you try it, take a look at PolygonTransform. You supply a polygon as a list of points, and the class warps the image to fit inside the polygon. If you need sample code for it, let me know.

It might be some sort of OpenGL 3D rendering, but an image could easily be morphed in a purely 2D way for this effect. Horizontally, it would need to be squished where it goes off the side of the cup. Each column of pixels needs to be shifted vertically by varying amounts depending on which column - such that a horizontal line the image would become like a "U" shape. With the right parameters, such a morph could mimic the proper 3D shape. Lighting effects could be applied to, by brightening/darkening the image a bit in the right places.

Related

Render 2D text in Autodesk Forge without aliasing or blurring

Turns out I’m working with the Autodesk Forge viewer and Three.js, trying to render 2D text that can be interacted with (specifically select, rotate, and move).
To do this I am working with meshes (using MeshBasicMaterial, Mesh and TextGeometry) but it turns out that the text does not look perfectly sharp, it presents aliasing and I found that according to the API reference, the antialiasing is not applicable to 2d.
Here are some examples of the problem, as you can see, the more I move away from the plane, the worse the text looks (and even up close it doesn't look perfect):
I have tried to make a test representing the text with a Sprite (despite the fact that it would mean having to change the entire implementation already made with meshes of other functionalities) but apart from the fact that I cannot see it, I have seen example images and they do not appear either well: aliasing is visible from a distance and it looks really blurry up close. Here some examples:
Is there a way to correct this problem or is this the most I can get in 2D? I've tried searching for information on this but can't find anything helpful. And what has puzzled me the most has been realizing that antialiasing was not applicable in the case of 2d, like making it clear that nothing can be done to fix it.
I would be very grateful if you could solve my doubts, thank you very much in advance for your help.
An easier alternative, is to just use a higher pixel ratio for the renderer...
window.devicePixelRatio=2;
viewer.resize();
For example, using the custom geometry text, from Joao's demo, you can see the same aliasing issue at DPR=0.5 and DPR=1.0 ...
https://joaomartins-forge.github.io/textgeometry-sample/
But when I set the DPR=2.0, the text looks clean. The trade off is rendering performance, but your 2D drawings may be simple enough that it won't matter. You can use a 'mouse up' camera settle trick, to switch between DPR of 1 and 2, if you want a better UX experience.
There are a few ways to solve this aliasing issue for 2D (and 3D text).
The way I would recommend for your use case, is to use DIV elements (THREE.CSS3DRenderer), instead of text converted into three.js tessellated triangle geometry, as shown in this blog post:
https://forge.autodesk.com/blog/how-do-you-add-labels-forge-viewer
You can find out more information about THREE.CSS3DRenderer here:
https://threejs.org/docs/#examples/en/renderers/CSS3DRenderer
and an Example here: https://threejs.org/examples/#css3d_periodictable
Using CSS3DRenderer instead of CSS2DRenderer, means you will get the correct scaling (and rotation) of the div element as you zoom into your 2D drawing and the mathematics inside the calculation for the matrix transform has less edge-cases.
Once you are using DIV elements for your text, you will notice that the text is sharper and has no aliasing issues. That's because it is not being rasterized by the webGL pipeline, but by the SKIA library used by chrome/firefox/opera/etc for rasterizing text.
There is one final option, that uses signed-distance fields, but it's probably overkill for what you need.
Let me know if you want some example code.

Generate thumbnail from stage for react-konva

I have created a react app Which is very similar to office whiteboard. I would like to generate a thumbnail or card preview of each whiteboard and wondering how to go about it.
My initial thought was to just create a card component and render the shapes to that the same way I do for the real whiteboard. However, the points for each shape will be outside the stage and I can't think of how I can scale it down.
Any ideas?
Take a look at the official canvas thumbnail demo from Konva.
You can use a similar approach with react-konva.
Create a special component for the preview.
I think this approach will work better and probably more performant (depending on your app). You just need to create another Stage and draw all objects into it. It will be better if you can draw simplified versions of the shape, because the drawing is much smaller, so not all details are visible.
You will have to calculate your own scale ratio.
Use image preview
Instead of making a full components tree for the whiteboard, you can just export the main stage into an image and show it. You have to do reexport from time to time.

What is the best approach to displaying drawings on different-sized Paper JS views?

Context
I'm using Paper JS to build a multi-player drawing game. At any given point, a single user will be drawing to his/her canvas, and the data will get sent to the server to be broadcast to other users. Each user's canvas may be of variable size, and it resizes as the window resizes while maintaining the same aspect ratio.
The goal is for each user to have a scaled representation of the drawing (i.e. everything fits inside the different sized canvases and the content doesn't get distorted). This should be the case if a drawing transfers from a larger canvas to a smaller canvas, and vice-versa. The project supports a drawing tool as well as an eraser tool.
Problem
Approach 1 below scales the drawings the way I want, but there is substantial lag. Approach 2 deals with the lag, but doesn't scale the drawings the way I want.
My understanding is that SVGs will scale nicely whether they are scaled-up or scaled-down. But rasters are pixel-based and will become "blurry" when scaled-up. When I test approach 2, a drawing from a smaller canvas gets blurred on a larger canvas. The result is the same whether I use export/importJSON or export/importSVG. Is there a way to get both good performance and scaled-drawings? See below for example implementations of the tools.
Approach 1: Paths + Symbols:
Every path/symbol placement is kept in the active layer.
The eraser tool draws a white rectangle (defined as a symbol) to
mimic an "erasing" effect.
This works fine as a demo, but will start to lag very quickly as the
number of items in the active layer increases. The eraser tool in
particular will not function smoothly.
Relevant sketch
Approach 2: Rasterization:
After a path is drawn or a symbol is placed, the active layer is
rasterized and its children are removed.
This seems to work quite well on a single canvas, and the eraser
doesn't lag like in the first approach. There are only 2 items in the
active layer after each rasterization.
When a drawing from a client with a smaller canvas is exported (using exportJSON or exportSVG) to a client with a larger canvas, the result is "blurry".
The above also happens when a drawing is made and then the canvas is re-sized to be larger.
Relevant sketch
You could send your objects as SVG and rasterize them once received.

ScalaFX: How to couple 2 figures rotationally in perspective

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
>
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:
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).
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.
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.
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.)
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:
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
>
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
>
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
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
>
>
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
>

Rendering an invisible occluder

I'm currently upgrading from a DirectDraw system (yeah I know, it's very old) to DirectX10. It's a 2D system but simulates real world as each object has a range/depth in meters. There is a background image that is rendered and kept on the farthest z-order. All other objects are drawn on top of it and scaled according to what their range/depth would be. However, there is a certain type of object I have that is defined as a polygon and renders a bit different. It acts as an invisible occluder. For instance, an occluder is at a range/depth of 40 (my units are meters) and is defined by 5 vertices (a pentagon) in the middle of the viewport. There is a sprite object at the same viewport position but at a range/depth of 50. The desired output is to have the sprite object not rendered, but the background should be seen through both of them. So in essence these are invisible occluders, except that they do not occlude the background.
As a note, the occluders and the sprites all derive from the same base object type and are mixed together in a depth-sorted container.
My idea was to override the occluders Render method so they draw to a render target writing the range/depth values. I then would render the sprites as normal, but in the vertex or pixel shader would compare the range value of the sprite with the range values in the render target. However, it seems to me that I'd have to potentially read/write from the render target in the same pass before Present is called, and that's undefined. If i was to render the occluders, unbind the render target and pass the texture in for a lookup by the other objects, I'll have to convert the sprite positions into that texture space which may be non-trivial. Are either of these methods possible?
After thinking some more about it, one other idea came to mind. I could take the occluders and set their texture coordinates in reference to the background texture. In this way they would draw the same color values as the background, and because of the sorting if a sprite was behind it the user would still see the "background" but really it's the occluder looking like it.
Sorry if this is less a question and more thinking out loud, but I wanted to get impressions and ideas on the best way to go about this. Seems to me I have options but wasn't certain which was most efficient and which is easiest. Thanks in advance for any responses.
As stated in my comments I went with setting the texture coordinates in reference to the background image and then making sure the occluder, which was a simple polygon, was triangulated properly to make use of those texture coordinates.

Resources