Jump to content

  • Log In with Google      Sign In   
  • Create Account

Brother Bob

Member Since 26 Nov 2001
Offline Last Active Yesterday, 12:36 AM

#5217312 C++ do while error

Posted by Brother Bob on 18 March 2015 - 04:32 AM

You can't start the do-whole loop outside the function.




#5216884 simple regex issue

Posted by Brother Bob on 16 March 2015 - 12:02 PM

The documentation seems to suggest that matches() returns true only if the entire string matches the regular expression. Your current expression can only match the entire string if it consists of a single digit.




#5215473 Picking a random value from array with priority

Posted by Brother Bob on 09 March 2015 - 01:30 PM

Your second option is possible if it is sufficient to only approximate the distribution of the individual elements. This is equivalent to generating random numbers with a different distribution, you example is biased towards the start of the array so a Laplacian distribution could make sense.

 

Another option that allows for fully arbitrary and individual weights is to keep a separate vector of weights corresponding to each element. Sum all the weights and generate a random number from 0 to to the sum. Loop through the array to find the point where the cumulative sum of all previous weights becomes greater than then generated random number.

 

An optimization on that variant is to keep an array of cumulative weights instead of the weights themselves. The last element is the sum of all elements, and you can now use a binary search algorithm to find the random number more efficiently.




#5213953 null a vector of pointers in a parameter?

Posted by Brother Bob on 02 March 2015 - 10:37 AM

A reference must refer to a valid object, but your null-pointer is not a valid vector object. If you want to pass an optional parameter, you can pass a pointer to the vector instead of a reference so you can pass a null-pointer to indicate the absence of a vector.




#5213633 Equation for Zooming

Posted by Brother Bob on 01 March 2015 - 04:02 AM

You want an exponential interpolation. An easy way to achieve that is to linearly interpolate in logarithmic domain.

  1. Calculate the logarithm of your two end points: logMinZoom = log(minZoom) and logMaxZoom = log(maxZoom).
  2. Linearly interpolate between logMinZoom and logMaxZoom in the desired number of steps: logZoom = logMinZoom + (logMaxZoom-logMinZoom)*step/(maxSteps-1).
  3. Transform logarithmic zoom to linear zoom: zoom = exp(logZoom).

This ensures that zoom increases or decreases with a uniform scale instead of with a uniform offset.




#5213538 General questions about matrix multiplications

Posted by Brother Bob on 28 February 2015 - 01:46 PM

Your first two points are correct, but the remaining ones doesn't make any sense. Row/column majorness of a matrix has nothing to do with matrix maths, what you can do with it and what the result of operations are. The majorness affects one and only one thing: how the two-dimensional grid of numbers representing the matrix is mapped to a one-dimensional linear memory storage. You have to store the matrix in some way in one-dimensional memory, and the majorness dictates where the individual matrix elements are stores in memory.




#5212300 glDrawElements (SEGAULT)

Posted by Brother Bob on 22 February 2015 - 12:32 PM

The vector object itself is just a small class that stores a few pointers, such as a pointer to the actual data you put into it, and some internal book-keeping information for things such as how much memory has been allocated, how much is actually used, and so on. You want the pointer to the data stored by the vector, not a pointer to the vector object itself. A pointer to the vector object just points to its internal private data.




#5212266 glDrawElements (SEGAULT)

Posted by Brother Bob on 22 February 2015 - 08:47 AM

You're passing pointers to the vectors to glBufferData, not the pointer to the data the vector contains. Also, pass the vectors by reference instead and skip the size parameter; the vector know its own size.

GLuint InitializeVBOs(std::vector<Vertex> &vertices)
{
    GLuint VBOid;
    glGenBuffers(1, &VBOid);
    glBindBuffer(GL_ARRAY_BUFFER, VBOid);
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
    return VBOid;
}



#5211970 Cannot initialize constant base member value

Posted by Brother Bob on 20 February 2015 - 01:33 PM

You need to initialize the base class members from the base class, you cannot do it from the derived classes.

class Block : public Entity
{
public:
Block() : Entity(eIDError) {}
Block(EntityIDs id) : Entity(id) {}
};



#5211960 Cannot initialize constant base member value

Posted by Brother Bob on 20 February 2015 - 01:04 PM

Constant members can only be initialized in the constructor's initializer list, but there's no constructor in your base class to initialize it. Add a constructor that takes an ID so that the base class can initialize its member and call that base constructor from the derived classes.

class base
{
public:
base(__int32 ID) : ID(ID) {}
const __int32 ID;
};



#5211873 Easiest way to pass a 2D array?

Posted by Brother Bob on 20 February 2015 - 06:18 AM

Pay closer attention to where the ampersand goes: clicky.

 

In any case, I suggest some dynamic array anyway. A two-dimensional array, or any-dimensional for the matter, can always be flattened into a one-dimensional storage so there's no need for vectors of vectors of vector of... how many dimensions you decide to have.

std::vector<int> storage(size_x * size_y);
...
int value = storage[y*size_x + x];

Wrap that up in a small class containing the storage and the dimensions, and provide some convenience function to access the storage based on two indices.




#5210820 Exclusive maximum in random functions

Posted by Brother Bob on 15 February 2015 - 08:20 AM

But you can turn that argument around and ask, why would one design the random function's range only to index stuff in arrays smoothly when it's just as likely to be used for simulating die rolls? Stated differently, I *am* designing for general use, and I get the feel that exclusive maximum is a weirdness designed for indexing arrays, a very specific problem.

If you are designing a random generator for die rolls, then go ahead and use an inclusive range. If you design a random generator for array access, then go ahead and use an exclusive range. But a general-purpose random generator is not specifically designed for any case but to generate random numbers, it is designed neither for die rolls nor array accesses.

 

As Bacterius stated earlier, or at least hinted at, when you apply specific use cases to random number generators you are mixing two things; randomness and distributions. A random number generator should preferably only generate numbers, while specific code is used to shape the random numbers into specific distributions. In this case, a die roll and array indices are two distributions.

 

The general way to think about a die rolls that separates randomness and distribution is: I want 6 different random numbers, and once I have them I map them to the possible outcomes of a die roll. If your random function returns numbers between 0 and 5, then your die roll map becomes f(x) = x+1 (that is, insert random number 0 to 5, and get a die roll from 1 to 6), while the array index becomes f(x) = x. Similarly, if your random generator returns a value between 1 and 6, the map becomes f(x) = x for the die roll and f(x) = x-1 for array access.

 

None of the mapping functions are inherently better than the other. However, when you look at many different use cases, the math of 0-based exclusive ranges falls out prettier without magic numbers more often than not. You rarely have to add or subtract 1 to compensate for exclusive ranges.




#5210495 Variable id mapping

Posted by Brother Bob on 13 February 2015 - 09:26 AM

Another suggestion is to store the value as string and perform a lexical cast on demand. In that case, you don't have to determine the type of the data in the parser. For example, is the quoted string "42" supposed to be an integer, a floating point value without a decimal part, or an actual string that just happens to contain numbers? If your parser can always determine that, then that's fine, but maybe it's more useful if the user determines what the type of a certain named variable should be.

struct NamedVariable
{
    std::string name;
    std::string value;
 
    template<typename T>
    T get() {
        std::stringstream ss(value);
        T v;
        ss >> v;
        return v;
    }
};

You can also specialize this for, for example, T=std::string so you just return the value instead of passing it through a string stream object.

 

The benefit of this approach is that you can read your named variables and query them as many different types. You string "42" will be returned as the integer value 42 if you ask for an integer, the floating point value 42.0 if you ask for a float, and the string "42" if you ask for a string, and so on. Any type that can be read from a text stream can be stored and parsed.




#5210279 Qt datatypes with GLM and OpenGL

Posted by Brother Bob on 12 February 2015 - 09:00 AM

The quick non-standard solution, and the solution I'm not going to mention, is to just cast your pointers to GLM-data to Qt-data of the corresponding type. All reasonable vector and matrix libraries are just wrappers on top of the same physical layout; a contiguous memory buffer of floating point values. So, I said it anyway, even though I intended not to. Just don't take it as a long-term solution but something you can do under some control/supervision until you migrate to the Qt solution if that is what you're going for.

 

However, looking at the documentation, there are variants taking either individual X/Y/Z/W-parmeters for vectors, or effectively taking pointers to matrix data (not as plain pointers, but as pointer-to-arrays types).




#5209695 Operator Overloading C++

Posted by Brother Bob on 09 February 2015 - 04:30 PM

But that code isn't "nothing", it is "something". That "something" has side effects (it prints some text), which means that your program is doing different things whether there is an extra copy or not (either prints some additional text or doesn't print some additional text), and the compiled can't know if that is important or not to you personally.

 

The mere fact that you print something means that there is now an observable difference between making the extra copy and not. That may, as SiCrane suggested, very well be the deciding factor for the compiler's ability and/or desire to remove the extra copy. And that could be a problem for you; attempts you make to observe if this extra copy is made or not, could actual end up being the reason why it is made.






PARTNERS