Recently, I encountered float number corrupted problem in selected Android device. I was wondering, anyone of you had encountered the similar problem as mine, yet have a way to reproduce it with a simplified code block?
I encountered similar problem in Nexus 5 devices. The problem doesn't happen in Genymotion Emulator.
It only happen in selected for loop code block, and it is extremely difficult to re-produce in other code block.
My situation is as follow :-
float rectangleWidth2 = 0.0f;
float startX = (float) (left + xPixelsPerUnit * (xValue - minX));
float stopX = startX;
float _left = startX - rectangleWidth2;
float _right = stopX + rectangleWidth2;
// I expect "_left" and "_right" will have same value. However, at this point,
// "_right" will become an arbitary large value, something like 5.3482353354E20
// However, I expect the value range for "_left" and "_right" within [-1000,1000]
If I change the code to
float _left = startX - rectangleWidth2;
float _right = startX + rectangleWidth2;
// "_left" and "_right" will then having same value.
A "realiable" workaround for my case, is to avoid using float as suggested by reporter. I use double whenever possible, and only perform necessary float casting, when there is a need.
Same problem occur, regardless I'm using Eclipse or Android Studio. I'm going to get Nexus 4 this week, to see whether same problem occur still...
Referenced Links
https://code.google.com/p/android/issues/detail?id=58698
http://www.gamedev.net/topic/660746-problem-with-random-float-value-on-android/
Related
I want to emulate user's walking and count their steps for auto testing.
I tried to search for the solution, but only found simulate the location.
It's pretty easy since in reality this sensor returns a float number describing the number of steps taken by the user since the last reboot while activated.
So that the easiest implementation will include a method which generates just a random float within some realistic constraints (between 1 and 9999 steps):
public float generateStepsCount(){
float minVal = 1.0f;
float maxVal = 9999.0f;
Random rand = new Random();
return rand.nextFloat() * (maxVal - minVal) + minVal;
}
PS: TYPE_STEP_COUNTER has been there since API 19.
I'm an experienced native iOS developer making my first foray into Android through Unity. I'm trying to set up a custom shader, but I'm having some trouble with the Normal maps. I've got them working perfectly in the Unity simulator on my computer, but when I build to an actual device (Samsung Galaxy S8+), the Normal maps don't work at all.
I'm using Mars as my test case. Here's the model running in the simulator on my computer:
And here's a screenshot from my device, running exactly the same code.
I've done a LOT of research, and apparently using Normal maps on Android with Unity is not an easy thing. There are a lot of people asking about it, but almost every answer I've found has said the trick is to override the texture import settings, and force it to be "Truecolor" which seems to be "RGBA 32 Bit" according to Unity's documentation. This hasn't helped me, though.
Another thread suggested reducing the Asino Level to zero, and another suggested turning off Mip Maps. I don't know what either of those are, but neither helped.
Here's my shader code, simplified but containing all references to Normal mapping:
void surf (Input IN, inout SurfaceOutputStandard o) {
half4 d = tex2D (_MainTex , IN.uv_MainTex);
half4 n = tex2D (_BumpMap , IN.uv_BumpMap);
o.Albedo = d.rgb;
o.Normal = UnpackNormal(n);
o.Metallic = 0.0;
o.Smoothness = 0.0;
}
I've seen some threads suggesting replacements for the "UnpackNormal()" function in the shader code, indicating that it might not be the thing to do on Android or mobile in general, but none of the suggested replacements have changed anything for better or worse: the normal maps continue to work in the simulator, but not on the device.
I've even tried making my own normal maps programmatically from a grayscale heightmap, to try to circumvent any import settings I may have done wrong. Here's the code I used, and again it works in the simulator but not on the device.
public Texture2D NormalMap(Texture2D source, float strength = 10.0f) {
Texture2D normalTexture;
float xLeft;
float xRight;
float yUp;
float yDown;
float yDelta;
float xDelta;
normalTexture = new Texture2D (source.width, source.height, TextureFormat.RGBA32, false, true);
for (int y=0; y<source.height; y++) {
for (int x=0; x<source.width; x++) {
xLeft = source.GetPixel (x - 1, y).grayscale * strength;
xRight = source.GetPixel (x + 1, y).grayscale * strength;
yUp = source.GetPixel (x, y - 1).grayscale * strength;
yDown = source.GetPixel (x, y + 1).grayscale * strength;
xDelta = ((xLeft - xRight) + 1) * 0.5f;
yDelta = ((yUp - yDown) + 1) * 0.5f;
normalTexture.SetPixel(x,y,new Color(xDelta,yDelta,1.0f,yDelta));
}
}
normalTexture.Apply();
return normalTexture;
}
Lastly, in the Build Settings, I've got the Platform set to Android and I've tried it using Texture Compression set to both "Don't Override" and "ETC (default)". The former was the original setting and the latter seemed to be Unity's suggestion both by the name and in the documentation.
I'm sure there's just some flag I haven't checked or some switch I haven't flipped, but I can't for the life of me figure out what I'm doing wrong here, or why there would be such a stubborn difference between the simulator and the device.
Can anyone help a Unity newbie out, and show me how these damn Normal maps are supposed to work on Android?
Check under:
Edit -> Project Settings -> Quality
Android is usually set to Fastest.
I want to emulate user's walking and count their steps for auto testing.
I tried to search for the solution, but only found simulate the location.
It's pretty easy since in reality this sensor returns a float number describing the number of steps taken by the user since the last reboot while activated.
So that the easiest implementation will include a method which generates just a random float within some realistic constraints (between 1 and 9999 steps):
public float generateStepsCount(){
float minVal = 1.0f;
float maxVal = 9999.0f;
Random rand = new Random();
return rand.nextFloat() * (maxVal - minVal) + minVal;
}
PS: TYPE_STEP_COUNTER has been there since API 19.
I am working on an application which requires me to manually handle the fling process rather than giving it to the framework. What I want to achieve is basically calculate the amount of pixels a listview moves when it receives a fling action. As the scroll method already provides distance in form of delta, I have handled it easily. But is there a way to get fling distance as only velocity parameter is being passed in the super method.
Note- I have to move another view in accordance with the fling distance, so I need to get it simultaneously just like onScroll provides it.
Thanks.
It is passed 3 years but no answer yet. I found some workaround to achieve it.
Actually it is kind of advanced topic as there are a lot of nuances but basically you can refer to Android source code(OverScroller class in particular) and use this method. You will need to copy it into your class and use it.
private double getSplineFlingDistance(int velocity) {
final double l = getSplineDeceleration(velocity);
final double decelMinusOne = DECELERATION_RATE - 1.0;
return mFlingFriction * PHYSICAL_COEF * Math.exp(DECELERATION_RATE / decelMinusOne * l);
}
Other methods and values can be obtained from the same class.
The link to the source code: https://android.googlesource.com/platform/frameworks/base/+/jb-release/core/java/android/widget/OverScroller.java
Keep in mind that in some devices the value can be different (not too much). Some vendors change the formula depending on their requirements and hardware to make it more smooth.
It looks like the original question ended up with nothing, but it was formulated pretty good, so I landed here and started my research. Here are my results.
My question was: What is the final value at the end of Android standard FlingAnimation?
new FlingAnimation(new FloatValueHolder(0f))
.addEndListener((animation, canceled, value, velocity) -> {
? value
I needed that value before animation start based on the start velocity to make some preparations at the destination point of the FlingAnimation.
Actually I started with Overscroller.java mentioned by #Adil Aliyev. I collected all the portions of code, but the result was way less, that came from the animation.
Then I took a look into FlingAnimation.java in pair with DynamicAnimation.java.
The key function in FlingAnimation.java to start the research was:
MassState updateValueAndVelocity(float value, float velocity, long deltaT) {
After playing with some equations I composed this final code. It gives not totally exact estimation to the last digit, but very close. I will use it for my needs. You are welcome too:
final float DEFAULT_FRICTION = -4.2f;
final float VELOCITY_THRESHOLD_MULTIPLIER = 1000f / 16f;
float mFriction = 1.1f * DEFAULT_FRICTION; // set here friction that you set in .setFriction(1.1f) or 1 by default
final float THRESHOLD_MULTIPLIER = 0.75f;
float mVelocityThreshold = THRESHOLD_MULTIPLIER * VELOCITY_THRESHOLD_MULTIPLIER;
double time = Math.log(mVelocityThreshold / startVelocity) * 1000d / mFriction;
double flingDistance = startVelocity / mFriction * (Math.exp(mFriction * time / 1000d) - 1);
Something seems funny about the way that Android's frustumM works. If I check the OpenGL red book, the matrix generated looks like this:
(source: glprogramming.com)
Songho.ca seems to agree with this:
(source: songho.ca)
However, one component is multiplied by 2 with Android's frustumM, and not in the other example matrices. Here's what it seems to be doing:
Everything seems to functionally match up, except the first row, third column. Why is that being multiplied by two? Here's the lines of code from android.opengl.Matrix's frustumM method that generate the first three elements of the third column:
final float A = 2.0f * ((right + left) * r_width);
final float B = (top + bottom) * r_height;
final float C = (far + near) * r_depth;
With r_width, r_height, r_depth defined as:
final float r_width = 1.0f / (right - left);
final float r_height = 1.0f / (top - bottom);
final float r_depth = 1.0f / (near - far);
The line starting with "final float A" appears to be mistakenly multiplying by 2.
Is this a mistake in Android's code, or am I just missing something? I know that the term cancels out if the frustum is symmetrical. When running the code with an asymmetrical frustum, the generated matrices actually are different and so are the resulting vectors when the same vector is multiplied with those differing matrices.
It's a bug with Android. Please see http://code.google.com/p/android/issues/detail?id=35646
((I'd preffer just to comment but I'm not allowed.))
Thank you guys for the insight. I just had to add
mMyMatrix[8] /= 2f;
after
Matrix.frustrumM(mMyMatrix, ...)
To solve my aspect ratio problems :)
yes, if you call the function with a (-ratio, ratio, -1, 1, 1, 10) parameters set, it does not cause the probelm, but if you call with (right != -1 * left), it makes thing different.
I find this issue when i check the source code. sigh.