• Content count

  • Joined

  • Last visited

Community Reputation

2460 Excellent

About Samith

  • Rank
  1. I worked on Excite Truck many years ago and most of the game is spent driving really fast with motion blur and a very wide field of view, which makes objects appear much smaller than they are. In order to actually see the objects in the environment, they have to be artificially huge. If you take your truck in Excite Truck and slowly drive up to a house, you'll see the house is probably two or three times bigger than it should be if things were to scale, but appears normal when playing the game regularly.   Also, in 3D third person games, doors and stuff have to be both readable and functional from a gameplay perspective. Doors can be scaled up a bit to allow the player to walk through easily without tweaky collision volumes getting impeded. 
  2. I'll occasionally use code I don't understand if the scope of the code is small enough and I understand exactly what the code is intended to do. For example, I might use a compression algorithm I don't fully understand as long as I understand the (hopefully very simple) API to use the code, or I might use someone else's triangulation code even if I don't understand the underlying algorithm. As long as I understand how to use the code, and what the result of using the code is supposed to be, then I'm fine. And, as Jason Z says, it's important to properly attribute such code to its original creators, at the very least to be able to track down where the code came from originally if you have some questions in the future.
  3. Trying to conceptually understand the following code

    In the first example the code is attempting to lock the framerate to 25 frames per second. It does this by determining how long each frame should be (ie 1/25th of a second), then it measures how long it took to do update_game() and display_game(), and sleeps for the remaining amount of time. So, 1/25th of a second is 40ms. If update_game and display_game only take 30ms, then you sleep for the remaining 10ms. If it takes 45ms, then you're running behind and you just start the next frame immediately. Note that Sleep is typically a very bad way to implement this behavior, because you have no control of when execution will be returned to your thread. The operating system is in charge of rescheduling your thread, and it can do whatever it wants (though it'll likely be CLOSE to what you asked for).    The second example runs each frame as quickly as it can. It doesn't sleep at all. So, in order to get a consistent play experience, there needs to be a way for the game to know how long it's been since the last frame. Hence, you see the code passing in the delta time to update_game(). That means that if you're running at, for example, 10ms a frame, update_game() will know that each frame is taking 10ms and only update 10ms worth of time in the simulation. If you have an object with a position and a velocity, then its updated position would be position = position + velocity * 10ms. If the game started to run slower, and was only going at 20ms a frame, then it would be position = position + velocity * 20ms. So if your game runs fast or slow, the simulation should be approximately the same.
  4. The operator itself has side effects (you're assigning SomeFooValue to s.SomeFooValue, for example), which occur even if you don't return a value. The return value from the = operator isn't used very often, and you probably wouldn't notice its absence unless you were chaining = operators together (for example: a = b = c; a is assigned the return value from the b = c operation). In regular use, a = b performs the = operator but the return value is discarded.   And, as others have said, usually the compiler will warn about a code path that doesn't return a value. You should make sure your warning levels are set high enough so that you don't end up returning nothing from a function by accident.
  5. You'll have to point out what exactly is wrong with the image you posted. Or at least post an image that looks correct, so we can spot the differences. I'm not sure what I'm looking at.   Also, the title of the post claims frac is the cause of the problem, but the content of your post indicates that it's mipmaps that are the thing that determines whether the artifact appears or not. Your use of frac looks correct to me, so I would guess your problem is that your mipmaps don't look the way you think they do.   How are you generating mips? Do you ever look at your mips to make sure they're correct? Is it possible your mips have some kind of corruption near the border?
  6. Fear of replacement

        If you've only been working for 7th months I don't think it's that rare to get a null pointer or leave a boundary condition unchecked or something. You'll get better and remember those things more in the future (especially after getting yelled at!).    We all make mistakes. It's best to learn from them and move on. I've made every mistake you listed above. Fortunately, the mistakes you mention are pretty easy to fix and easy to always remember to check. Here's a tip: when you're writing a new function, you should consider the boundary conditions and null pointer assertions and error handling to essentially be part of the function's signature.  int foo(int *pArray, size_t array_size, int idx) // signature { ASSERT(pArray); // basically signature ASSERT(idx >= 0 && idx < array_size); // basically signature // actual function } I like to make sure all the assertions are written first, at the top of the function. That way 1) I remember to write them, and 2) they communicate a bit about what the function is supposed to do to the next person who comes along and looks at the code. The next person, for example, immediately knows that pArray must not be null when he calls this function, etc.
  7. FBX - UV usable range?

    (0.5, 0.5) maps to the image center. The UV range is [0..1] when the actual texture lookup happens, but your UVs don't have to be confined to that range. The result of a UV that is outside the [0..1] range depends on your texture addressing mode. If the mode is CLAMP, then UVs less than 0 will clamp to 0, and UVs greater than 1 will clamp to 1. If the mode is WRAP, then the fractional part of the UV is used (and if that's less than 0, 1 must be added. ie -0.04 becomes 0.96, -0.75 becomes 0.25, etc).
  8. We're gonna need a bit more to go on here...   What do you mean when you say it "does not work"? Does it not compile? If not, what errors do you get that you don't understand? If it does compile, then does it not run? If not, how does it crash? Does it run mostly correctly except some small things are different? If so, what's different? What were you expecting?   Are you using a cross platform game engine that you expect to run on both Apple and Windows computers?
  9.   I'm not entirely sure what you mean by "free", but here's an example: if you have a constant buffer that contains only a single float (so, 4 bytes), then no matter what that constant buffer will be 16 bytes wide, even if you only care about the 4 byte float. So yeah, you have 12 bytes that you can put stuff in without increasing the size of your constant buffer. So, the extra space is essentially "free".
  10.   a-har a-har a-har... not.   seriously, one thing is to read documentation the other is reading hundreds of pages just to prevent something you have no idea of what. most functions and other programming instruments offer functionality that isn't needed most of the time. that's like reading about rocket science just because you are interested in a fuel tank that is also used in rockets by coincidence.     Welcome to the world of software engineering. Data alignments are an extremely common requirement, especially on consoles and especially when dealing with graphics/DSP hardware.   For Direct3D: have you tried building with the debug layer enabled? If you had done so earlier, you would have gotten a message in your debug output informing you that you're not allowed to create a constant buffer whose size is not a multiple of 16. Then you wouldn't have had to spend ages digging through documentation to find out where you went wrong.   Also, when using structs on the CPU that you plan to memcpy into a constant buffer, you have to be very vigilant to ensure your struct has the same layout as you're expecting on the CPU. You'll want to familiarize yourself with constant buffer packing rules.   EDIT: Page detailing how to use the Direct3D debug layer:
  11. I am not sure about mobile development practices, but in general for console games teams that want to develop on multiple platform simultaneously will have some kind of platform abstraction layer that handles the platform specific stuff (input, sound, graphics, file system, etc). Then the rest of the game code will interact with the abstraction layer, which will then do the correct thing for each platform. The vast majority of a game's code should be platform agnostic, and only lower level file, io, graphics, sound, etc code will have to be written for each platform.   This is pretty easy on consoles, because the major consoles are so similar to one another. On mobile things might be a lot different, given the massive variation in screen size and performance that there is in the mobile marketplace.
  12. how to represent this number

      I think the pairs are actually countable. See this link for a proof.   So to answer the OP's question, the number of different pairs is countably infinite, so essentially there are as many pairs as there are integers.
  13. I doubt it'll matter either way. My main concern with one huge image is that you might run into some texture size limitations on some platforms. Otherwise, I doubt you're likely to notice any difference between the two techniques.    And also, it should be possible for you to author your images as one big image, and then split it into many smaller images in your data build pipeline. So this should be something where you can switch back and forth between the two techniques with relative ease if there really is a problem with one method, and you won't have to reauthor everything just to try the other method.
  14. OpenGL Mip mapping issue

    Since gluBuild2DMipmaps is more of a utility function to get things running than a final solution, I would be surprised if it was doing anything more complicated than a simple box filter (like what you're doing in your DirectX version right now).    However, you can rule out gluBuild2DMipmaps as the source of your problem by simply doing the same thing you do in DirectX in OpenGL. Have you tried generating mips yourself in OpenGL, the same way you do in DirectX, and seeing if that produces results that look the same?   Also, are you sure your DirectX mip map generation is correct? Have you looked at the generated mips directly and verified that they're correct? It can be kind of hard to tell just from an in-game screenshot whether the mips are exactly right (or exactly what you're expecting, since "right" is kind of subjective).
  15. Sorting a std::map

    std::map is an "ordered" container, meaning it is already sorted internally based on the Compare template parameter of the type (less<Key> by default). You can't change the sorting of a map, because that would violate its type properties. Basically, it does not make sense to sort a map.   What you probably want is a separate container that stores your entities in sorted order specifically for drawing. Perhaps you could keep an std::list that you sort each frame, or each time an entity's Y position moves it could be removed from the list an reinserted in the proper location.