Help with Diamond Square algorithm implementation - c++

I'm trying to implement the Diamond-square algorithm, but the problem is only part of the bitmap is being filled and I'm not sure what's wrong. I'm doing it recursively:
GLuint CreateDsquare()
{
std::vector<GLubyte> pdata(256 * 256 * 4);
vector2i loc;
vector2i sz;
GLubyte val;
sz.x = 256;
sz.y = 256;
val = rand() % 255;
loc = vector2i(0,0);
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
loc.x = sz.x - 1;
loc.y = 0;
val = rand() % 255;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
loc.x = sz.x - 1;
loc.y = sz.y - 1;
val = rand() % 255;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
loc.x = 0;
loc.y = sz.y - 1;
val = rand() % 255;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
RescursiveDiamond(pdata,sz,vector2i(0,0));
return CreateTexture(pdata,256,256);
}
void RescursiveDiamond(std::vector<GLubyte> &pdata,vector2i psz, vector2i offset)
{
int val;
int newnum;
if(psz.x < 2 && psz.y < 2)
{
return;
}
vector2i loc;
vector2i sz = psz;
std::vector<int> pvertz(4,0);
loc = offset;
pvertz[0] = pdata[loc.y * 4 * sz.x + loc.x * 4 + 0];
loc.x = offset.x + (psz.x - 1);
loc.y = offset.y;
pvertz[1] = pdata[loc.y * 4 * sz.x + loc.x * 4 + 0];
loc.x = offset.x + (psz.x - 1);
loc.y = offset.y + (psz.y - 1);
pvertz[2] = pdata[loc.y * 4 * sz.x + loc.x * 4 + 0];
loc.x = offset.x;
loc.y = offset.y + (psz.y - 1);
pvertz[3] = pdata[loc.y * 4 * sz.x + loc.x * 4 + 0];
val = (pvertz[0] + pvertz[1]) / 2;
val += 255;
loc.x = (offset.x + (sz.x - 1)) / 2;
loc.y = offset.y;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
val = (pvertz[1] + pvertz[2]) / 2;
val += 255;
loc.x = (offset.x + (sz.x)) - 1;
loc.y = ((offset.y + (sz.y)) / 2) - 1;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
val = (pvertz[3] + pvertz[2]) / 2;
val += 255;
loc.x = ((offset.x + (sz.x)) / 2) - 1;
loc.y = (offset.y + (sz.y)) - 1 ;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
val = (pvertz[0] + pvertz[3]) / 2;
val += 255;
loc.x = offset.x;
loc.y = (offset.y + (sz.y)) - 1 ;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
//center
val = (pdata[(offset.y) * 4 * sz.x + ((offset.x + (sz.x - 1)) / 2) * 4 + 0] +
pdata[(offset.y + (sz.y - 1)) * 4 * sz.x + ((offset.x + (sz.x - 1)) / 2) * 4 + 0]) / 2;
int ad = (rand() % 12) - 6;
if(val + ad < 0)
{
val = 0;
}
else
{
val += ad;
}
val += 255;
loc.x = ((offset.x + (sz.x) ) / 2) - 1;
loc.y = ((offset.y + (sz.y)) / 2) - 1;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 0] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 1] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 2] = val;
pdata[loc.y * 4 * sz.x + loc.x * 4 + 3] = 255;
vector2i newoffset;
vector2i newparentsz;
newoffset = offset;
newparentsz = (psz / 2);
RescursiveDiamond(pdata,newparentsz,newoffset);
newoffset.x = offset.x + (newparentsz.x);
newoffset.y = offset.y;
RescursiveDiamond(pdata,newparentsz,newoffset);
newoffset.x = offset.x;
newoffset.y = offset.y + (newparentsz.y);
RescursiveDiamond(pdata,newparentsz,newoffset);
newoffset.x = offset.x + (newparentsz.x);
newoffset.y = offset.y + (newparentsz.y);
RescursiveDiamond(pdata,newparentsz,newoffset);
}
I suspect that I might be recalling the function with the wrong offset or something.
offset is like the top left and then there is the size, together these nake the square.
what could be wrong here?
Thanks

Ok, first, Let's start with cleaning up the violations of D-R-Y, your code should read more along the lines of this:
int position( _y, _x, _offset ){
return _y * _x * 4 + _x * 4 + _offset;
}
void adjust(vector<GLubyte> &pdata, _x, _y){
GLubyte val = rand() % 255;
for(int j=0; j < 3; ++j){
pdata[ position( _y, _x, j ) ] = val;
}
pdata[ position( _y, _x, 3 ) ] = 255;
}
GLuint CreateDsquare(){
vector2i sz;
sz.x = 256;
sz.y = 256;
adjust( pdata, 0, 0 );
adjust( pdata, sz.x - 1, 0 );
adjust( pdata, sz.x -1, sz.y - 1 );
adjust( pdata, 0, sz.y - 1 );
RescursiveDiamond(pdata,sz,vector2i(0,0));
return CreateTexture(pdata,256,256);
}
Can you format the rest of it down so it's more readable/understandable? Then I'll update so that I can better answer your question (if someone hasn't beaten me to it or the woman decides I've had enough computer time.)

When you are calculating the offset into your height map for each row (y * pitch) you are using the current size of the square you are calculating instead of the actual pitch which is 256. The deeper you go into the recursion you are writing into your height map as if it was smaller and smaller until the last step of your recursion is writing into pixel (0, 0).

Related

Converting RGB to Luv

i'm trying to convert an rgb image to Luv, i have some problem. The L component is good, but when i show the u and v component both are black(all pixels have value 0).
for (int i = 0; i<height; i++)
for (int j = 0; j<width; j++)
{
Vec3b v3 = src.at<Vec3b>(i, j);
float b = ((float)v3[0]) / 255;
float g = ((float)v3[1]) / 255;
float r = ((float)v3[2]) / 255;
float x = r * 0.412453 + g * 0.357580 + b * 0.180423;
float y = r * 0.212671 + g * 0.715160 + b * 0.072169;
float z = r * 0.019334 + g * 0.119193 + b * 0.950227;
//L
if (y > 0.008856) {
l_mat.at<uchar>(i, j) = 255 / 100 * (116 * pow(y, 1.0 / 3.0));
dst.at<Vec3b>(i, j)[0] = 255 / 100 * (116 * pow(y, 1.0 / 3.0));
// printf("%d / " , l_mat.at<uchar>(i, j));
}
else {
l_mat.at<uchar>(i, j) = 255 / 100 * (903.3 * y);
dst.at<Vec3b>(i, j)[0] = 255 / 100 * (903.3 * y);
}
float u = 4 * x / (x + 15 * y + 3 * z);
float v = 9 * y / (x + 15 * y + 3 * z);
//printf("u: %.2f , v:%.2f || ", u, v);
//U
u_mat.at<uchar>(i, j) = 255 / 354 * (13 * l_mat.at<uchar>(i, j)*(u - 0.19793943) + 134);
//printf("%d / ", u_mat.at<uchar>(i, j));
dst.at<Vec3b>(i, j) = 255 / 354 * (13 * l_mat.at<uchar>(i, j)*(u - 0.19793943) + 134);
//v
v_mat.at<uchar>(i, j) = 255 / 262 * (13 * l_mat.at<uchar>(i, j)*(v - 0.46831096)+140);
dst.at<Vec3b>(i, j) = 255 / 262 * (13 * l_mat.at<uchar>(i, j)*(v - 0.46831096) + 140);
}
I have to do the conversions pixel by pixel, i can't use cvtcolor.

AVX512 illegal instruction

In my previous post I explain that I am starting with AVX to speed up my code (please, note that although there are parts in common this post refers to AVX512 and the previous one to AVX2 which as far as I know are slightly different and need different compiling flags). After experimenting with AVX2 I decided to try with AVX512 and changed my AVX2 function:
void getDataAVX2(u_char* data, size_t cols, std::vector<double>& info)
{
__m256d dividend = _mm256_set_pd(1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0);
info.resize(cols);
__m256d result;
for (size_t i = 0; i < cols / 4; i++)
{
__m256d divisor = _mm256_set_pd((double(data[4 * i + 3 + cols] << 8) + double(data[4 * i + 2 * cols + 3])),
(double(data[4 * i + 2 + cols] << 8) + double(data[4 * i + 2 * cols + 2])),
(double(data[4 * i + 1 + cols] << 8) + double(data[4 * i + 2 * cols + 1])),
(double(data[4 * i + cols] << 8) + double(data[4 * i + 2 * cols])));
result = _mm256_sqrt_pd(_mm256_mul_pd(divisor, dividend));
info[size_t(4 * i)] = result[0];
info[size_t(4 * i + 1)] = result[1];
info[size_t(4 * i + 2)] = result[2];
info[size_t(4 * i + 3)] = result[3];
}
}
for what I think should be its equivalent:
void getDataAVX512(u_char* data, size_t cols, std::vector<double>& info)
{
__m512d dividend = _mm512_set_pd(1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0);
info.resize(cols);
__m512d result;
for (size_t i = 0; i < cols / 8; i++)
{
__m512d divisor = _mm512_set_pd((double(data[4 * i + 7 + cols] << 8) + double(data[4 * i + 2 * cols + 7])),
(double(data[4 * i + 6 + cols] << 8) + double(data[4 * i + 2 * cols + 6])),
(double(data[4 * i + 5 + cols] << 8) + double(data[4 * i + 2 * cols + 5])),
(double(data[4 * i + 4 + cols] << 8) + double(data[4 * i + 2 * cols + 4])),
(double(data[4 * i + 3 + cols] << 8) + double(data[4 * i + 2 * cols + 3])),
(double(data[4 * i + 2 + cols] << 8) + double(data[4 * i + 2 * cols + 2])),
(double(data[4 * i + 1 + cols] << 8) + double(data[4 * i + 2 * cols + 1])),
(double(data[4 * i + cols] << 8) + double(data[4 * i + 2 * cols])));
result = _mm512_sqrt_pd(_mm512_mul_pd(divisor, dividend));
info[size_t(4 * i)] = result[0];
info[size_t(4 * i + 1)] = result[1];
info[size_t(4 * i + 2)] = result[2];
info[size_t(4 * i + 3)] = result[3];
info[size_t(4 * i + 4)] = result[4];
info[size_t(4 * i + 5)] = result[5];
info[size_t(4 * i + 6)] = result[6];
info[size_t(4 * i + 7)] = result[7];
}
}
which in a non AVX form is:
void getData(u_char* data, size_t cols, std::vector<double>& info)
{
info.resize(cols);
for (size_t i = 0; i < cols; i++)
{
info[i] = sqrt((double(data[cols + i] << 8) + double(data[2 * cols + i])) / 64.0);
;
}
}
After compiling the code I get the following error:
Illegal instruction (core dumped)
To my surprise, this error occurs in the call of sqrt in the getData function. If I remove the sqrt call then the error appears further forward, in the __m512d divisor = _mm512_set_pd((d..... Any ideas on what is happening?
Here is the full example.
Thank you very much.
I am compiling with c++ (7.3.0) with the following options -std=c++17 -Wall -Wextra -O3 -fno-tree-vectorize -mavx512f. I have checked as explained here and my CPU (Intel(R) Core(TM) i7-4710HQ CPU # 2.50GHz) supports AVX2. Should the list have AVX-512 to indicate support for this?
I don't think AVX-512 instructions are supported on your system (CPU). Taking the official documentation into consideration; it only mentions AVX-2. A newer CPU would indicate AVX-512 perfectly fine. Both can be found under the "Instruction Set Extensions" section.

C++/3D Terrain: std::vector pushback() crashes with c0000374

When attempted to push back a vector of UINT, the progrma crashes with Critical error detected c0000374. Below is the initial code:
void Terrain::CreateIndexList(UINT Width, UINT Height){
UINT sz_iList = (Width - 1)*(Height - 1) * 6;
UINT *iList = new UINT[sz_iList];
for (int i = 0; i < Width; i++){
for (int j = 0; j < Height; j++){
iList[(i + j * (Width - 1)) * 6] = ((UINT)(2 * i));
iList[(i + j * (Width - 1)) * 6 + 1] = (UINT)(2 * i + 1);
iList[(i + j * (Width - 1)) * 6 + 2] = (UINT)(2 * i + 2);
iList[(i + j * (Width - 1)) * 6 + 3] = (UINT)(2 * i + 2);
iList[(i + j * (Width - 1)) * 6 + 4] = (UINT)(2 * i + 1);
iList[(i + j * (Width - 1)) * 6 + 5] = (UINT)(2 * i + 3);
}
}
for (int i = 0; i < sz_iList; i++){
Geometry.IndexVertexData.push_back(iList[i]);
}
delete[] iList;
}
The goal is to take the generated indices from the iList array and fill the Geometry.IndexVertexData vector array. While debugging this, I've created several other implementations of this:
//After creating the iList array:
Geometry.IndexVertexData.resize(sz_iList); //Fails with "Vector subscript out of range?"
UINT in = 0;
for (int i = 0; i < Width; i++){
for (int j = 0; j < Height; j++){
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 1] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 2] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 3] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 4] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 5] = iList[in];
in++;
}
}
And a final, direct to vector implementation:
Geometry.IndexVertexData.reserve(sz_iList);
for (int index = 0; index < sz_iList; index+=6) {
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6] = ((UINT)(2 * i));
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 1] = (UINT)(2 * i + 1);
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 2] = (UINT)(2 * i + 2);
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 3] = (UINT)(2 * i + 2);
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 4] = (UINT)(2 * i + 1);
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 5] = (UINT)(2 * i + 3);
}
sz_iList has a final value of 2166, resultant from a grid of 20x20 (400 total points) and is used to initialize sizes. In all cases, the vector array would not fully fill, crashing with Critical error detected c0000374. Am I doing something wrong?
Your sz_iList doesn't appear to be big enough. Let's use a simple example of Width = Height = 2;, then sz_iList = (2 - 1) * (2 - 1) * 6 = 6, right? But in your nested loops, the last iteration occurs when i = j = 1 (i is one less than Width and j is one less than Height), where (in the last line of your loop), you try to access element (i + j * (Width - 1)) * 6 + 5 = (1 + 1 * (2 - 1)) * 6 + 5 = (1 + 1 * 1) * 6 + 5 = 2 * 6 + 5 = 17, which is bigger than the size of your array. This results in undefined behavior.

Fast input and output in c++

While searching the web for fast i/o in c++, this is the "best" (according to me) that I have come across
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
class FastInput {
public:
FastInput() {
m_dataOffset = 0;
m_dataSize = 0;
m_v = 0x80000000;
}
uint32_t ReadNext() {
if (m_dataOffset == m_dataSize) {
int r = read(0, m_buffer, sizeof(m_buffer));
if (r <= 0) return m_v;
m_dataOffset = 0;
m_dataSize = 0;
int i = 0;
if (m_buffer[0] < '0') {
if (m_v != 0x80000000) {
m_data[m_dataSize++] = m_v;
m_v = 0x80000000;
}
for (; (i < r) && (m_buffer[i] < '0'); ++i);
}
for (; i < r;) {
if (m_buffer[i] >= '0') {
m_v = m_v * 10 + m_buffer[i] - 48;
++i;
} else {
m_data[m_dataSize++] = m_v;
m_v = 0x80000000;
for (i = i + 1; (i < r) && (m_buffer[i] < '0'); ++i);
}
}
}
return m_data[m_dataOffset++];
}
public:
uint8_t m_buffer[32768];
uint32_t m_data[16384];
size_t m_dataOffset, m_dataSize;
uint32_t m_v;
};
class FastOutput {
public:
FastOutput() {
m_dataOffset = 0;
}
~FastOutput() {
}
void Flush() {
if (m_dataOffset) {
if (write(1, m_data, m_dataOffset));
m_dataOffset = 0;
}
}
void PrintUint(uint32_t v, char d) {
if (m_dataOffset + 11 > sizeof(m_data)) Flush();
if (v < 100000) {
if (v < 1000) {
if (v < 10) {
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 1;
} else if (v < 100) {
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 2;
} else {
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 3;
}
} else {
if (v < 10000) {
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 4;
} else {
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 5;
}
}
} else {
if (v < 100000000) {
if (v < 1000000) {
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 6;
} else if (v < 10000000) {
m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 7;
} else {
m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 8;
}
} else {
if (v < 1000000000) {
m_data[m_dataOffset + 8] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 9;
} else {
m_data[m_dataOffset + 9] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 8] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 10;
}
}
}
m_data[m_dataOffset++] = d;
}
void PrintChar(char d) {
if (m_dataOffset + 1 > sizeof(m_data)) Flush();
m_data[m_dataOffset++] = d;
}
void ReplaceChar(int offset, char d) {
m_data[m_dataOffset + offset] = d;
}
public:
uint8_t m_data[32768];
size_t m_dataOffset;
};
int main()
{
;
}
But, it was nothing written about how to take input or give output.
It would be of great help, if you can tell how to take input a integer and a c++ string and give output, with an example.
The following code reads an unsigned integer value from standard input:
FastInput fi;
uint32_t value = fi.ReadNext();
To write an unsigned integer value to standard output:
FastOutput fo;
fo.PrintUint(123456, '\n');
fo.Flush();
But seriously: Forget about these classes. I cannot image how this class could be in any way useful for whatever you're trying to achieve.

Gradient algorithm produces little white dots

I'm working on an algorithm to generate point to point linear gradients. I have a rough proof of concept implementation done:
GLuint OGLENGINEFUNCTIONS::CreateGradient( std::vector<ARGBCOLORF> &input,POINTFLOAT start, POINTFLOAT end, int width, int height,bool radial )
{
std::vector<POINT> pol;
std::vector<GLubyte> pdata(width * height * 4);
std::vector<POINTFLOAT> linearpts;
std::vector<float> lookup;
float distance = GetDistance(start,end);
RoundNumber(distance);
POINTFLOAT temp;
float incr = 1 / (distance + 1);
for(int l = 0; l < 100; l ++)
{
POINTFLOAT outA;
POINTFLOAT OutB;
float dirlen;
float perplen;
POINTFLOAT dir;
POINTFLOAT ndir;
POINTFLOAT perp;
POINTFLOAT nperp;
POINTFLOAT perpoffset;
POINTFLOAT diroffset;
dir.x = end.x - start.x;
dir.y = end.y - start.y;
dirlen = sqrt((dir.x * dir.x) + (dir.y * dir.y));
ndir.x = static_cast<float>(dir.x * 1.0 / dirlen);
ndir.y = static_cast<float>(dir.y * 1.0 / dirlen);
perp.x = dir.y;
perp.y = -dir.x;
perplen = sqrt((perp.x * perp.x) + (perp.y * perp.y));
nperp.x = static_cast<float>(perp.x * 1.0 / perplen);
nperp.y = static_cast<float>(perp.y * 1.0 / perplen);
perpoffset.x = static_cast<float>(nperp.x * l * 0.5);
perpoffset.y = static_cast<float>(nperp.y * l * 0.5);
diroffset.x = static_cast<float>(ndir.x * 0 * 0.5);
diroffset.y = static_cast<float>(ndir.y * 0 * 0.5);
outA.x = end.x + perpoffset.x + diroffset.x;
outA.y = end.y + perpoffset.y + diroffset.y;
OutB.x = start.x + perpoffset.x - diroffset.x;
OutB.y = start.y + perpoffset.y - diroffset.y;
for (float i = 0; i < 1; i += incr)
{
temp = GetLinearBezier(i,outA,OutB);
RoundNumber(temp.x);
RoundNumber(temp.y);
linearpts.push_back(temp);
lookup.push_back(i);
}
for (unsigned int j = 0; j < linearpts.size(); j++) {
if(linearpts[j].x < width && linearpts[j].x >= 0 &&
linearpts[j].y < height && linearpts[j].y >=0)
{
pdata[linearpts[j].x * 4 * width + linearpts[j].y * 4 + 0] = (GLubyte) j;
pdata[linearpts[j].x * 4 * width + linearpts[j].y * 4 + 1] = (GLubyte) j;
pdata[linearpts[j].x * 4 * width + linearpts[j].y * 4 + 2] = (GLubyte) j;
pdata[linearpts[j].x * 4 * width + linearpts[j].y * 4 + 3] = (GLubyte) 255;
}
}
lookup.clear();
linearpts.clear();
}
return CreateTexture(pdata,width,height);
}
It works as I would expect most of the time, but at certain angles it produces little white dots. I can't figure out what does this.
This is what it looks like at most angles (good) http://img9.imageshack.us/img9/5922/goodgradient.png
But once in a while it looks like this (bad): http://img155.imageshack.us/img155/760/badgradient.png
What could be causing the white dots?
Is there maybe also a better way to generate my gradients if no solution is possible for this?
Thanks
I think you have a bug indexing into the pdata byte vector. Your x domain is [0, width) but when you multiply out the indices you're doing x * 4 * width. It should probably be x * 4 + y * 4 * width or x * 4 * height + y * 4 depending on whether you're data is arranged row or column major.