Width is shrink after increasing the width & height 2 times openGL C++ - android

I am rendering video on GLSurfaceView by openGL. The openGL portion is written on C++ in native portion. This is my render routine:
void VideoRenderOpenGL2::Render(const unsigned char *pData)
{
......................
// GL_OPERATION is a macro, nothing special
GL_OPERATION(glUseProgram(m_program))
UpdateTextures(pData); // other routine, I will post the function if needed
bool bClear = true;
float vpx = 0.0f;
float vpy = 0.0f;
float vpw = 1.0f;
float vph = 1.0f;
int nOrientation = 0;
float uLeft, uRight, vTop, vBottom;
uLeft = vBottom = 0.0f;
uRight = m_uvx;
vTop = m_uvy;
GLfloat squareUvs[] = {
uLeft, vTop,
uRight, vTop,
uLeft, vBottom,
uRight, vBottom
};
if (bClear) {
GL_OPERATION(glViewport(0, 0, m_nDisplayWidth, m_nDisplayHeight))
GL_OPERATION(glClearColor(0, 0, 0, 1))
GL_OPERATION(glClear(GL_COLOR_BUFFER_BIT))
}
GLfloat squareVertices[8];
// drawing surface dimensions
int screenW = m_nDisplayWidth;
int screenH = m_nDisplayHeight;
if (nOrientation == 90 || nOrientation == 270) {
screenW = m_nDisplayHeight;
screenH = m_nDisplayWidth;
}
int x,y,w,h;
// Fill the smallest dimension, then compute the other one using the image ratio
if (screenW <= screenH) {
float ratio = m_nTextureHeight / (float)m_nTextureWidth;
w = screenW * vpw;
h = w * ratio;
if (h > screenH) {
w *= screenH /(float) h;
h = screenH;
}
x = vpx * m_nDisplayWidth;
y = vpy * m_nDisplayHeight;
} else {
float ratio = m_nTextureWidth / (float)m_nTextureHeight;
h = screenH * vph;
w = h * ratio;
if (w > screenW) {
h *= screenW / (float)w;
w = screenW;
}
x = vpx * screenW;
y = vpy * screenH;
}
// here m_nDisplayWidth = 5536, m_nDisplayHeight = 3114, w = 5536, h = 3114, x = 0, y = 0, screenW = 5536, screenH = 3114, m_nTextureWidth = 1280, m_nTextureHeight = 720
squareVertices[0] = (x - w * 0.5) / screenW - 0.;
squareVertices[1] = (y - h * 0.5) / screenH - 0.;
squareVertices[2] = (x + w * 0.5) / screenW - 0.;
squareVertices[3] = (y - h * 0.5) / screenH - 0.;
squareVertices[4] = (x - w * 0.5) / screenW - 0.;
squareVertices[5] = (y + h * 0.5) / screenH - 0.;
squareVertices[6] = (x + w * 0.5) / screenW - 0.;
squareVertices[7] = (y + h * 0.5) / screenH - 0.;
GL_OPERATION(glViewport(0, 0, m_nDisplayWidth, m_nDisplayHeight))
GLfloat mat[16];
#define VP_SIZE 1.0f
float vpDim = VP_SIZE / (2 * m_scaleFactor);
#define ENSURE_RANGE_A_INSIDE_RANGE_B(a, aSize, bMin, bMax) \
if (2 * aSize >= (bMax - bMin)) \
a = 0; \
else if ((a - aSize < bMin) || (a + aSize > bMax)) { \
float diff; \
if (a - aSize < bMin) diff = bMin - (a - aSize); \
else diff = bMax - (a + aSize); \
a += diff; \
}
float zoom_cx = 0.0f;
float zoom_cy = 0.0f;
ENSURE_RANGE_A_INSIDE_RANGE_B(zoom_cx, vpDim, squareVertices[0], squareVertices[2])
ENSURE_RANGE_A_INSIDE_RANGE_B(zoom_cy, vpDim, squareVertices[1], squareVertices[7])
LoadOrthographicMatrix(
zoom_cx - vpDim,
zoom_cx + vpDim,
zoom_cy - vpDim,
zoom_cy + vpDim,
0, 0.5, mat);
GL_OPERATION(glUniformMatrix4fv(m_uniforms[UNIFORM_PROJ_MATRIX], 1, GL_FALSE, mat))
#define degreesToRadians(d) (2.0 * 3.14157 * d / 360.0)
float rad = degreesToRadians(nOrientation);
GL_OPERATION(glUniform1f(m_uniforms[UNIFORM_ROTATION], rad))
GL_OPERATION(glActiveTexture(GL_TEXTURE0))
GL_OPERATION(glBindTexture(GL_TEXTURE_2D, m_textures[Y]))
GL_OPERATION(glUniform1i(m_uniforms[UNIFORM_TEXTURE_Y], 0))
GL_OPERATION(glActiveTexture(GL_TEXTURE1))
GL_OPERATION(glBindTexture(GL_TEXTURE_2D, m_textures[U]))
GL_OPERATION(glUniform1i(m_uniforms[UNIFORM_TEXTURE_U], 1))
GL_OPERATION(glActiveTexture(GL_TEXTURE2))
GL_OPERATION(glBindTexture(GL_TEXTURE_2D, m_textures[V]))
GL_OPERATION(glUniform1i(m_uniforms[UNIFORM_TEXTURE_V], 2))
GL_OPERATION(glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices))
GL_OPERATION(glEnableVertexAttribArray(ATTRIB_VERTEX))
GL_OPERATION(glVertexAttribPointer(ATTRIB_UV, 2, GL_FLOAT, 1, 0, squareUvs))
GL_OPERATION(glEnableVertexAttribArray(ATTRIB_UV))
GL_OPERATION(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4))
}
And this is LoadOrthographicMatrix:
void VideoRenderOpenGL2::LoadOrthographicMatrix(float left, float right, float bottom, float top, float near, float far, float* mat)
{
float r_l = right - left;
float t_b = top - bottom;
float f_n = far - near;
float tx = - (right + left) / (right - left);
float ty = - (top + bottom) / (top - bottom);
float tz = - (far + near) / (far - near);
mat[0] = (2.0f / r_l);
mat[1] = mat[2] = mat[3] = 0.0f;
mat[4] = 0.0f;
mat[5] = (2.0f / t_b);
mat[6] = mat[7] = 0.0f;
mat[8] = mat[9] = 0.0f;
mat[10] = -2.0f / f_n;
mat[11] = 0.0f;
mat[12] = tx;
mat[13] = ty;
mat[14] = tz;
mat[15] = 1.0f;
}
Suppose, my device dimension is 1080 x 1557 and I am trying to render 2768 x 1557 (height equal to device height and corresponding width keeping aspect ratio with 1280 x 720) sized video on the GLSurfaceView. Everything works fine so far and Render(const unsigned char *pData) is properly rendering and glViewport(0, 0, m_nDisplayWidth, m_nDisplayHeight) is working fine.
But when I want to load video twice the size of 2768 x 1557 I mean 5536 x 3114 the video shinked/congested (not truncated) across X axis. The Render(...) is drawing the full contents of video, but not using the full canvas. I can't figure it out what's wrong here. Why the video is congested across X axis?
It is to be noted that, the video is rendered more congested when I increased the width & height more than 2 times. Its okay till 2768 x 1557

You may be exceeding limits of your OpenGL implementation. Particularly, the maximum texture size and maximum viewport dimensions could come into play.
To query the maximum texture size, use:
GLint maxTexSize = 0;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
and for the maximum viewport dimensions:
GLint viewportDims[2] = {0};
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewportDims);
Typical values for these limits are as low as 2K for current low end devices, and possibly even lower for older devices. 4K and 8K are very common for current mainstream devices. Recent high end mobile GPUs support sizes up to 16K.
So before you try sizes over 4K, you should definitely check these limits. It's very likely that your 5536x3114 size will be beyond the limit of some fairly recent devices.

Related

How to capture exactly the image inside the rectangular overlay in Camera?

I successfully made the auto crop to some extent for small devices so far. I am facing two issues:
1) the auto crop in big devices lets say 6.5 inches is not working properly
2) i want to take picture inside the rectangle frame
Below is my code:
public static Bitmap crop(Bitmap originalBitmap)
{
double originalWidth = originalBitmap.getWidth();
double originalHeight =
originalBitmap.getHeight();
double scaleX = originalWidth / 1280;
int navBarHeightPxIn1280x720Ui
CommonUtils.px2dp(CommonUtils.get
NavigationBarHeightInPx()) * 5 ;
double scaleXMultiplier = ((double) 1280) /
((double) (1280 - navBarHeightPxIn1280x720Ui));
scaleX = scaleX * scaleXMultiplier;
double scaleY = originalHeight / 720;
int x = (int) (52 * scaleX + 0.5);
int y = (int) (80 * scaleY + 0.5);
int width = (int) (896 * scaleX + 0.5);
int height = (int) (588 * scaleY + 0.5);
return Bitmap.createBitmap(originalBitmap, x, y,
width, height);
}

TextureView TranslationX & Y not expected behaviour on API 23

Currently I am making a camera player with a textureview to render my camera. Because the preview can have any dimension I have created some custom code to alter the textureview when OnSurfaceTextureUpdated is called:
void updateTextureMatrix(int width, int height) {
Display display = WindowManager.DefaultDisplay;
var isPortrait = (display.Rotation == SurfaceOrientation.Rotation0 || display.Rotation == SurfaceOrientation.Rotation180);
int previewWidth = orgPreviewWidth;
int previewHeight = orgPreviewHeight;
if(isPortrait) {
previewWidth = orgPreviewHeight;
previewHeight = orgPreviewWidth;
}
// determine which part to crop
float widthRatio = (float)width / previewWidth;
float heightRatio = (float)height / previewHeight;
float scaleX;
float scaleY;
if(widthRatio > heightRatio) {
// height must be cropped
scaleX = 1;
scaleY = widthRatio * ((float)previewHeight / height);
} else {
// width must be cropped
scaleX = heightRatio * ((float)previewWidth / width);
scaleY = 1;
}
Android.Graphics.Matrix matrix = new Android.Graphics.Matrix();
matrix.SetScale(scaleX, scaleY);
_textureView.SetTransform(matrix);
float scaledWidth = width * scaleX;
float scaledHeight = height * scaleY;
float dx = (width - scaledWidth) * 0.5f;
float dy = (height - scaledHeight) * 0.5f;
_textureView.TranslationX = dx;
_textureView.TranslationY = dy;
}
The scaling & calculation of dx & dy work perfectly fine on older android devices but the devices I have at my disposal with API level 23 throw unexpected behaviour.
The galaxy S3 displays it correctly:
But on the S7:
The phone cuts off a lot of the image, despite positioning it correctly. This makes me believe the bottom part is not being rendered where on older devices it is. Can anyone confirm this and point me in the correct position to fix this issue?
After long testing I figured out the issue was due to the SetTransform method. I was setting my scale using the matrix but this somehow rendered my texture & ignored the TranslationX & TranslationY. Removing the matrix & replacing it by
float scaledWidth = width * scaleX;
float scaledHeight = height * scaleY;
float dx = (width - scaledWidth) * 0.5f;
float dy = (height - scaledHeight) * 0.5f;
_textureView.ScaleX = scaleX;
_textureView.ScaleY = scaleY;
_textureView.TranslationX = dx;
_textureView.TranslationY = dy;
Fixed my issue of rendering wrongly on certain android devices.

How can I make quarter indicators in Android Wear Watch Face?

It's no secret. My math skills aren't that impressive.
I'm developing my own Wear Watchface. But I want to draw a Drawline to the center of the screen for every 10 minute place on the watch. (See the 500px analog example).
By using the Google example code I can achieve this but only an entire line from the side of the screen to the center. But I want it to be like 5% (or a fixed amount of pixels) in length of that like in the 500px watchface. This is Google's code for drawing the second dial:
float centerX = width / 2f;
float centerY = height / 2f;
float secRot = mTime.second / 30f * (float) Math.PI;
float secLength = centerX - 20;
float secX = (float) Math.sin(secRot) * secLength;
float secY = (float) -Math.cos(secRot) * secLength;
canvas.drawLine(centerX, centerY, centerX + secX, centerY + secY, mHandPaint);
By changing the mTime.second I can draw from a specific second.
Found the solution, here's a snippet:
int teller_minuut_stip = 0; //Current minute
float secRot_stip = teller_minuut_stip / 30f * (float) Math.PI;
float secRot_stip_klein = teller_minuut_stip / 30f * (float) Math.PI;
float secLength_stip = centerX - 10;
float secX = (float) Math.sin(secRot_stip) * secLength_stip;
float secY = (float) -Math.cos(secRot_stip) * secLength_stip;
float secLength_stip_klein = centerX - 140;
float secX_klein = (float) Math.sin(secRot_stip_klein) * secLength_stip_klein;
float secY_klein = (float) -Math.cos(secRot_stip_klein) * secLength_stip_klein;
float eindpunt_x = centerX + secX;
float eindpunt_y = centerY + secY;
float lijn_x = eindpunt_x - secX_klein;
float lijn_y = eindpunt_y - secY_klein;
canvas.drawLine(eindpunt_x, eindpunt_y, lijn_x, lijn_y, datePaint_cirkel_kleurtien);

Android: How to find the position the mouse pointer hit on the object in 3d space

I have trouble of finding the hitpoint on the 3d space. I currently have viewport data which is the screen size, the depth from camera to the object (object is = plane parallel with the screen), and the mouse pointer on the screen.
I am using opengl es 2.0, how do if ind the hit point on the object which was parallel with the camera.
Setup for my camera:
App app = App.getInstance();
app.setWidth(width);
app.setHeight(height);
float widthDP = width;
float heightDP = height;
float ratio = widthDP / heightDP ;
mShader = new SimpleShader();
Polygon poly = Polygon.Builder()
.addVertex(new Point(widthDP*6,heightDP*2))
.addVertex(new Point(widthDP*6, 0))
.addVertex(new Point(0, heightDP*2))
.addVertex(new Point(0, 0)).build();
Environment environment = Environment.getInstance();
environment.setPolgyon(poly);
environment.setScreenSize((int)widthDP, (int)heightDP);
Camera camera = Camera.getInstance();
camera.setShader(mShader);
camera.setEye(new Point3D(widthDP*2,heightDP, -heightDP));
camera.setLook(new Point3D(widthDP*2,heightDP,0));
camera.setUp(new Point3D(0,1,0));
environment.setCamera(camera);
Matrix.frustumM(camera.getProjectionMatrix(), 0, -ratio, ratio, -1, 1, 1, 1000);
This is the code I followed from the link: http://schabby.de/picking-opengl-ray-tracing/
App app = App.getInstance();
Vector3D lookAt = new Vector3D(look.x, look.y, look.z);
Vector3D position = new Vector3D(eye.x, eye.y, eye.z);
Vector3D up = new Vector3D(this.up.x, this.up.y, this.up.z);
Vector3D view = Vector3D.sub(lookAt, position);
view.normalize();
Vector3D h = view.cross(up);
h.normalize();
Vector3D v = h.cross(view);
v.normalize();
float rad = (float) (45.0f * Math.PI / 180.0f);
float vLength = (float) Math.tan( rad / 2 ) * 1;
float hLength = vLength * (app.getWidth() / app.getHeight());
v.mult(vLength);
h.mult(hLength);
//point.x = app.getWidth() - point.x;
//point.y = app.getHeight() - point.y;
point.x += app.getWidth() / 2;
point.y += app.getHeight() / 2;
//point.x *= -1;
//point.y *= -1;
Log.w("point", "Width x="+app.getWidth()+" y="+app.getHeight());
point.x /= app.getWidth() / 2;
point.y /= app.getHeight() / 2;
view.mult(1);
h.mult(point.x);
v.mult(point.y);
view.add(h);
view.add(v);
Vector3D pos = Vector3D.add(position, view);
Vector3D dir = Vector3D.sub(pos, position);
float s = -1*pos.z / dir.z;
float[] newPoint = new float[2];
newPoint[0] = pos.x + dir.x *s;
newPoint[1] = pos.y + dir.y *s;
return new Point(newPoint[0], newPoint[1]);

android 3d vertical carousel view

I am using http://www.codeproject.com/Articles/146145/Android-3D-Carousel code to create a vertical carousel view.i can see the vertical carousel using below changes in the code but center item is not properly placed in the screen and if the list items size increased, diameter moves upwards.
private void setUpChild(CarouselImageView child, int index, float angleOffset) {
// Ignore any layout parameters for child, use wrap content
addViewInLayout(child, -1 /*index*/, generateDefaultLayoutParams());
child.setSelected(index == mSelectedPosition);
int h;
int w;
if (mInLayout)
{
h = (getMeasuredHeight() - getPaddingBottom()-getPaddingTop())/3;
w = getMeasuredWidth() - getPaddingLeft() - getPaddingRight()/3;
}
else
{
h = (getMeasuredHeight() - getPaddingBottom()-getPaddingTop())/3;
w = getMeasuredWidth() - getPaddingLeft() - getPaddingRight()/3;
}
child.setCurrentAngle(angleOffset);
// modify the diameter.
Calculate3DPosition(child, w*(getAdapter().getCount()/4), angleOffset);
// Measure child
child.measure(w, h);
int childLeft;
// Position vertically based on gravity setting
int childTop = calculateTop(child, true);
childLeft = 0;
child.layout(childLeft, childTop, w, h);
}
change in calculate3position function as below
float x = (float) (-diameter/2 * Math.cos(angleOffset) * 0.00001);
float z = diameter/2 * (1.0f - (float)Math.cos(angleOffset));
float y = (float) (diameter/2 * Math.sin(angleOffset)) + diameter/2 - child.getWidth();
child.setX(x);
child.setZ(z);
child.setY(y);
I think that this calculation:
float x = (float) (-diameter/2 * Math.cos(angleOffset) * 0.00001);
float z = diameter/2 * (1.0f - (float)Math.cos(angleOffset));
float y = (float) (diameter/2 * Math.sin(angleOffset)) + diameter/2 - child.getWidth();
should be this:
float x = 0.0f
float z = diameter/2.0f * (1.0f - (float)Math.cos(angleOffset));
float y = (diameter/2.0f * Math.sin(angleOffset)) + diameter/2.0f - child.getHeight()/2.0f;
Your x position should always be zero, and your y position should be based on the sin, and should be offset by 1/2 of the height of the child instead of 1/2 of the width.
Hello try this code and replace with this code in your Calculate3DPosition method
angleOffset = angleOffset * (float) (Math.PI / 180.0f);
float y = (float) (((diameter * 60) / 100) * Math.sin(angleOffset)) + ((diameter * 50) / 100);
float z = diameter / 2 * (1.0f - (float) Math.cos(angleOffset));
float x = (float) (((diameter * 5) / 100) * Math.cos(angleOffset) * 0.3);
child.setItemX(x);
child.setItemZ((z * 30) / 100);
child.setItemY(-(y));
its solve my problem please try this one

Categories

Resources