Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

440 Neutral

About dimebolt

  • Rank
  1. dimebolt

    Computing tangents

    Quote:Original post by cignox1 Thank you all, now I have many different implementations of the algorithm, and some more general description of it. I wil try to figure it out from them. Thank you again! EDIT: I've just read the article "Bump mapping using GC" and perhaps I'm able to understand things with this article. I've one question though: In the algorithm the normal is computed with a cross product between tangent and bitangent. But in the general case the normal is already there, that is the mesh already has normals (perhaps averaged among triangles sharing vertices). How should I behave in this case? Should I rotate my resulting tangent to be perpendicular to the normal? How do I perform this? Thank you. Usually, generating normals works like this: 1. calculate normals for triangles 2. calculate normals per vertex for smooth shading (as yous said, often by taking the average vector of all normals of the triangles meeting in that vertex) I believe that when also using s and t tangents, the process is similar: 1. calculate normal and s and t vectors for the triangles (s and t tangents simply being the actual directions of the texture coordinates in the plane of the triangle) 2. calculate normals, s and t tangents per vertex for smooth shading (this time getting 3 average vectors instead of 1) If, for example, the normals come from a model file, they already went through step 1 and 2. You can then either do the calculation only for the tangents (which may or may not look weird depending on how much your algorithm for obtaining the smooth vectors differs from the one used when creating the model) or you can throw away the normals and do the entire thing yourself. Tom
  2. dimebolt

    Computing tangents

    Since source code for this problem for OpenGL is easy to find (for example, check the Irrlicht sources for inspiration), I'll explain the mechanics. In general a tangent only requires to be perpendicular to the normal, so an arbitrary vector perpendicular to the normal could be chosen. The binormal then simply is cross(normal, tangent). However, since you wish to use these for bumpmapping, there are additional requirements to the tangent and binormal. They will be used to determine the direction of the texture to properly interpret the normal values stored in the texture. This means that tangent and binormal should be alligned with the direction of the texturecoordinates. Therefore, in this context, the tangent and binormal are usually referred to as s tangent and t tangent, corresponding to the s and t texture directions the correspond to. Hence, to calulate the tangent and binormals for the 3 vertices of a bumpmapped triangle, we need the values of the 3 vertices, their respective normals and their texture coordinates. For a more thourough explanaition and the important formulas I suggest this webpage: Bump Mapping Using CG. The part describing the theory is not specific to CG and can be applied to any shader type. Tom
  3. dimebolt

    Moving objects in opengl

    Quote:Original post by Ezbez Quote:Original post by EndarEdit:: Also, if you want to rotate something and also translate it, you must rotate first and then translate. Otherwise instead of rotate about the object's center point, it will be rotating around another point and you'll go crazy attempting to figure it out. So, just remember rotate then translate. I'm a rather new to OpenGL, but I don't beleive that this is correct. Isn't the reverse true? Yes, he got the order mixed up. One way to remember this stuff, is that the last transformation before drawing an object always applies 'first'. Therefore, to rotate an object around it's axis, this rotation should be the last transform before drawing it. Tom
  4. dimebolt

    Moving objects in opengl

    OpenGL uses transformation matrices that the hardware (or software, depending on where and what OpenGL you use) will apply to your vertices. Plenty of information on transformations in OpenGL is available in the online version of Red Book. For the actual matrix/vector math involved, you may (or may not) need to brush up your linear and vector algebra. Tom
  5. First of all, I'm having a bit of trouble of understanding how all this would work for the user (i.e. the guy specifying the scene to be rendered). After creating scene objects, does he have to sort them into each separate component himself? Or can he create a scene graph, which is subsequently sorted into a render list, a collision structure, etc? Quote:Original post by tank104 1. One problem is that part of the SceneManager structure is partially stored in the ITransform implementation as it keeps track of children objects, I see this as not good in design, but cannot see an easy way around it? If you want parent/child information separated from the ITransform class and defined within the scene manager, you can use the Decorator pattern: define some tree classes (group/leaf) local to SceneManager that contain ITransforms (with a has-a relation rather than the usual is-a (inheritance)). Use these classes to define the hierarchy for their contained ITransforms. I'm not sure if this is a good idea though. A transformation is an operation that should be applied to it's context (children). If you separate data and children, a single ITransform becomes rather meaningless. This means that if an object different from the scene manager requires to apply a transform, he'll have to go the scene manager first (which could also be axplained as a good thing, so I really don't know). Quote:Original post by tank104 2. Is there going to be a worrying ammount of overhead keeping so many list/trees? As a base rule, don't do performance optimization until you run into a performance problem. That being said, there is a simple observation that applies to scene management overhead: the overhead of managing a single scene object is only noticable when the cost is approaching the cost of the actual rendering of that object. This implies that if your management overhead becomes higher, your system will perform worse on applications with many simple (i.e. low rendering cost) objects. Quote:Original post by tank104 3. Is texture swapping the most expensive change, followed by shading swapping? It appears so and if that is the case am i best to order all my IRenderable objects first by Material and then by Shader, or is there a better order? This question is addressed in the OpenGL forum FAQ. Although it's described in the context of OpenGL, it will apply to direct3D as well, as they're useing the same hardware. Quote:Original post by tank104 4. Other designs seem to keep the cameras/render objects seperate from the SceneNodes (i.e. as properties and not by inheriting), is there an obvious reason for this? I believe it's mainly a matter of personal taste. I prefer to put the camera in the scene graph, that way I can simply attach it to the head of an avatar and it will move automatically when this avatar moves. It's a lot less bookkeeping for the user. Tom
  6. dimebolt

    Would like input

    Quote:Original post by Zahlman Taking a glance at this I believe I have a lot to comment on (there is, after all, a lot of code), but unfortunately I won't have time to write it up for at least a week... bookmarking the thread now, will come back to it :) Zahlman is usually much more thourough and perceptive than I am in commenting on code. However, I'll post my opinion on your code here, to give you something to read while you wait for his reply. Let me start by saying that despite the amount of comments you'll find in my post, your code is much better than most 'comment on my code' posts I've seen in this forum. I tried to give constructive critisism by describing what I think is wrong, why I think that, and what I would have done. Occasionally this will be my personal taste or opinion and should be marked as such. If any of my comments is unconstructive, unclear or simply dumb, feel free to ask for clarification, ignore my statements, call me names, or take any other action you deem appropriate ;) Comments placed in source, written within /*** ***/ pairs and preceding the line I comment on: #include <iostream> #include <fstream> #include <string> #include <vector> #include <ctype.h> #include <limits> #include <time.h> /*** * I don't know why people don't want to type std:: every now and then. * Even if you don't want to, I would prefer only to do 'using' with the * classes and functions you actually use, to prevent polluting namespace * with classes and functions I dont even use: using std::vector; using std::string; etc ***/ using namespace std; /*** * as stated in a previous post, try using const instead of defines for constants * as it is much safer: const static string menu_text = "What would you like to do: "; ***/ #define MENU_TEXT "What would you like to do: "; /*** * Useful comments are great. Thumbs up! ***/ //'EASY=10' means Difficulty setting EASY has number range from 1-10 enum DIFFICULTY{EASY=10, NORMAL=50, HARD=200}; /*** * Some comment on the purpose of the class might be nice :) * The name is obvious, but when looking at the variables and functions I start * wondering what on earth it's supposed to represent... ***/ class Score { public: //Constructors /*** * I'm a const correctness fan, and I'm baffled that a self-proclaimed noob is aware of the concept. Thumbs up! * You don't use it consistently yet, you could try: Score(const string &userInit = "Empty", const string &diff = "None", int guesses = 0) * The references are used to prevent needless copying of string data. * The const means that the contents of the reference won't (can't) be changed * by the function (which is good, as you'll only copy them anyway). ***/ Score(string userInit="Empty", string diff="None", int guesses=0) : /*** * Don't use inline functions as an excuse to throw away lay-out! * In fact, I would rather prefer all functions of this class to be implemented * separate from the class definition, unless performance issues arise (which is unlikely in this case). ***/ itsInitials(userInit), itsDiff(diff), itsGuesses(guesses) { } ~Score() {}; //Member functions /*** * const string without the '&' (reference) is not so useful. Without the * reference, the string will be copied anyway and it doesn't really matter * if the function changes its own copy or not. * Lay-out again, and initials and diff could be a const reference: void SetInitials(const string &initials) { itsInitials = initials; } void SetDiff(const string &diff) { itsDiff = diff; } ***/ void SetInitials(const string initials) {itsInitials=initials;} void SetDiff(const string diff) {itsDiff=diff;} /*** * No need to make basic type parameters constant as they will be passed by value anyway: void SetGuesses(int guesses) { itsGuesses = guesses; } ***/ void SetGuesses(const int guesses) {itsGuesses=guesses;} /*** * Lay-out again, initials and diff could be a const reference: void SetAll(const string &diff, const string &initials, int guesses) { itsDiff = diff; itsInitials = initials; itsGuesses = guesses; } ***/ void SetAll(const string diff, const string initials, const int guesses) {itsDiff=diff; itsInitials=initials; itsGuesses=guesses;} int GetGuesses() const {return itsGuesses;} string GetInitials() const {return itsInitials;} string GetDiff() const {return itsDiff;} //Member data private: /*** * I don't like these member names. This is, of course, partially subjective but I'll try to give * objective pointers: * - The 'its' prefix is meaningless. If you use it simply to separate between member variables and * local/global variables, the 'm_' is a more commonly used prefix. I myself prefer no prefixes whatsoever, * but I understand why some people like 'm_'. * - Diff is an abbrieviation most commonly used for 'difference' but from the * fact that it's a string I deduce that it's supposed to represent 'difficulty' here. But if it is a difficulty * why not use a variable of type DIFFICULTY, since you have this nice enum? * - Initials probably means initial values? What kind of initial values? Why is it a string? The name should * tell us what it represents (like e.g. initialDifficultyLevel if that's what it's supposed to be). * Ok, reading on I see you meant initials as in a persons name :) I argue that PlayerName would be a better * choice still, as it's not as ambiguous. Besides, storing initials only is a bit too retro for my taste: PCs * nowadays have plenty of space to store full names :) **/ string itsInitials; string itsDiff; int itsGuesses; /*** * This class contains only variables and getters and setters. I find that rather cumbersome in use. * If a class just contains random access data, you can simply make the data public and use it directly. * If every member has a getter and a setter, your not really doing information hiding anyway. ***/ }; //function protoypes void DisplayScores(const vector<Score> & theScores); void SaveScores(const vector<Score> & scoreList); void LoadScores(vector<Score> & scoreList); inline bool ChangeDiff(int menuChoice, DIFFICULTY & gameDiff); string CheckDiff(const DIFFICULTY & gameDiff); void SetInitials( string & theInitials); int GuessNumber(DIFFICULTY gameDiff, int whoGuessing); //Main program int main() { vector<Score> scoreList(10); //keep track of 10 Scores Score newScore; string userInit; DIFFICULTY gameDiff=NORMAL; //Game difficulty string temp; bool Quit=false; bool success=false; /*** * Like your difficulty enum, it would be nice to have a player enum: enum player {human = 1, computer = 2}; ***/ int whoGuessing; //1 if user is guessing, 2 if computer is guessing int menuChoice; int numGuesses; /*** * IMO your main function is to big (and therefore harder to read) * I suggest moving the following code.... ***/ cout << " ********** You are playing Guess the Number! **********\n"; cout << " Coded by: DarkSuicide\n\n\n"; cout << "Initials(ex: AOH): "; getline(cin, userInit); SetInitials(userInit); LoadScores(scoreList); //load scores from previous session srand(time(NULL)); //seed number gen /*** * ... to a function called InitGame() or something: * InitGame(); * * And move the following code... ***/ while(!Quit) { /*** * Although not critical, the 5 menu options also could be an enum: enum main_options {new_game = 1, show_score = 2, change_difficulty = 3, change_name = 4, quit = 5}; * this avoids 'magic numbers' more on that topic later :) ***/ cout << "\n(1)New Game\n(2)Display Scores\n(3)Change Difficulty | Current difficulty: " << CheckDiff(gameDiff) << "\n"; cout << "(4)Change initials | Current initials: " << userInit << "\n(5)Exit\n"; cout << MENU_TEXT; cin >> menuChoice; cin.ignore(numeric_limits<int>::max(), '\n'); /*** * I have a personal rule that cases of an if statement may not contain more than 2 statements * normally a function call and a break. I would suggest putting all the different case contents in * separate functions. This prevents your 'do-loop in switch-statement in while-loop'. ***/ switch(menuChoice) { //new game case 1: /*** * Note that if you follow my advice on the player enum the following line should become: * cout << "\n\n(" << human << ") Human\n(" << computer << ") Computer\n"; ***/ cout << "\n\n(1)Me\n(2)Computer\n"; cout << "\nWho will be guessing: "; cin >> whoGuessing; numGuesses=GuessNumber(gameDiff, whoGuessing); /*** * Note that if you follow my advice on the player enum the following line would become: * if(whoGuessing == human) * which reads a lot better ;) ***/ if(whoGuessing==1)//User guessing newScore.SetAll(CheckDiff(gameDiff), userInit, numGuesses); else //comp guessing newScore.SetAll(CheckDiff(gameDiff), "Computer", numGuesses); //update score list /*** * EDIT: removed some nonsense ***/ scoreList.insert(scoreList.begin(), newScore); scoreList.pop_back(); break; //Display Scores. case 2: /*** * This case conforms to my two line case rule :) ***/ DisplayScores(scoreList); break; //Change Difficulty case 3: cout << "\n\nDifficulty: Number Range:\n"; cout << "\n(1)EASY"; cout.setf(ios_base::internal); /*** * The 30 in the following line is a 'magic number'. I can have a guess that the number * has something to do with layout. However, I don't know why it's 30 and what it actually * represents. Replacing it with a 'const uint LeftMargin' (or whatever it represents) is * more easy to grasp. The same goes for all the other width statements of course... ***/ cout.width(30); cout << "1-10\n"; cout << "(2)NORMAL"; cout.setf(ios_base::internal); cout.width(28); cout << "1-50\n"; cout << "(3)HARD"; cout.setf(ios_base::internal); cout.width(31); cout << "1-200\n"; do { cout << "\nChoose a difficulty: "; cin >> menuChoice; success=ChangeDiff(menuChoice, gameDiff); }while(!success); cout << "Difficulty changed to : " << CheckDiff(gameDiff) << "\n\n"; break; //Change userInit case 4: cout << "Please enter the new initials: "; getline(cin, userInit); SetInitials(userInit); cout << "\nInitials changed to: " << userInit << "\n"; break; //Exit program case 5: /*** * This case conforms to my two line case rule :) ***/ Quit=true; break; //not valid option default: cout << "\nNot a valid menu option.\n"; } } /*** * ... to a function called RunGame() or something: * scoreList = RunGame(); * * Which would reduce your main to three or four lines... ***/ SaveScores(scoreList); return 0; } //Function definitions //Displays last 10 scores on a nicely formatted table void DisplayScores(const vector<Score> & theScores) { vector<Score>::const_iterator theIterator; cout << " ******* Scores ******\n"; cout << "\nPlayer:"; cout.setf(ios_base::internal); cout.width(20); cout << "Difficulty:"; cout.setf(ios_base::right); cout.width(39); cout << "# of Guesses:\n\n"; /*** * EDIT: removed some nonsense ***/ for(theIterator=theScores.begin(); theIterator!=theScores.end(); theIterator++) { cout.setf(ios_base::left); cout.width(8); cout << theIterator->GetInitials(); cout.setf(ios_base::internal); cout.width(20); cout << theIterator->GetDiff(); cout.setf(ios_base::right); cout.width(37); cout << theIterator->GetGuesses() << "\n"; } cout << "\n\n\n\n"; } //Saves scores stored in scoreList void SaveScores(const vector<Score> & scoreList) { vector<Score>::const_iterator theIter; ofstream scoreFile("scores", ios::binary); if(!scoreFile) cout << "Unable to open 'scores' for writing.\n"; else { /*** * EDIT: removed some nonsense ***/ for(theIter=scoreList.begin(); theIter!=scoreList.end(); theIter++) scoreFile << theIter->GetInitials() << " " << theIter->GetDiff() << " " << theIter->GetGuesses() << "\n"; scoreFile.close(); } } //Load scores from previous session void LoadScores(vector<Score> & scoreList) { vector<Score>::iterator theIter; int theGuesses; string theInitials; string theDiff; ifstream scoreFile("scores", ios::binary); if(scoreFile) { /*** * EDIT: removed some nonsense ***/ for(theIter=scoreList.begin(); theIter!=scoreList.end(); theIter++) { scoreFile >> theInitials; scoreFile >> theDiff; scoreFile >> theGuesses; theIter->SetAll(theDiff, theInitials, theGuesses); } } } //Chenges difficulty setting bool ChangeDiff(int menuChoice, DIFFICULTY & gameDiff) { bool success = false; /*** * This switch violates my two lines per case rule. This might be a good time * to tell you about my other rule: the two lines per case rule need not always apply :) * This switch is clear and to the point. ***/ switch(menuChoice) { case 1: gameDiff=EASY; success=true; break; case 2: gameDiff=NORMAL; success=true; break; case 3: gameDiff=HARD; success=true; break; default: cout << "\nNot a valid menu option.\n"; } return(success); } //Checks the numeric value of gameDiff and tells you the difficulty setting as a string string CheckDiff(const DIFFICULTY & gameDiff) { /*** * Good, but you should never store the string (like in the Score class). Always store the enum value * and use this function only for printing the name. That way, difficulty is always consistently represented * by the same type: DIFFICULTY. ***/ string diff; if(gameDiff==EASY) diff="Easy"; else if(gameDiff==NORMAL) diff="Normal"; else diff="Hard"; return(diff); } //Erases all but first 3 chars and converts those 3 to uppercase void SetInitials( string & theInitials) { /*** * How retro ***/ if(theInitials.size()>3) //user typed more than 3 chars theInitials.erase(3); for(int i=0; i<theInitials.size(); i++)//change to uppercase theInitials=toupper(theInitials); } //Handles everything dealing with the computer and users guesses /*** * The name of this function implies that only one number is set, whereas it in fact is the * Main part of the game. A more descriptive name would be nice. ***/ int GuessNumber(DIFFICULTY gameDiff, int whoGuessing) { int theNumber; int theGuess; int numGuesses=0; bool correct=false; bool used=false; vector<int> usedGuesses;// see if number was already used for a guess vector<int>::iterator theIter; /*** * No need to reserve 200. push_back and insert will expand the vector if necessary ***/ usedGuesses.reserve(200); //can hold up to 200 chars to support all difficulty levels; /*** * Nesting as deep as you do here within one function is never good. Try to put the inner loops * in separate functions. That will increase abstraction and readability ***/ if(whoGuessing==1)//user is guessing { cout << "\nYou will be the one guessing the number.\n"; cout << "Picking random number..."; /*** * Using modulo would work in practice, but mathematically it's incorrect as it will slightly affect * the distribution of the random number. * It's probably better to use (rand() / RAND_MAX) * gameDiff. Unfortunately, for that to work we need * to use floating point calculations, which leads to the following casting mess: static_cast<int> ( ( static_cast<float>(rand()) / static_cast<float>(RAND_MAX) ) * static_cast<float>(gameDiff) ) * But it is more correct :) ***/ theNumber=(rand() % gameDiff +1); /*** * The inside of this do loop could be moved to a function for which the name GuessNumber(...) actually * would be appropriate (since we are then really guessing only a single number) ***/ do { cout << "\nPick a number between 1 and " << gameDiff << ": "; cin >> theGuess; //Check if user already used this number for a guess for(theIter=usedGuesses.begin(); theIter!=usedGuesses.end(); theIter++) { if(*theIter==theGuess) { used=true; break; } } if(!used) { /*** * insert() is not very efficient for std::vector. Since the * order of guesses would make no difference for the algorithm in this case, * try usedGuesses.push_back(theGuess) instead. ***/ //add current guess to usedGuesses list usedGuesses.insert(usedGuesses.begin(), theGuess); if(theGuess==theNumber) { numGuesses++; cout << "That's it the number was " << theNumber << " and you got it in " << numGuesses << " guess(s).\n"; correct=true; } else if(theGuess > theNumber && theGuess <= gameDiff) { cout << "\nToo high.\n"; numGuesses++; } else if(theGuess < theNumber && theGuess > 0) { cout << "\nToo low.\n"; numGuesses++; } else cout << "\nNot a valid guess.\n"; } else cout << "Already used " << theGuess << " as a guess :P.\n"; used=false; }while(!correct); return(numGuesses); } else if(whoGuessing==2) { cout << "\nThe computer will be guessing the number.\n"; theNumber=(rand() % gameDiff+1); /*** * The inside of this do loop could be moved to a function named something like ComputerGuessNumber(...) ***/ do { //picks a random number in the difficulty range for the computers guess theGuess=(rand() % gameDiff+1); //goes through all the used guesses for(theIter=usedGuesses.begin(); theIter!=usedGuesses.end(); theIter++) { //if the current guess was already used set used=true so it skips everything and picks new guess if(*theIter==theGuess) { used=true; break; } } //if guess wasn't used insert it into the usedGuesses list and compare it to the random number if(!used) { usedGuesses.insert(usedGuesses.begin(), theGuess); if(theGuess==theNumber) { numGuesses++; correct=true; } else numGuesses++; } used=false; }while(!correct); cout << "It took the computer " << numGuesses << " guess(s) to guess the correct number, " << theNumber << "\n"; } return(numGuesses); } Tom EDIT: To those wondering what rip-off is talking about, I had overlooked that the array size was initialized at ten and concluded some nonsense from that. I removed references to that... Thanx rip-off, don't know how I overlooked that, especially since he wrote this in his comments :) [Edited by - dimebolt on January 10, 2006 9:22:00 AM]
  7. Quote:Original post by someone2 Hi, How can I get the current transformation matrix (The Model View matrix)? Also, if I have a transformation matrix, is there a function that calculates where a certain vertex would go under this matrix (i.e. it will do the matrix multiplication instead of me doing it myself!) Thank you very much Like haegarr said, the sentence "where a certain vertex would go under this matrix" doesn't specify in which coordinate system you want this point. If it is indeed view space (i.e. the position of the point w.r.t. the camera), no function exists, but multiplying a vector by the matrix is pretty straightforward. I can post code for doing this with the output of the glGetFloatv function if you desire. If instead you want to know the point in screen space (i.e. the position of the point on the window), then there is a function you can use: gluUnProject. It looks a bit tricky at first, but all required parameters can be obtained through the glGetFloatv function. Finally, another commonly used coordinate system: the coordinates in world space (i.e. the position of the point in the world). If you want this, they cannot be obtained through the modelview matrix, as they require multplication with the model matrix only. If this is what you want, you'll need to keep track of the model matrix yourself. Tom
  8. Quote:Original post by deavik I also plan to start using Linux soon, and this might be important, so I'll put in a question here (which will probably useful for the OP, so I didn't start a new thread). Tom, you said that the OpenGL libraries come with the video card driver. How does that work? Is there an OpenGL SDK or something related to the video card I'm using? My driver installations on Windows have been so automatic, that I've never really noted if it copies anything to my system except the driver files. Does the driver update include libraries and if so where? With windows, the OpenGL 1.1 headers and dll are included. Without a vendor driver, this dll will handle all calls as best as it can, but when a driver is available, it will forward calls there to better utilize hardware. Since both dll and headers are only 1.1, using more recent gl-functions requires all this extension horror (that is solved by GLEW, etc). On linux, no such hack is required. If no headers or libraries exist, the vendor driver can put the most recent gl headers and .so in the normal place (/usr/include/GL/gl*.h and /usr/lib/libGL.so). If they do exist, multiple dlls can co-exist: /usr/lib/libGL.so is usually a soft link to the actual library (for example /usr/lib/libGL.so.1.0.7174). Not all drivers install the headers, but if they do they'll probably overwrite any existing headers if these are of a lower version. With the most recent driver+headers installed, there should be no need for any extension loading on linux. Quote:Original post by deavik This page on opengl.org refer to a 'X server integration of GLX' which is a part of the named OpenGL distros. Does anyone know if it comes with Ubuntu? A software implementation doesn't sound attractive. I have no idea, but from the looks of this google query it doesn't seem to be the case. Tom EDIT: and case sensitivity might indeed be the most likely cause of the missing headers. Most linux distributions come with at least some form of OpenGL headers in /usr/include/GL.
  9. Quote:Original post by supagu im a linux newb, but wanna compile my opengl app on linux. Problem is my codeblocks project cant find gl/gl.h how am i supposed to set up the includes/libs for my project to find this? i searched my drive and it came up with gl/gl.h in some nnvidia folder which is not good! i would have expected it in some non-driver specific location like one tut said it should be in usr/include/gl which doesnt exist :-/ do i need so install some package for this or something? Linux distributions don't necesseraly come with OpenGL libraries by default (like windows). Possible sources are: MESA for a non-accelerated OpenGL implementation or the driver by the vendor of your graphics card for hardware accelerated OpenGL. Did you install the nvidia drivers yourself? Perhaps someone chose to install them into that nvidia directory, rather than the usual dirs. In that case it should work fine all the same. If you want them to be in usr/include and usr/lib then you should probably just download the current driver from www.nvidia.com. Getting latest driver is probably a good idea anyway. Tom
  10. dimebolt

    Scenegraphs again

    Quote:Original post by jeroenb I was wondering how to render this scenegraph with regard to the lights. The program must be aware of these lights before rendering the terrain. Should I keep a list of pointers to these lights in the renderer? Could someone please explain this? One possible solution to this problem is to traverse the tree to create a sorted list of objects before rendering. This first traversal visits all nodes, calculates model matrices, and adds (visible, if combined with culling) objects to a sorted list. The sorting criteria can be anything, but obviously lights should end up in front of objects they affect. Since this combines really well with state sorting (making sure that objects with the same shader, texture, etc. are grouped together), it's a nice solution. The renderer is also reasonably easy to implement at this point, as it simply gets a list of nicely ordered objects with the proper matrices already calculated. Tom
  11. Quote:Original post by Sev Hello folks, I picked up the above-mentioned book (2nd edition) and found it to be pretty well written and easy to understand. Unfortunately, I'm having a few problems with compiling the source code. Someone suggested it might not work properly with the version of DirectX I'm running, and that I should try posting here. I've got DirectX SDK 9.0c, with the July 2005 update. I'm mainly getting a lot of errors where it doesn't seem to recognize keywords (IDirectXFileData comes up a lot) or that functions don't match their declarations. Has anyone here worked out the kinks themselves, or are able to give me some insight on what I should try next? Thanks in advance! Please post the specific errors you're getting. Without that, it's hard for us to tell what's wrong. Also specify which compiler/IDE you're using. That way, we can explain you the solution in case you have linker errors. Tom
  12. dimebolt

    lights flickering

    Quote:Original post by indigox3 I'm setting up directional lighting in OGL with something like: float pos[3] = { 1, 0, 0, 0 }; glLightfv ( GL_LIGHT0, GL_POSITION, pos ); glEnable( GL_LIGHT0 ); Which works fine, until I start moving my camera around. At certain camera positions my meshes will look like they are being lit from (-1,0,0)! It could be my modelview matrix is messed up, but if that were the case wouldn't my geometry come out messed up? The geometry gets rendered fine, its just the lighting that flips sometimes. I'm totally stumped by this. The checklist in this FAQ is a good place to start if you have lighting issues. It certainly doesn't cover all possible problems, but at least it covers the most common lighting mistakes. From your description, it sounds like the lighting position is not properly placed (point four in the FAQ), although it is impossible to tell without the code surrounding your glLightfv(...). Your code should look something like this: void MainLoop() { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // clean matrix gluLookAt(...); // create the view matrix glLightfv(.., GL_POSITION, ..); // define the light in world coordinates for (i = 0; i < all_objects; i++) { transform(object); // setup the model matrix draw(object); // draw all objects } } Note, if you place the glLightfv() before the gluLookAt() (or whatever you use to setup the view matrix) the lighting is defined in camera space which could explain the behaviour you experience. Tom
  13. dimebolt

    how do you pass arrays to a function?

    Since you already use std::vector for your strings, why not use them for the shorts as well? That saves you all the trouble of messing with C-style arrays. Tom
  14. dimebolt

    Having problems with gluUnproject

    Quote:Original post by prototypev Quote:Original post by zedzeek why havent u done what i said? I am doing that, I have a debugging text to show the x,y,z in window co-ords as well as x,y,z in object co-ords (after gluUnProject). But your suggestion isn't really helping because like I mentioned, the values I'm getting are wrong :) In defense of zedzeek: He wants you to print the mouse x, y and associated z (depth). You never told us that you printed those values or that they are wrong. The only values you give us are the return values of the function. Since the consensus is that function looks fine, your first assumption should be that at least one of your input values (mouse x,y, projection, modelview and viewport) is incorrect. Therfore, make absolutely sure that the modelview matrix you use is identical to the modelview matrix of your object. This can be done by calling glGetFloatv(GL_MODELVIEW_MATRIX, matrix), both in the render function and in the GetOGLPos function and comparing the contents of the two 16 float arrays. If they differ this might be caused by the fact that you don't load the view matrix before the 3 object transforms (it might still be on the stack, but there is no way for us to tell). A less redundant and therefore safer option would be to just store the array you get with glGetFloatv while rendering the object and pass that array directly in the gluUnProject function. Similar tricks should be done for the viewport and projection if those ever change in your application. If your mouse x, y values are wrong check the parameters of the function. If depth is wrong, you should check for errors with glGetError. In fact, you should probably call glGetError at the end of the function anyhow. Just to make sure nothing went wrong. Tom
  15. Quote:Original post by Ned_K I'm trying to get at the subtle distiction that SEEMS apparent to me since I can have two slightly different expressions(pbuffer = buffer and *pbuffer = buffer) which have identical left-hand sides of the assignment aoperation and different right-hand sides and yet provide exactly the same result. Assuming you have your left and rights mixed up (if you really meant to say that they have different right-hand sides I have really have no idea what you mean and you can ignore me), you should look at it differently: They don't have different left-hand sides because you incorrectly associate the * with the variable name. Consider * part of the type not part of the variable. Writing it like this will perhaps make more sense to you: char* pbuffer = buffer; // assigns the pointer (pointing to element 0 of // buffer) to pbuffer (which happens to be a char*) or char* pbuffer; pbuffer = buffer; // assigns the pointer (pointing to element 0 of // buffer) to pbuffer (which was defined to be a // char* on a different line) Your code means exactly the same thing and will compile to the same executable, but this notation makes it more clear that the * is part of the type. To add to the confusion the * can also be used as an operator to dereference the pointer and access the pointee directly. In other words *pbuffer also has meaning by itself, for example: char* pbuffer; pbuffer = buffer; *pbuffer = 'a'; // the * operator dereferences the pointer, which means // that *pbuffer is a synonym for buffer[0] and has type // char instead of char*. // the result of this code is that the contents of buffer[0] // will be 'a' after the assignment Tom
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!