taz0010

Members
  • Content count

    423
  • Joined

  • Last visited

Community Reputation

277 Neutral

About taz0010

  • Rank
    Member
  1. Culling points from a polygon.

    I have solved problems very similar to this by using the "Signed triangle area" formula.   http://geomalgorithms.com/a01-_area.html   All you need to do is loop over the points in the shape, and test the triangle at each vertex. i.e. for vertex v, you form the triangle with vertices {v-1, v, v+1}. You know the shape has vertices in a straight line if the triangle area is very close to zero. Unfortunately you can't rely on using an exact comparison against zero when dealing with floating point numbers, so you compare against epsilon (+-0.000001 or whatever suits).
  2. Are the references actually circular or are you just talking about a node which may belong to multiple entities? To handle the latter you can use a std::shared_ptr wrapper for your node objects. It will automatically count the number of references to the node and call the delete operator when the object containing the last reference is deleted.   Dealing with circular references is much harder. Some approaches are to use weak pointers (std::weak_ptr) to allow an object to know about another without having ownership (i.e. holding the weak reference will not prevent the object from being deleted). If you can't design the solution in this way, there are more elaborate methods where you scan your objects, detect the circular reference and delete objects which are unreachable in the graph. But it's normally much simpler to just not use (strong) circular references at all.
  3. You have your old and new direction vectors, so the problem is simply a matter of building the rotation matrix to rotate the first vector onto the second. You use the cross and dot product to get the rotation axis and angle.   Assuming that oldV and newV are normalised: axisOfRotation = crossProduct(oldV, newV).normalise(); // Depending on whether your library requires normalised rotation axes angleOfRotation = arccos(dotProduct(oldV, newV));   Whatever library you're using should have a function that builds a rotation matrix from an axis and angle of rotation, so there's no need to manually code a whole bunch of math.
  4. Calculating angles of rotation

    I'd do it like this: 1) Project the destination vector onto the XZ axis. Do this simply by setting the y component to zero. The projected vector will no longer be normalised. 2) Get the angle between the object's vector and the vector resulting from 1), and rotate around the y axis by this amount. 3) Now you can rotate your object onto the destination vector using the method outlined earlier in this thread (cross product vectors to get rotation axis, dot product to find angle). This will cause the object to point at the destination vector without any undesired rotation along the object's local x axis.
  5. Bit Flags vs. Boolean

    One thing to keep in mind is that accessing bit fields will require the compiler to produce additional bit masking instructions, which will *increase* the memory footprint of your instruction code. If you try to use bit fields as a general rule instead of a situational optimisation, you'll end up with slower code. Also, the alignment issues are subtle. Most types want to align on 4 byte boundaries, so AFAIK if you have a structure containing, say, an integer, and any less than 5 flags, then converting these flags to single bits won't save any space at all.
  6. [quote]Most modern compilers will optimize the trivial stuff. So I only stick important things (large items, parent classes, references, ect...) in the initializer list, as I really don't like them. My big issue is that the order items are initlialized in the initializer list is not the same order as they are listed. Which for dependent items can really lead to some hard to track down bugs.[/quote] Why is this being voted down? His gripe about the initialiser list order not being the actual initialisation order is perfectly valid. It's intuitive to assume that the variables are going to be initialised in the order that the initialisation code is written - which is exactly the case whenever you initialise something using the equals sign. Also mentioned in this topic, ordering your members for alignment or caching reasons can potentially break your code if one member was initialised using the value of another. And since headers are used, the potential error will not even be visible in the file where the initialisation code is actually written. Personally if I have primitive variables that I need to initialise in a specific order, I'm not going to rely on the class definition order to do it, and that means good old fashioned assignment with the = operator.
  7. As pointed out, the lack of built in libraries is by far the biggest issue. There's also a fair bit of boilerplate involved in implementing proper "rule of 5" (formally known as the rule of 3...) classes, and the header system is relatively complicated and requires you to jump from source to header file as you're adding new methods. And debugging compiler errors in template classes is potentially a time waster, since they can be *very* cryptic, and usually you're not told which part of the calling code actually triggered the error. c++ does allow you to implement RAII based memory management which is much better than garbage collected implementations when you need to control exactly when you release a resource. It's easy to make mistakes and leak memory building a c++ object, but when correctly implemented, the caller rarely has to worry about managing memory at all.
  8. [quote]The compiler can surely deduce that the value of Length is immutable, even if only because there is no assignment anywhere to the array or any element of the array [and thus the array itself can be treated as immutable in that context]. Whether this is being done, it's hard to say, especially given the current setup.[/quote] The reason the compiler isn't optimising out the call is because there's no guarantee that the value isn't being changed by another thread. Other compilers might optimise more aggressively and rely on the programmer to use the proper keywords (volatile) on all objects used in multithreading, but VS does not. I'm not 100% sure of the situation in C#, but in c++ under VS, levels of indirection are not cached at all. If you access a->b->c multiple times, you pay for the dereferences each time. This might be different if you create everything on the stack and don't use dynamic allocation at all, however. I prefer to write my loops like this: for (int i = 0, len = x.Length; i < len; ++i) { // actions } This should produce optimal code while avoiding the need to waste lines on declarations. Of course the effort is only of benefit 1% of the time (premature optimisation and all), but if you get in the habit of writing all loops like that, you're not wasting any time.
  9. Providing a function to return a const reference to the widget collection is the level of encapsulation I usually settle on. Controlling changes to the underlying container by requiring people to use your implementation of addWidget() rather than vector push_back(), is likely to mitigate most of the problems you'd face when changing your implementation in the future. Most of the time classes containing collections will perform some logic behind the scenes when the user adds or removes something, so not exposing a mutable collection object is just thinking ahead. But really, you can skip all the headache and just use a map. Expose find, insert and delete methods, and bidirectional iterators for traversal. If you provide the flexibility of maps from the beginning, you don't have to worry about breaking the implementation if you find out you need them in the future. Plus there are several avenues of optimisation of this structure without breaking the interface, should the situation warrant. (You could switch to hash_maps, etc)
  10. Placing random points on map

    Start by adding points randomly to the terrain, and then gradually remove points until you achieve the desired density. You can use spatial hashing techniques to divide your region up into equal sized squares, allowing you to query the points in a square and it's neighbours very quickly. Then you can take all the points within a fixed distance of the query point, and replace them with a single point whose position is the average of it's neighbours. Increase the threshold distance if the points in question are on water. Depending on how you tweak it, you might end up with no points being closer than a certain distance. Or if you prefer, you could randomly decide whether to merge points, in order to allow points to occasionally be close together, but not often.
  11. What's the preferred method of dealing with the "QPC on old dual core machines" problem? Do developers simply ignore the issue? I was one of the unlucky people to experience the bug and it was definitiely present in several big name titles I played. Is it safe to conclude that QPC is fixed on modern (all quad core and above) platforms?
  12. Factorial Recursion

    Considering that your average recursive function with a stack growth of log(n) is likely to only overflow some point after the universe reaches maximum entropy, I wouldn't be too worried about it. And this is only possible with algorithms implemented in a way where the upper bound isn't simply a function of the datatype size. (i.e. 2^32 or 2^64 max values for a comparison sort). Stack size is a compiler option you can control anyhow.
  13. Branch elimination usually results in a performance hit rather than gains on modern CPUs. For this reason, writing branchless code sometimes results in the compiler restructuring the code and putting the branches right back in there! This is the case when you deliberately use & rather than && in conditional statements. You should also consider that this particular operation (AABB collision) may have an extremely high branch prediction rate. Also, reinterpret casting between float and integer can drastically impact performance as the compiler/CPU has to copy the value to memory in between the move between floating point and integer registers. The only thing that really works is using SSE to vectorise (perform 4 tests at a time).
  14. You always need to read the documentation to make sure you aren't causing memory leaks when using API functions. Functions with "create" in their name typically allocate memory, and functions with "get" sometimes increment reference counts. The documentation will tell you if you need to call the corresponding "free" or "release" functions.
  15. As far as I know, Objective-C's reference counting scheme is intrusive, but shared_ptr allocates from the heap. Considering that c++ objects are potentially MUCH faster than their Objective-C ounterparts, I wouldn't worry about the overhead of storing the reference count separate from the object.