Does the Windows Composition API support 2.5D projected rotation? - animation

I have started to use the Windows Composition API in UWP applications to animate elements of the UI.
Visual elements expose RotationAngleInDegrees and RotationAngle properties as well as a RotationAxis property.
When I animate a rectangular object's RotationAngleInDegrees value around the Y axis, the rectangle rotates as I would expect but in a 2D application window, it does not appear to be displaying with a 2.5D projection.
Is there a way to get the 2.5D projection effect on rotations with the composition api?

It depends to the effect that you want to have. There is a fluent design app sample on GitHub and here is the link. You will be able to download the demo from the store. And you can get some idea from depth samples. For example, flip to reveal shows a way to rotate a image card and you can find source code from here. For more details please check the sample and the demo.
In general, the animation is to rotate based on X axis:
rectanglevisual.RotationAxis = new System.Numerics.Vector3(1f, 0f, 0f);
And then use rotate animation to rotate based on RotationAngleInDegrees.
It is also possible for you to do this directly on XAML platform by using PlaneProjection from image control.

As the sample that #BarryWang pointed me to demonstrates it is necessary to apply a TransformMatrix to the page (or a parenting container) before executing the animation to get the 2.5D effect with rotation or other spatial transformation animations with the composition api.
private void UpdatePerspective()
{
Visual visual = ElementCompositionPreview.GetElementVisual(MainPanel);
// Get the size of the area we are enabling perspective for
Vector2 sizeList = new Vector2((float)MainPanel.ActualWidth, (float)MainPanel.ActualHeight);
// Setup the perspective transform.
Matrix4x4 perspective = new Matrix4x4(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, -1.0f / sizeList.X,
0.0f, 0.0f, 0.0f, 1.0f);
// Set the parent transform to apply perspective to all children
visual.TransformMatrix =
Matrix4x4.CreateTranslation(-sizeList.X / 2, -sizeList.Y / 2, 0f) * // Translate to origin
perspective * // Apply perspective at origin
Matrix4x4.CreateTranslation(sizeList.X / 2, sizeList.Y / 2, 0f); // Translate back to original position
}

Related

Point cloud rendered only partially

I only get a partial point cloud of the room. Other parts of the room do not get rendered at all. It only sees a part to the left. I am using the Point Cloud prefab in Unity. When I use one of the apps, such as Room Scanner or Explorer, I get the rest of the room. I intend to modify the pre-fab for my application but so far I get that limited view. I am using Unity 5.3.3 on Windows 10 on a 64.
set the unity camera aligned with the depth camera frame
so for the matrix dTuc
dTuc = imuTd.inverse * imuTdepth * depthTuc
double timestamp = 0.0;
TangoCoordinateFramePair pair;
TangoPoseData poseData = new TangoPoseData();
// Get the transformation of device frame with respect to IMU frame.
pair.baseFrame = TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_IMU;
pair.targetFrame = TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_DEVICE;
PoseProvider.GetPoseAtTime(poseData, timestamp, pair);
Matrix4x4 imuTd = poseData.ToMatrix4x4();
// Get the transformation of IMU frame with respect to depth camera frame.
pair.baseFrame = TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_IMU;
pair.targetFrame = TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_CAMERA_DEPTH;
PoseProvider.GetPoseAtTime(poseData, timestamp, pair);
Matrix4x4 imuTdepth = poseData.ToMatrix4x4();
// Get the transform of the Unity Camera frame with respect to the depth Camera frame.
Matrix4x4 depthTuc = new Matrix4x4();
depthTuc.SetColumn(0, new Vector4(1.0f, 0.0f, 0.0f, 0.0f));
depthTuc.SetColumn(1, new Vector4(0.0f, -1.0f, 0.0f, 0.0f));
depthTuc.SetColumn(2, new Vector4(0.0f, 0.0f, 1.0f, 0.0f));
depthTuc.SetColumn(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
m_dTuc = Matrix4x4.Inverse(imuTd) * imuTdepth * depthTuc;

How to scale and rotate textures in opengl es?

I am using opengl ES for my iphone game. To scale and rotate my object i do this:
glScalef( scaleX , scaleY ,1);
glRotatef(rotationZ, 0.0f, 0.0f, 1.0f)
I am using an ortho screen with orthof(-1,1,-1,1,-1,1). My problem is when i rotate objects, the image gets skewed. I understand why that is happening as i am scaling wrt to the screen size so while rotating it changes the image size.
What can i do to prevent it from getting skewed.
glViewport(0,0, (GLint)screenWidth, (GLint)screenHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-1,1,-1,1,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(positionX, positionY,0.0f);
glScalef(scaleX , scaleY ,1);
glRotatef(rotationZ, 0.0f, 0.0f, 1.0f);
Use an ortho projection that matches your aspect ratio of the screen rather than just sending a bunch of ones. Unless you have a square screen, your left/right shouldn't be the same as your top/bottom or you will see skew.

Opengl es render to textture appears upside down

Using frame buffer
When rendering the texture appears upsidedown, here are vertices and texture coordinate.
By the way rendering without creating frame buffer renders the texture correctely
private final float[] mVerticesData =
{
-1f, 1f, 0.0f, // Position 0
0.0f, 0.0f, // TexCoord 0
-1f, -1f, 0.0f, // Position 1
0.0f, 1.0f, // TexCoord 1
1f, -1f, 0.0f, // Position 2
1.0f, 1.0f, // TexCoord 2
1f, 1f, 0.0f, // Position 3
1.0f, 0.0f // TexCoord 3
};
Any help please ...
thanks
When uploading 2D texture images to OpenGL, it expects the data to be specified from bottom to top, even though usually images are in memory from top to bottom. You seem to have inverted your texture coordinates to work around this problem.
You should instead flip the texture data before uploading it to OpenGL and keep your texture coordinates intact. If you do that, the same texture coordinates work for both image and FBO textures.
So the solution is to flip the bitmap before calling GLUtils.texImage2D and to write your vertices as
private final float[] mVerticesData =
{
-1f, 1f, 0.0f, // Position 0
0.0f, 1.0f, // TexCoord 0
-1f, -1f, 0.0f, // Position 1
0.0f, 0.0f, // TexCoord 1
1f, -1f, 0.0f, // Position 2
1.0f, 0.0f, // TexCoord 2
1f, 1f, 0.0f, // Position 3
1.0f, 1.0f // TexCoord 3
};
By the way rendering without creating frame buffer renders the texture correctely
I think it actually doesn't. With all transformations set to identity and texture coordinates matching vertex coordinates, i.e. S=X, T=Y, OpenGL assumes the origin of texture data to be in the lower left (with the noteable exception of cube maps, which are different beasts). Framebuffer color attachments, in your case your texture, agree upon that convention.
Your texture T coordinates are antiparallel to the Y vertex coordinates, which means in the case of an all identity transformation setup you flip it "upside down".
However most image file formats assume the origin in the upper left and if you upload such data as is to a OpenGL texture this adds another flip, and together with your texture coordinate flip both cancel out.
So it's very likely, that in face your regular texture code path is "flipped".

glMaterialfv not working for me

This is OpenGL on iPhone 4.
Im drawing scene using light and materials. Here is snippet of my code:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustumf(-1, 1, -1, 1, -1, 1);
CGFloat ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
CGFloat diffuseLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
CGFloat direction[] = { 0.0f, 0.0f, -20.0f, 0 };
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, direction);
glShadeModel(GL_FLAT);
glEnable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
float blankColor[4] = {0,0,0,1};
float whiteColor[4] = {1,1,1,1};
float blueColor[4] = {0,0,1,1};
glMaterialfv(GL_FRONT, GL_DIFFUSE, blueColor);
glEnable(GL_CULL_FACE);
glVertexPointer(3, GL_FLOAT, 0, verts.pdata);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals.pdata);
glEnableClientState(GL_NORMAL_ARRAY);
glDrawArrays (GL_TRIANGLES, 0, verts.size/3);
Problem is that instead of seeing BLUE diffuse color I see it white. It fades out if I rotate model's side but I can't understand why its not using my blue color.
BTW if I change glMaterialfv(GL_FRONT, GL_DIFFUSE, blueColor) to glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, blueColor) then I do see blue color. If I do it glMaterialfv(GL_FRONT, GL_DIFFUSE, blueColor); and then glMaterialfv(GL_BACK, GL_DIFFUSE, blueColor); I see white color again. So it looks like GL_FRONT_AND_BACK shows it but rest of combinations show white. Anyone can explain it to me?
This is because of clockwise
10.090 How does face culling work? Why doesn't it use the surface normal?
OpenGL face culling calculates the signed area of the filled primitive in window coordinate space. The signed area is positive when the window coordinates are in a counter-clockwise order and negative when clockwise. An app can use glFrontFace() to specify the ordering, counter-clockwise or clockwise, to be interpreted as a front-facing or back-facing primitive. An application can specify culling either front or back faces by calling glCullFace(). Finally, face culling must be enabled with a call to glEnable(GL_CULL_FACE); .
OpenGL uses your primitive's window space projection to determine face culling for two reasons. To create interesting lighting effects, it's often desirable to specify normals that aren't orthogonal to the surface being approximated. If these normals were used for face culling, it might cause some primitives to be culled erroneously. Also, a dot-product culling scheme could require a matrix inversion, which isn't always possible (i.e., in the case where the matrix is singular), whereas the signed area in DC space is always defined.
However, some OpenGL implementations support the GL_EXT_ cull_vertex extension. If this extension is present, an application may specify a homogeneous eye position in object space. Vertices are flagged as culled, based on the dot product of the current normal with a vector from the vertex to the eye. If all vertices of a primitive are culled, the primitive isn't rendered. In many circumstances, using this extension
from here
Also you can read here

How to draw a texture as a 2D background in OpenGL ES 2.0?

I'm just getting started with OpenGL ES 2.0, what I'd like to do is create some simple 2D output. Given a resolution of 480x800, how can I draw a background texture?
[My development environment is Java / Android, so examples directly relating to that would be best, but other languages would be fine.]
Even though you're on Android, I created an iPhone sample application that does this for frames of video coming in. You can download the code for this sample from here. I have a writeup about this application, which does color-based object tracking using live video, that you can read here.
In this application, I draw two triangles to generate a rectangle, then texture that using the following coordinates:
static const GLfloat squareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat textureVertices[] = {
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 0.0f,
};
To pass through the video frame as a texture, I use a simple program with the following vertex shader:
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
void main()
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy;
}
and the following fragment shader:
varying highp vec2 textureCoordinate;
uniform sampler2D videoFrame;
void main()
{
gl_FragColor = texture2D(videoFrame, textureCoordinate);
}
Drawing is a simple matter of using the right program:
glUseProgram(directDisplayProgram);
setting the texture uniform:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, videoFrameTexture);
glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
setting the attributes:
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
and then drawing the triangles:
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
You don't really draw a background, instead you draw a rectangle (or, even more correctly: two triangles forming a rectangle) and set a texture to that. This isn't different at all from drawing any other object on screen.
There are plenty of places showing how this is done, maybe there's even an android example project showing this.
The tricky part is getting something to display in front of or behind something else. For this to work, you need to set up a depth buffer and enable depth testing (glEnable(GL_DEPTH_TEST)). And your vertices need to have a Z coordinate (and tell glDrawElements that your vertices are made up of three values, not two).
If you don't do that, objects will be rendered in the order their glDrawElements() functions are called (meaning whichever you draw last will end up obscuring the rest).
My advice is to not have a background image or do anything fancy until you get the hang of it. OpenGL ES 2.0 has kind of a steep learning curve, and tutorials on ES 1.x don't really help with getting 3D to work because they can use helper functions like gluPerspective, which 2.0 just doesn't have. Start with creating a triangle on a background of nothing. Next, make it a square. Then, if you want to go fancy already, add a texture. Play with positions. See what happens when you change the Z value of your vertices. (Hint: Not a lot, if you don't have depth testing enabled. And even then, if you don't have perspective projection, objects won't get smaller the farther they are away, so it will still seem as if nothing happened)
After a few days, it stops being so damn frustrating, and you finally "get it", mostly.

Resources