I'm new to OpenGl ES. I'm trying to build a sphere not using any manuals, tutrials...
I have succeded to achieve my goal. I can draw a sphere using TRIANGLE_STRIP. And the number of meridians/horizontals I specify before drawing.
Everything works fine when I have less then 256 indexes for vertixes. I tried to use GLushort instead of GLubyte but the picture changed a lot.
GLubyte *Indices;
...
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * (meridians * (horizontals * 2 + 2)), Indices, GL_STATIC_DRAW);
...
Indices = malloc(sizeof(GLubyte) * (meridians * (horizontals * 2 + 2)));
Thats where I change byte to short.
Current project on GitHub
What should I do?
Here are the pictures where I change byte to short
Looks like you forgot to change the following line:
glDrawElements(GL_TRIANGLE_STRIP, (meridians * (horizontals * 2 + 2)), GL_UNSIGNED_BYTE, 0);
This indicates that there are a number of indices to be render, and each one is the size of an unsigned byte (most likely 8 bits, but the actual number is platform specific...very very very rarely is it not 8 bits though). However, you have filled an array of indices that are the size of unsigned shorts (probably 16 bits) so what will end up happening is that each of your numbers will be read twice. Once with the "first" 8-bits, and once with the "second" (endian will determine whether high or low order comes first). Since a lot of your indices (the majority?) are under 255, then there are going to be a lot of vertices that turn into "0" since the higher 8 bits are all 0. On top of that, you will only render half of your indices.
So, you need to indicate to OpenGL that it needs to draw these indices as unsigned shorts instead by changing the above line to this:
glDrawElements(GL_TRIANGLE_STRIP, (meridians * (horizontals * 2 + 2)), GL_UNSIGNED_SHORT, 0);
Related
I'm working with a Gyroscope (L3GD20) with a 2000DPS
Correct me if their is a mistake,
I start by reading the values High and Low for the 3 axes and concatenate them. Then I multiply every value by 0.07 to convert them into DPS.
My main goal is to track the angle over time, so I simply implemented a Timer which reads the data every dt = 10 ms
to integrate ValueInDPS * 10ms, here is the code line I'm using :
angleX += (resultGyroX)*dt*0.001; //0.001 to get dt in [seconds]
This should give us the value of the angle in [degree] am I right ?
The problem is that the values I'm getting are a little bit weird, for example when I make a rotation of 90°, I get something like 70°...
Your method is a recipe for imprecision and accumulated error.
You should avoid using floating point (especially if there is no FPU), and especially also if this code is in the timer interrupt handler.
you should avoid unnecessarily converting to degrees/sec on every sample - that conversion is needed only for presentation, so you should perform it only when you need to need the value - internally the integrator should work in gyro sample units.
Additionally, if you are doing floating point in both an ISR and in a normal thread and you have an FPU, you may also encounter unrelated errors, because FPU registers are not preserved and restored in an interrupt handler. All in all floating point should only be used advisedly.
So let us assume you have a function gyroIntegrate() called precisely every 10ms:
static int32_t ax = 0
static int32_t ay = 0
static int32_t az = 0
void gyroIntegrate( int32_t sample_x, int32_t sample_y, int32_t sample_z)
{
ax += samplex ;
ay += sampley ;
az += samplez ;
}
Not ax etc. are the integration of the raw sample values and so proportional to the angle relative to the starting position.
To convert ax to degrees:
degrees = ax × r-1 × s
Where:
r is the gyro resolution in degrees per second (0.07)
s is the sample rate (100).
Now you would do well to avoid floating point and here it is entirely unnecessary; r-1 x s is a constant (1428.571 in this case). So to read the current angle represented by the integrator, you might have a function:
#define GYRO_SIGMA_TO_DEGREESx10 14286
void getAngleXYZ( int32_t* int32_t, int32_t* ydeg, int32_t* zdeg )
{
*xdeg = (ax * 10) / GYRO_SIGMA_TO_DEGREESx10 ;
*ydeg = (ax * 10) / GYRO_SIGMA_TO_DEGREESx10 ;
*zdeg = (ax * 10) / GYRO_SIGMA_TO_DEGREESx10 ;
}
getAngleXYZ() should be called from the application layer when you need a result - not from the integrator - you do the math at the point of need and have CPU cycles left to do more useful stuff.
Note that in the above I have ignored the possibility of arithmetic overflow of the integrator. As it is it is good for approximately +/-1.5 million degrees +/-4175 rotations), so it may not be a problem in some applications. You could use an int64_t or if you are not interested in the number of rotations, just the absolute angle then, in the integrator:
ax += samplex ;
ax %= GYRO_SIGMA_360 ;
Where GYRO_SIGMA_360 equals 514286 (360 x s / r).
Unfortunately, MEMs sensor math is quite complicated.
I would personally use ready libraries provided by the STM https://www.st.com/en/embedded-software/x-cube-mems1.html.
I actually use them, and the results are very good.
I am using GNU nettle library. I have the following code:
#include <nettle/curve25519.h>
uint8_t result[32], one[32];
for(auto &i : one) i = 0;
one[31] = 1;
curve25519_mul_g(result, one);
In the code, I multiplied 1 with the base point. The base point's x-coordinate is 9, so I would expect the result to be 9.
But instead, it gives me this number:
0xfd3384e132ad02a56c78f45547ee40038dc79002b90d29ed90e08eee762ae715.
Why does this code not generate 9?
Curve25519 clamps some bits of the scalar to 1 or 0. Specifically in Curve25519 scalar multiplication:
the lowest 3 bits are set to 0, to ensure the output point is only in the large subgroup, and
the highest bit (2^254) is set to one, to make sure the implementer does not skip any Montgomery-ladder steps.
After this clamping operation, the scalar multiplication algorithm will be executed. So in Curve25519, a point cannot be multiplied with 1.
In your case, however, there is even more going on. nettle uses a little-endian convention in their code. That is, when you execute
one[31] = 1;
you are actually setting the 2^248 bit to one, not the 2^0 bit. Then the clamped value will become k = 2^254 + 2^248.
The computation [2^254 + 2^248] * (9 : 1) results in 0x15e72a76ee8ee090ed290db90290c78d0340ee4755f4786ca502ad32e18433fd (big endian), which corresponds with your observation.
What and why is the developer adding a hex value of 16, then using the bitwise operations AND followed by a NOT in this line:
size_t bytesPerRow = ((width * 4) + 0x0000000F) & ~0x0000000F;
He comments that "16 byte aligned is good", what does he mean?
- (CGContextRef)createBitmapContext {
CGRect boundingBox = CGPathGetBoundingBox(_mShape);
size_t width = CGRectGetWidth(boundingBox);
size_t height = CGRectGetHeight(boundingBox);
size_t bitsPerComponent = 8;
size_t bytesPerRow = ((width * 4) + 0x0000000F) & ~0x0000000F; // 16 byte aligned is good
ANDing with ~0x0000000F = 0xFFFFFFF0 (aka -16) rounds down to a multiple of 16, simply by resetting those bits that could make it anything other than a multiple of 16 (the 8's, 4's, 2's and 1's).
Adding 15 (0x0000000F) first makes it round up instead of down.
purpose of size_t bytesPerRow = ((width * 4) + 0x0000000F) & ~0x0000000F; is to round up this value to 16 bytes
The goal is to set bytesPerRow to be the smallest multiple of 16 that is capable of holding a row of data. This is done so that a bitmap can be allocated where every row address is 16 byte aligned, i.e. a multiple of 16. There are many possible benefits to alignment, including optimizations that take advantage of it. Some APIs may also require alignment.
The code sets the 4 least significant bits to zero. If the value is an address it will be on an even 16 byte boundary, "16 byte aligned".
this ia a one's complement so
~0x0000000F
becomes
0xFFFFFFF0
and-ing it with another value will clear 4 least significant bits.
This is the kind of thing we used to do all the time "back in the day"!
He's adding 0xf, and then masking out the lower 4 bits (& ~0xf), to make sure the value is rounded up. If he didn't add the 0xf, it would round down.
I've started editing the RaspiStillYUV.c code. I eventually want to process the image I receive, but for now, I'm just working to understand it. Why am I working with YUV instead of RGB? So I can learn something new. I've made minor changes to the function camera_buffer_callback. All I am doing is the following:
fprintf(stderr, "GREAT SUCCESS! %d\n", buffer->length);
The line this is replacing:
bytes_written = fwrite(buffer->data, 1, buffer->length, pData->file_handle);
Now, the dimensions should be 2592 x 1944 (w x h) as set in the code. Working off of Wikipedia (YUV420) I have come to the conclusion that the file size should be w * h * 1.5. Since the Y component has 1 byte of data for each pixel and the U and V components have 1 byte of data for every 4 pixels (1 + 1/4 + 1/4 = 1.5). Great. Doing the math in Python:
>>> 2592 * 1944 * 1.5
7558272.0
Unfortunately, this does not line up with the output of my program:
GREAT SUCCESS! 7589376
That leaves a difference of 31104 bytes.
I figure that the buffer is allocated in fixed size chunks (the output size is evenly divisible by 512). While I would like to understand that mystery, I'm fine with the fixed size chunk explanation.
My question is if I am missing something. Are the extra bytes beyond the expected size meaningful in this format? Should they be ignored? Are my calculations off?
The documentation at this location supports your theory on padding: http://www.raspberrypi.org/wp-content/uploads/2013/07/RaspiCam-Documentation.pdf
Specifically:
Note that the image buffers saved in raspistillyuv are padded to a
horizontal size divisible by 16 (so there may be unused bytes at the
end of each line to made the width divisible by 16). Buffers are also
padded vertically to be divisible by 16, and in the YUV mode, each
plane of Y,U,V is padded in this way.
So my interpretation of this is the following.
The width is 2592 (divisible by 16 so this is ok).
The height is 1944 which is 8 short of being divisible by 16 so an extra 8*2592 are added (also multiplied by 1.5) thus giving your 31104 extra bytes.
Although this kindof helps with the size of the file, it doesn't explain the structure of the YUV output properly. I am having a look at this description to see if this provides a hint to start with: http://en.wikipedia.org/wiki/YUV#Y.27UV420p_.28and_Y.27V12_or_YV12.29_to_RGB888_conversion
From this I believe it is as follows:
Y Channel:
2592 * (1944+8) = 5059584
U Channel:
1296 * (972+4) = 1264896
V Channel:
1296 * (972+4) = 1264896
Giving a sum of :
5059584 + 2*1264896 = 7589376
This makes the numbers add up so only thing left is to confirm if this interpretation is correct.
I am also trying to do the YUV decode (for image comparisons) so if you can confirm if this actually does correspond to what you are reading in the YUV file this would be much appreciated.
You have to read the manual carefully. Buffers are padded to multiples of 16, but colour data is half-size, so your image size needs to be in multiples of 32 to avoid problems with padding breaking external software.
I'm developing an application that should use very few resources and be very fast. And in my app I use an unsigned char* rawData which contains bytes got from image. So in this rawData array I have to keep some bytes and others set to zero. But I'm not permitted to use any loop(otherwise I can just run through each byte and set them zero).
So here are questions.
Q1) Is there any method in Objective C like ZeroMemory in C
Q2) Is there any other ways to set nessecary bytes to zero without using any loop.
Thanks In Advance...
P.S. Can provide some code if nessecary...
If you don't know the size of the buffer, you can't do it without a loop. Even if you don't write the loop yourself, calling something like strlen will result in a loop. I'm counting recursion as a loop here too.
How do you know which bytes to keep and which to set to zero? If these bytes are in known positions, you can use vector operations to zero out some of the bytes and not others. The following example zeros out only the even bytes over the first 64 bytes of rawData:
__m128i zeros = _mm_setzero_si128();
uint8_t mask[] = {8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0, 8, 0};
__m128i sse_mask = _mm_load_si128(mask);
_mm_maskmoveu_si128(zeros, sse_mask, &rawData[0]);
_mm_maskmoveu_si128(zeros, sse_mask, &rawData[16]);
_mm_maskmoveu_si128(zeros, sse_mask, &rawData[32]);
_mm_maskmoveu_si128(zeros, sse_mask, &rawData[48]);
If the high bit of each byte in mask is 1, the corresponding value in zeros will be copied to rawData. You can use a sequence of these masked copies to quickly replace some bytes and not others. The resulting machine code uses SSE operations, so this is actually quite fast. It's not required, but SSE operations will run much faster if rawData is 16-byte aligned.
Sorry if you're targeting ARM. I believe the NEON intrinsics are similar, but not identical.