Jump to content

  • Log In with Google      Sign In   
  • Create Account

Brother Bob

Member Since 26 Nov 2001
Online Last Active Today, 06:18 AM

#5177387 Vertices with multiple UV coordinates and glDrawElements()?

Posted by Brother Bob on 01 September 2014 - 02:20 AM

Short answer; no, these things have not changed since 2003.


The thing is, a vertex is defined as everything that defines it, not just its position. The position attribute of a vertex, and the vertex itself, are often used for the same thing. Sometimes that's correct, but in the context of OpenGL, that is not correct. The position attribute of a vertex which many faces may share all over the model is just that, the position attribute of a greater atomic entity.


When you say that you have two identical vertices with the same position but different color, you really have two completely different vertices. So you're not duplicating any vertices, because the two vertices are different.

#5176190 Mapping Poker-Starting Hands to 0..1325

Posted by Brother Bob on 26 August 2014 - 07:34 AM

The two two solutions above assume all possible combinations of all possible cards without regards for duplication or order. That is, you have a unique identifier allocated for {i,i} which is not a possible hand, and you get two different identifiers for {i,j} and {j,i} which in fact are the same hands.

Assume a deck of 6 cards for each for easy visualization; the concept extends to any size. If you just take the above solutions, you get the following matrix of enumerated hards (x- and y-axes fo the table are the cards i and j, respectively):

     0     1     2     3     4     5
     5     6     7     8     9    10
    10    11    12    13    14    15
    15    16    17    18    19    20
    20    21    22    23    24    25
    25    26    27    28    29    30

As you can see, the diagonals have a unique value for impossible hands, and the upper-right and lower-left triangular parts also have unique values for the same hands.

What you want is the following matrix:

     -     0     2     5     9    14
     -     -     1     4     8    13
     -     -     -     3     7    12
     -     -     -     -     6    11
     -     -     -     -     -    10
     -     -     -     -     -     -

where - indicates a don't care-value because those hands are either impossible or already represented in the upper-right triangle.


Given two card indices {i,j}, the formula 0.5*i*i + 0.5*i - j - 1 gives you those values, assuming that i and j are integers and that j<i. The formula is independent on the number of cards. It should be possible to solve this for {i,j} given a hand index. It is a single equation with two unknowns, and the quadratic equation generally have two solutions as well, but I believe there is only one solution given the constraints that i and j are integers, and that 0<=j<i<52.


But given the very limited number of hands, a table with pre-coded hands may be feasible. In that case, just search the table for the combination of two cards and likewise look up the table index and read which two cards it represents.

#5176022 Missile Command code review request

Posted by Brother Bob on 25 August 2014 - 11:02 AM

For example, using an array.
for(int n=0; n<6; ++n) {
static float const data[] = {100, 200, 300, 600, 700, 800};
_bases[n] = EntityC(50, 10, sf::Vector2f(data[n], 520), _baseColor);
Maybe not worth it for such a small piece of repetitive code, but at least it begins to separates the data from the code.

I never really considered the possibility of simply creating a data array to fill another array. Wouldn't it be expensive though to recreate the array every iteration of the loop?


The array is constant and has static duration. Your compiler will allocate it at compile time and there's zero additional cost at run-time other than actually accessing it from memory.

#5175828 Missile Command code review request

Posted by Brother Bob on 24 August 2014 - 09:52 AM


_bases[0] = EntityC(50, 10, sf::Vector2f(100, 520), _baseColor);
_bases[1] = EntityC(50, 10, sf::Vector2f(200, 520), _baseColor);
_bases[2] = EntityC(50, 10, sf::Vector2f(300, 520), _baseColor);
_bases[3] = EntityC(50, 10, sf::Vector2f(600, 520), _baseColor);
_bases[4] = EntityC(50, 10, sf::Vector2f(700, 520), _baseColor);
_bases[5] = EntityC(50, 10, sf::Vector2f(800, 520), _baseColor);
This could be a loop.


Huh, but how would I integrate the jump from 300 to 600? I can't think of a way.

For example, using an array.

for(int n=0; n<6; ++n) {
    static float const data[] = {100, 200, 300, 600, 700, 800};
    _bases[n] = EntityC(50, 10, sf::Vector2f(data[n], 520), _baseColor);

Maybe not worth it for such a small piece of repetitive code, but at least it begins to separates the data from the code.

#5174674 How to react on KeyPress + Release?

Posted by Brother Bob on 19 August 2014 - 04:46 AM

I had to assign the idle()-function using glutIdleFunc() not glutIdleCallback() (this one wasn't even suggested by VS).


My mistake, glutIdleFunc is of course correct.

#5174665 How to react on KeyPress + Release?

Posted by Brother Bob on 19 August 2014 - 04:17 AM


Is the display routine invoked regularly at all? Set a breakpoint into the display() routine and look what happens.

Yes it is, otherwise it would not draw anything I guess.


There's between being called once and being called regularly. GLUT will only issue a call to the display function when the contents is invalidated which typically happens when for example, the window is created, the window is resized, or when the window is moved behind other windows. Otherwise, the display callback is not called again unless you explicitly force a redisplay.


So, your display function is called once which explains why something is rendered, but not regularly which explains why nothing more is happening after that. You need to use the idle callback to keep the program busy all the time instead of idling when there's nothing new to display.


Quick solution:

void idle()
int main()
As soon as there's nothing else for GLUT to do, it calls the idle callback which then forces GLUT to redraw the window.

But while stepping through the method something strange happened. When the debugger hit the memcpy() line it VS opened a OpenFileDialog and said that it was missing a memcpy.asm file.
What does that mean it didn't throw any errors when compiling without breakpoints.

You're stepping into the memcpy call but the debugger can't find the source for the memcpy function. Could be that the source directories are not set up properly or you haven't installed the runtime library source. Quick solution is to step over the call, and into it.

#5172044 Safely eating potatoeses

Posted by Brother Bob on 07 August 2014 - 08:10 AM

#1 What does it actually mean when it says 7.22 (i'll just take it as 7) decimal digits ?

A single-precision float with 24 effective bits (23 explicit and 1 implicit bit) has log10 224 = 24 log10 2 = 7.22, which is approximately 7, digits of precision. Note that it is not 7 decimal digits after the decimal point, but significant digits; the precision is relative, not absolute.

#2 What is the absollutely safe range (maximum and minimum) in floats without losing information(end ressult the number will be represented exactly). And how to safely use it?

Depends entirely on what scale you work with and type of operations you do.


If you limit yourself to integers, you can work with integers between -223 and +223 safely. If you introduce fractional powers of two, you need to ensure that the fractions don't scale beyond your 24 bits of precision.


For arbitrary values and operations, there's no such thing as "no loss of information" in floating point values.

#5170661 Understanding Qt At a Deeper Level

Posted by Brother Bob on 31 July 2014 - 12:17 PM

I started diving into Qt again last night, and a few things made me wonder how it works. For example: when the UI is designed in the Designer View, is the .ui file (an XML schema) compiled into a header/source file that contains all of the controls as if instantiated in-code?

That is correct. The uic program translates your UI-file into a header file (header only though, no source file) that you include in your code to instantiate the UI. If you have a UI called mywindow you typically have the mywindow.h and mywindow.cpp files, and you'll get a file ui_mywindow.h from the UI compiler that you include to instantiate the UI in mywindow.cpp.


The reason I ask is because the .ui file's corresponding header/source pair's class is also prototyped in the scope of the UI namespace. Then, a data member is created from that, called "ui" within the class itself. That ui data member appears to contain a pointer for each QWidget added in the Designer. For example, if I drag a QPushButton into the Designer, and name it as pushButton in its Properties Inspector, the ui member will have a ui->pushButton member pointer within it of type QPushButton. Funny thing is, I couldn't find where the "pushButton" member was declared in-code. This leads me to think that Qt Creator's Intellisense is smart enough to parse the XML file, and a class being changed behind the scenes, or at least at compile time.

When you create a project in QtCreator, you are asked for an intermediate directory for your project. For example, if your project is located in <path>/test, this intermediate build directory is usually <path>/build-test-Desktop_Qt_5_2_1_MSVC2012_OpenGL_64bit-Debug, or a variant thereof, and depends on which version (5.2.1 in this case), which compiler (MSVC2012) and Qt build options (w/ OpenGL, 64-bit, debug library) you use. You find all temporary files from, for example, the uic and the moc compiler there. This is where you find your compiled UI header files.



Then, there are, signals and slots. It sounds like they have some sort of special definition that's triggered by the Q_WIDGET macro. Also, QWidget::connect()'s 2nd and 4th parameters are of type const char*, and it's common practice to use the SIGNAL() and SLOT() macros to pass through prototypes of functions (not methods because they don't appear to be associated with any class). I understand that that I'm calling two functions that these widgets seem to have, but how does that work under-the-hood, exactly?

I won't, or can't, go into the details about signals and slots in general, and certainly not about Qt's signals and slots in particular. See them as callbacks on steroids. When something happens, for example a button is clicked, the button's clicked() signal is emitted. This, sort of, inserts a message into Qt's "message loop", and Qt then calls all connected slots. So if you connect your onQuitButtonClicked() function to the quit button's clicked() slot, Qt will call onQuitbuttonClicked whenever the quit button's clicked signal is emitted.



connect(button, SIGNAL(clicked()), this, SLOT(onClicked()));

informs Qt to call this->onClicked() whenever button's clicked() signal is emitted. It does not call button->clicked() at any time, it only observes it and responds by calling this->onClicked().


I suggest you study the idea behind signals and slots in online resources, but basically it's a kind of callback system that let's you receive calls to functions when something happens. Sometimes the signal is passed through the message loop, and sometimes the slot can be called immediately from the signal, but those details are not really relevant to the concept of signals and slots.



Does Qt rely on some special C++ compiler, or special rules?

jwezorek already got a reply before I finished this, so I won't repeat much of it: no special C++ compiler, but it preprocesses your UI and source/header files using the UI and meta object compiler to generate additional source/header files that is passed to the C++ compiler.

#5168140 Exception question

Posted by Brother Bob on 21 July 2014 - 07:55 AM

Pointers never deallocate themselves. Use a smart pointer object to manage ownership.

try {
    std::unique_ptr<int[]> ptr(new [10]);
    for (int i = 0; i < 10; i++) ptr[i] = 10;
    throw 1;
} catch(int x)

#5167544 How to keep straight line straight while mapping to non rectangular area

Posted by Brother Bob on 18 July 2014 - 02:47 AM

If you need to add perspective on top of something that doesn't have perspective itself, you need to add that additional perspective information to the texture coordinates instead. See this.

#5166791 OpenGL : GLEW or Qt or else ?

Posted by Brother Bob on 14 July 2014 - 01:55 PM

You probably want GLFW instead of GLEW, since GLEW is not a GUI library at all. However, GLFW is not much of a GUI library either, really, but rather a relatively simple rendering window and input wrapper but no widgets; only the basic rendering and input frameworks. On the other end, Qt is a complete GUI framework as well. It's not really fair to compare the two. For a lightweight wrapper, both GLFW and SDL are popular.


Another question though; if you are more experienced with Java, have you considered using Java? There are frameworks such as LWJGL that may be of interest to you. I haven't used Java at all though, so I cannot comment on it.

#5165771 how to use or ||

Posted by Brother Bob on 09 July 2014 - 04:27 AM


It should be noted that performing your comparisons using multiple Boolean variables means that you cannot take advantage of short-circuit evaluation.


VS2012, compiled with default release mode settings:


Resulting disassembly:


Compilers are very, very smart.


They are, hopefully, also very smart not to do that when the evaluations of the temporary variables have side effects because that would change the meaning of the program. Your example works because the individual conditions does not have any observable side effects. If the expressions have side effects, or otherwise relies on short circuiting to prevent the evaluation of an expression in the condition (for example checking for null-pointer before accessing a member of an object), expanding the expressions to temporary variables before the if-statement won't work.

#5164168 How is this a pass by value?!

Posted by Brother Bob on 01 July 2014 - 06:04 PM

Ivalue will obviously remain 0 since we pass by value, and svalue will become bar(because we use a pointer).


That was my initial response without running the code. To my surprise, after running it, i was right about ivalue, but not about svalue.


Looking at the code again, I realized that foo is actually a literal, hence, it cannot be changed at all. Is that why the pointers are copied by value? Is there some kind of rule about 2 pointers refering to the same literal?

svalue is a pointer variable, and a copy of its value is passed to the set function. The set function then assigns the local variable a new value, but the original pointer remains the same.


Now replace the two set functions with these instead that takes the parameters by reference.

void set(char const *&value)
    value = "bar";

void set(int &value)
    value = 42;

As I said, pointers are variables that work just like any other type. They just happen to have additional functionality that lets you access other objects through the pointer, but the pointers themselves are just values that are copied like any other value.


edit: There is a huge difference between a pointer, and the object a pointer points to. The pointer is copied, but the pointed-to object is not and can be reassigned across functions.

#5164162 How is this a pass by value?!

Posted by Brother Bob on 01 July 2014 - 05:49 PM

Step away from your nested max functions a bit and examine this program.

void set(char const *value)
    value = "bar";

void set(int value)
    value = 42;

int main ()
    int ivalue = 0;
    char const *svalue = "foo";


    std::cout << ivalue << " " << svalue << std::endl;

Now answer these two questions, and understand why the answer is what it is.

  1. Is the value of ivalue 0 or 42?
  2. Does the pointer svalue point to the string "foo" or "bar"?

This is what is the core of the problem with your max functions.

#5164151 How is this a pass by value?!

Posted by Brother Bob on 01 July 2014 - 05:09 PM

I know the code works, the problem is I can't get the: "error, if max(a,b) uses call-by-value" how would it be called by value when we can clearly see it takes pointers and not values?!

You are confused about what is actually passed to the function. In your max-function that is overloaded for char const *, the pointers a and b are not references to the pointers you pass to it, but value-copied of the original pointers. If you are confused about pointers and pass-by-value, it is easier to hide the pointer behind a typedef.

typedef char const *cstring;

cstring max (cstring a, cstring b)
{ ... }

Now compare with passing int, or float, or double, or char, and you'll see that the cstring object, which is a char const *, is actually passed by value.