Getting NAN when only dealing with integer and float - c++

I am working on an opengl assignment where I have to make a creature (I chose a snowman) move around some terrain. I am trying to make it move around, and I am getting the strangest errors. After printing the numbers out, I frequently get "-1.#QNAN0" as a number. I don't even know what that means. Below is the snowman's update function, constructor, and the header file. I am trying to get 2 numbers to use as velocity and add them to the position while it is set to animate (randomly changing), but I don't understand what errors are causing me to not get numbers out of rand().
Each time that the probability check succeeds, it prints out:
DEBUG: probability check succeeded
-1.#QNAN0 0.000000
or
DEBUG: probability check succeeded
0.000000 0.000000
with about 50% chance of each.
From Snowman.cpp
void Snowman::update(canvas_t texture){
//randomly toggle the walking variable
int probability = rand() % 100;
//printf("DEBUG: probability = %d\n", probability);
if(probability <= 10){
printf("DEBUG: probability check succeeded\n");
walking = !walking;
dx = static_cast<float>(( (rand() % 10) - 5));
dy = static_cast<float>(( (rand() % 10) - 5));
printf("%f %f\n", dx, dy);
}
//code to control movement
if(walking){
animate = true;
x += dx;
y += dy;
constrain(x, 0, texture.width);
constrain(y, 0, texture.height);
}else{
animate = false;
}
//set the height after x and y are resolved
z = getHeight(texture);
}
Snowman::Snowman(canvas_t terrain)
{
wireFrame = false;
animate = false;
armSegments = 2;
animationFrameNumber = 0;
manualUserOffset = 0;
//set its initial position
x = rand() % terrain.width;
y = rand() % terrain.height;
dx = 0;
dy = 0;
}
From Snowman.h
class Snowman
{
public:
Snowman(canvas_t);
~Snowman(void);
void setWireframe(bool);
void toggleWireframe(void);
void setAnimate(bool);
void toggleAnimate(void);
void setArmSegments(int);
void addArmSegment(void);
void subtractArmSegment(void);
void update(canvas_t);
void draw(void);
private:
bool wireFrame;
bool animate;
bool walking;
int armSegments;
int animationFrameNumber;
float manualUserOffset;
float x, y, z;
int dx, dy;
inline float f(void);
inline void drawMouth(int headRadius);
inline void drawFace(int headRadius);
void drawArm(int remainingSegments);
inline void drawBody();
inline float getHeight(canvas_t);
};

dx and dy are ints, but your format specifier %f requires a double or a float. So you have undefined behaviour.

Related

How can I draw filled triangle line by line in C++ console?

I am creating an utility to display graphics in the console. I currently have a method that takes 2 coordinates and draws a line between those two points. Is it possible to create a method based on this that will take 3 coordinates and draw a filled triangle?
I was thinking of drawing 2 lines, and then drawing lines from each point of one line to each point of the other. However, I think that the time complexity of this method will be really bad.
Here is a method that I used to draw a line:
void drawLine(Line line)
{
const bool steep = (fabs(line.end.y - line.begin.y) > fabs(line.end.x - line.begin.x));
if (steep)
{
std::swap(line.begin.x, line.begin.y);
std::swap(line.end.x, line.end.y);
}
if (line.begin.x > line.end.x)
{
std::swap(line.begin, line.end);
}
const double dx = line.end.x - line.begin.x;
const double dy = fabs(line.end.y - line.begin.y);
const double zStepLength = fabs(fabs(line.end.z) - fabs(line.begin.z)) / dx;
double error = dx / 2.0;
const int ystep = (line.begin.y < line.end.y) ? 1 : -1;
const double zstep = (line.begin.z < line.end.z) ? zStepLength : -zStepLength;
for (double x = line.begin.x, z = line.begin.z; x <= line.end.x; x++, z += zstep)
{
if (steep)
{
setPixel({ line.begin.y, x, z }, line.color);
}
else
{
setPixel({ x, line.begin.y, z }, line.color);
}
error -= dy;
if (error < 0)
{
line.begin.y += ystep;
error += dx;
}
}
}

weird inaccuracy in line rotation - c++

I have programmed a simple dragon curve fractal. It seems to work for the most part, but there is an odd logical error that shifts the rotation of certain lines by one pixel. This wouldn't normally be an issue, but after a few generations, at the right size, the fractal begins to look wonky.
I am using open cv in c++ to generate it, but I'm pretty sure it's a logical error rather than a display error. I have printed the values to the console multiple times and seen for myself that there is a one-digit difference between values that are intended to be the exact same - meaning a line may have a y of 200 at one end and 201 at another.
Here is the full code:
#include<iostream>
#include<cmath>
#include<opencv2/opencv.hpp>
const int width=500;
const int height=500;
const double PI=std::atan(1)*4.0;
struct point{
double x;
double y;
point(double x_,double y_){
x=x_;
y=y_;
}};
cv::Mat img(width,height,CV_8UC3,cv::Scalar(255,255,255));
double deg_to_rad(double degrees){return degrees*PI/180;}
point rotate(int degree, int centx, int centy, int ll) {
double radians = deg_to_rad(degree);
return point(centx + (ll * std::cos(radians)), centy + (ll * std::sin(radians)));
}
void generate(point & r, std::vector < point > & verticies, int rotation = 90) {
int curRotation = 90;
bool start = true;
point center = r;
point rot(0, 0);
std::vector<point> verticiesc(verticies);
for (point i: verticiesc) {
double dx = center.x - i.x;
double dy = center.y - i.y;
//distance from centre
int ll = std::sqrt(dx * dx + dy * dy);
//angle from centre
curRotation = std::atan2(dy, dx) * 180 / PI;
//add 90 degrees of rotation
rot = rotate(curRotation + rotation, center.x, center.y, ll);
verticies.push_back(rot);
//endpoint, where the next centre will be
if (start) {
r = rot;
start = false;
}
}
}
void gen(int gens, int bwidth = 1) {
int ll = 7;
std::vector < point > verticies = {
point(width / 2, height / 2 - ll),
point(width / 2, height / 2)
};
point rot(width / 2, height / 2);
for (int i = 0; i < gens; i++) {
generate(rot, verticies);
}
//draw lines
for (int i = 0; i < verticies.size(); i += 2) {
cv::line(img, cv::Point(verticies[i].x, verticies[i].y), cv::Point(verticies[i + 1].x, verticies[i + 1].y), cv::Scalar(0, 0, 0), 1, 8);
}
}
int main() {
gen(10);
cv::imshow("", img);
cv::waitKey(0);
return 0;
}
First, you use int to store point coordinates - that's a bad idea - you lose all accuracy of point position. Use double or float.
Second, your method for drawing fractals is not too stable numericly. You'd better store original shape and all rotation/translation/scale that indicate where and how to draw scaled copies of the original shape.
Also, I believe this is a bug:
for(point i: verices)
{
...
vertices.push_back(rot);
...
}
Changing size of vertices while inside such a for-loop might cause a crash or UB.
Turns out it was to do with floating-point precision. I changed
x=x_;
y=y_;
to
x=std::round(x_);
y=std::round(y_);
and it works.

Blender, Cycles Render, call to function cause app to crash

I am trying to get the get the color of each sample during Cycles rendering. In order to do so, I am calling the following function
void update_bcd_inputs(int x, int y, float sampleR, float sampleG, float sampleB){
float current_valueR = sStats->m_meanImage.getValue(bcd::PixelPosition(x, y), 0); // += sampleR;
float current_valueG = sStats->m_meanImage.getValue(bcd::PixelPosition(x, y), 1); // += sampleG;
float current_valueB = sStats->m_meanImage.getValue(bcd::PixelPosition(x, y), 2); // += sampleB;
sStats->m_meanImage.set(x, y, 0, current_valueR + sampleR);
sStats->m_meanImage.set(x, y, 1, current_valueG + sampleG);
sStats->m_meanImage.set(x, y, 2, current_valueB + sampleB);
}
in blender/intern/cycles/device/device_cpu.cpp
void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
{
float *render_buffer = (float*)tile.buffer;
int start_sample = tile.start_sample;
int end_sample = tile.start_sample + tile.num_samples;
float inv_weight = 1.0f/tile.num_samples;
for(int sample = start_sample; sample < end_sample; sample++) {
if(task.get_cancel() || task_pool.canceled()) {
if(task.need_finish_queue == false)
break;
}
for(int y = tile.y; y < tile.y + tile.h; y++) {
for(int x = tile.x; x < tile.x + tile.w; x++) {
path_trace_kernel()(kg, render_buffer,
sample, x, y, tile.offset, tile.stride);
int step = tile.offset + x + y*tile.stride;
step *= kernel_data.film.pass_stride;
float sampleR = *(render_buffer +step);
float sampleG = *(render_buffer +step +1);
float sampleB = *(render_buffer +step +2);
update_bcd_inputs(x, y, sampleR*inv_weight, sampleG*inv_weight, sampleB*inv_weight);
}
}
tile.sample = sample + 1;
task.update_progress(&tile, tile.w*tile.h);
}
}
SamplesStatisticsImages sStats is an attribute of CPUDevice
struct SamplesStatisticsImages
{
SamplesStatisticsImages() = default;
SamplesStatisticsImages(int i_width, int i_height, int i_nbOfBins);
SamplesStatisticsImages(const SamplesStatisticsImages&) = default;
SamplesStatisticsImages(SamplesStatisticsImages&&) = default;
SamplesStatisticsImages& operator=(const SamplesStatisticsImages&) = default;
SamplesStatisticsImages& operator=(SamplesStatisticsImages&&) = default;
DeepImage<float> m_nbOfSamplesImage;
DeepImage<float> m_meanImage;
DeepImage<float> m_covarImage;
DeepImage<float> m_histoImage;
};
Here are the files DeepImage.hpp and DeepImage.h.
The problem is that the call to update_bcd_inputs makes Blender to crash without even trying to render an image. I just change the renderer to Cycles, try to add a new material and boom, it crashes.
I figured out it is the set function that is the problem (when I remove it, the app doesn't crash).
Can someone understand why ? I don't have strong C++ skills so I must be missing something.
Here is the crash log as well.
Thanks !
Edit: more precisions
Here is the modified device_cpu.cpp.
The sStats pointer is initialized with nullptr in the CPUDevice constructor
CPUDevice(DeviceInfo& info_, Stats &stats_, bool background_)
: Device(info_, stats_, background_),
texture_info(this, "__texture_info", MEM_TEXTURE),
histoParams(),
#define REGISTER_KERNEL(name) name ## _kernel(KERNEL_FUNCTIONS(name))
...
#undef REGISTER_KERNEL
{
...
sStats = nullptr;
}
and then allocated in
void thread_render(DeviceTask& task)
{
...
sStats = new bcd::SamplesStatisticsImages(task.w, task.h, histoParams.m_nbOfBins);
...
}
histoParams is an attribute of CPUDevice as well.
struct HistogramParameters
{
HistogramParameters() :
m_nbOfBins(20),
m_gamma(2.2f),
m_maxValue(2.5f) {}
int m_nbOfBins;
float m_gamma; ///< exponent for the exponential size increase of histogram bins
float m_maxValue;
};

How to aim the camera at the z-index of the cell in front of my character?

I've got a 3D terrain environment like so:
I'm trying to get the character (camera) to look up when climbing hills, and look down when descending, like climbing in real life.
This is what it's currently doing:
Right now the camera moves up and down the hills just fine, but I can't get the camera angle to work correctly. The only way I can think of aiming up or down depending on the terrain is getting the z-index of the cell my character is currently facing, and set that as the focus, but I really have no idea how to do that.
This is admittedly for an assignment, and we're intentionally not using objects so things are organized a little strangely.
Here's how I'm currently doing things:
const int M = 100; // width
const int N = 100; // height
double zHeights[M+1][N+1]; // 2D array containing the z-indexes of terrain cells
double gRX = 1.5; // x position of character
double gRY = 2.5; // y position of character
double gDirection = 45; // direction of character
double gRSpeed = 0.05; // move speed of character
double getZ(double x, double y) // returns the height of the current cell
{
double z = .5*sin(x*.25) + .4*sin(y*.15-.43);
z += sin(x*.45-.7) * cos(y*.315-.31)+.5;
z += sin(x*.15-.97) * sin(y*.35-8.31);
double amplitute = 5;
z *= amplitute;
return z;
}
void generateTerrain()
{
glBegin(GL_QUADS);
for (int i = 0; i <= M; i++)
{
for (int j = 0; j <= N; j++)
{
zHeights[i][j] = getZ(i,j);
}
}
}
void drawTerrain()
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
glColor3ub( (i*34525+j*5245)%256, (i*3456345+j*6757)%256, (i*98776+j*6554544)%256);
glVertex3d(i, j, getZ(i,j));
glVertex3d(i, j+1, getZ(i,j+1));
glVertex3d(i+1, j+1, getZ(i+1,j+1));
glVertex3d(i+1, j, getZ(i+1,j));
}
}
}
void display() // callback to glutDisplayFunc
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
double radians = gDirection /180.*3.141592654; // converts direction to radians
double z = getZ((int)gRX, (int)gRY); // casts as int to find z-index in zHeights[][]
double dx = cos(radians)*gRSpeed;
double dy = sin(radians)*gRSpeed;
double at_x = gRX + dx;
double at_y = gRY + dy;
double at_z = z; // source of problem, no idea what to do
gluLookAt(gRX, gRY, z + 2, // eye position
at_x, at_y, at_z + 2, // point to look at, also wrong
0, 0, 1); // up vector
drawTerrain();
glEnd();
}
void init()
{
generateTerrain();
}
Firstly, I don't see any reason to cast to int here:
double z = getZ((int)gRX, (int)gRY);
Just use the double values to get a smooth behavior.
Your basic approach is already pretty good. You take the current position (gRX, gRY), walk a bit in the viewing direction (dx, dy) and use that as the point to look at. There are just two small things that need adaptation:
double dx = cos(radians)*gRSpeed;
double dy = sin(radians)*gRSpeed;
Although multiplying by gRSpeed might be a good idea, in my opinion, this factor should not be related to the character's kinematics. Instead, this represents the smoothness of your view direction. Small values make the direction stick very closely to the terrain geometry, larger values smooth it out.
And finally, you need to evaluate the height at your look-at point:
double at_z = getZ(at_x, at_y);

GLUT timer function

I am trying to get my tokens on a board game to fall slowly. Right now, they fall, but they fall so fast. How could I implement the timer function in my code? Right now I do a loop, that updates the y coordinate of glTranslate. But it is still too fast! the top y is the y coordinate where I press on the screen, and the bottomy is the coordinates of the lowest open spot for a token.
col =0;
double bottomy = 0;
int row = 0;
circlex = (double)x / width ;
circley = (double)y / height ;
row = board.getRow(col) + 1;
bottomy = 500 - (25*row);
for( double topy = y ; topy <= bottomy; topy += 2 ){
glTranslatef(circlex, circley, 0.0f);
circley += .0000000000000000001;
display();
}
r = board.makeMove(col);
You can use glutTimerFunc to execute a function at a regular time period. This has the signature
void glutTimerFunc(unsigned int msecs,
void (*func)(int value),
value);
For example if your drawing function was
void UpdateTokens(int time);
Then you could call an update every 0.5 seconds with the following call (where current_time was the current simulation time)
glutTimerFunc(500, UpdateTokens, current_time);
For more precise timing, I would recommend using <chrono> instead, and performing your timing using things like std::chrono::duration with a std::chrono::steady_clock.
The actual problem here is how glut works. Basically, the user only gets a image presented at the end of the main loop. As long as you do not return from the mouse function, nothing is presented on screen. You can solve the problem by transferring the work to the display function and distribute the translation across multiple frames:
global variables:
double circlex = 0, circley = 0, bottomy = 0;
bool isfalling = false;
int topy = 0;
mouse_func:
if (isfalling == false) //Prevents the user from clicking during an animation
{
circlex = (double)x / width ;
circley = (double)y / height ;
int row = board.getRow(col) + 1;
bottomy = 500 - (25*row);
topy = y;
isfalling = true;
}
display_func:
if (isfalling)
{
circley += .0000000000000000001;
topy += 2;
if (topy >= bottomy)
isfalling = false;
}
glTranslatef(circlex, circley, 0.0f);
display();