Page 1 of 2 12 LastLast
Results 1 to 40 of 44

Thread: Struct and vectors...need some dynamic stuff...

  1. #1

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157

    Struct and vectors...need some dynamic stuff...

    Hi,
    I can do this okay.

    Code:
    typedef struct TRIANGLE{
      VERTEX a,b,c;
    };
    vector<TRIANGLE> t;
     
    //or even this
    
    typedef struct QUAD{
      VERTEX a,b,c,d;
    };
    vector<QUAD> q;
    I want to create a struct FACE that stores 3, 4, 5....n number of vertices. This would allow me to parse a string from an .OBJ file that may contain anywhere from 3 or more vertices to define one polygon or face.

    There are work arounds. For example: I could decide that all faces are only 3, 4 or 5 vertices...I could create three respective vectors. As I read each line from the file, I could parse to determine if the line is 3, 4 or 5 and then load into appropriate vectors. I am looking for something a little more flexible.

    Any clues? Suggestions?

    Regards,
    ChuckB

  2. #2
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    use C++ style:

    PHP Code:
    struct POINT
    {
      
    POINT(VERTEX xVERTEX y) : a(x), b(y) {}
      
    VERTEX a,b;
    };

    struct TRIANGLE : public POINT
    {
      
    TRIANGLE(VERTEX xVERTEX yVERTEX z) : POINT(x,y), c(z) {}
      
    VERTEX c;
    };

    struct QUAD : public POINT
    {
      
    QUAD(VERTEX wVERTEX xVERTEX yVERTEX z) :
        
    POINT(w,x), c(y), d(z) {}
      
    VERTEX c,d;
    };

    // ...
    vector<POINT*> vec;

    // ...
    vec.push(new TRIANGLE({2,3},{5,6}));

    //... 
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  3. #3
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    C++ =):
    Code:
    template<int n>
    class FACE
    {
        VERTEX _v[n];
    };
    ...
    vector<FACE<10> > v; // vector of faces with 10 vertices each.
    Only works if you have n faces in all of your faces... otherwise, vectors:
    Code:
    struct FACE
    {
       vector<VERTEX> _v;
    };
    Z.

  4. #4
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Oooh, Nice but i dont see how it would be dynamic cuz the template is always compile time and you wont know how many faces untill run-time, faces will always be 1+... maybe a container class should better suit the situation?
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  5. #5

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157
    MoMad,
    I have looked at your sample...and it is my understanding that this is a C++ example as opposed to what I offered which I take is a C example. Am I right about that?

    I need to get jump started since this code format is new to me.

    Code:
    struct POINT
    {
      POINT(VERTEX x, VERTEX y) : a(x), b(y) {}
      VERTEX a,b;
    };
    If you have got the time, could you do some explaining on this for me?
    The POINT structure contains two vertices a and b. Right?
    Why doesn't the point contain only one vertex?
    Each vertex a and b has 3 values (say x,y,z). Right?
    You are using VERTEX because you would have defined it earlier like...

    typedef struct VERTEX{
    float x,y,z;
    }

    Right? Or a C++ version?

    What does the ':a(x),b(y){}' mean?

    Z, I am comfortable using the .reserve property for a vector. I intend to read the number of 'faces' during program load and use this for now. There is a possibility to reserve a 10 pointed face in a vector....in which I have an element indicating how many of the 10 points are used. This seems wasteful of space though...which is probably a real premium loading 3D models.

    Regards,
    ChuckB

  6. #6
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    Just throwing that template thing out there =). They really are the most useful thing since sliced bread =).

    Best bet would be to use the vector method.

    Dunno what MoMad was doing with that POINT class... doesnt make sense =). the a(x), b(y) {} is a constructor initiialization list. Essentially, its the same as doing this:
    Code:
    POINT(VERTEX x, VERTEX y)
    {
        a = x;
        b = y;
    };
    Except that using the initializer list calls the class's copy constructor (you can get into trouble with that =).

    And, if you are using a vector, you cant be using C =). I think the point was the inheritance. The only problem there is that you dont know how many VERTEX structures are in each pointer, so it is useless without using RTTI, which nearly defeats the purpose of inheritance (to be able to refer to an object of one type with a pointer to a parent type, without needing to know the actual type).

    Z.

  7. #7
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Well what im trying to get at eventually is this:

    C++ will give you the following for free:

    a. Copy constructor
    b. = operator
    c. destructor

    So you can use these without needed to explicitly define them yourself.

    I dont know what vertex is but now that I know, I can give you a better sample:

    PHP Code:

    struct VERTEX 
    {
      
    VERTEX (float afloat bfloat c) : x(a), y(b), z(c) {}
      
    float xyz;
    }

    struct FACE {
      
    FACE(VERTEX a) : x(a) {}
      
    VERTEX x;
    }

    struct PLANE : public FACE {
      
    PLANE  (VERTEX aVERTEX b) : FACE(a), y(b) {}
      
    VERTEX y;
    }

    struct TRIANGLE : public FACE {
      
    TRIANGLE (VERTEX aVERTEX bVERTEX c) : FACE(a), y(b), z(c) {}
      
    VERTEX y,z;
    }

    struct QUAD : public FACE {
      
    QUAD (VERTEX aVERTEX bVERTEX cVERTEX d) : FACE(a), y(b), z(c), w(d) {}
      
    VERTEX y,z,w;
    }

    // ... and so on 
    But notice that in C++ a struct acts like a class but with all members "public". We created a base class of FACE and derived everything else from it. The reason i did this is because I want all of these classes to have something in common! Just like DD or D3D, you can tell the different versions of FACE apart by finding out the size of the object

    Anyways, starting at the plane, the plane has 1 extra vertex than the face, but its constructor takes 2 arguments, they are being assigned the two different vertexes... all the way down the list...

    Bottom line is, the way i am creating an inheritance table will help you make your faces pretty much anything because they will essentially all be a "derived" copy of the "base" class which is FACE.

    Like Z said, the a(x), b(y) {} are just another way of saying a = x and b = y; but since you arent using dynamic data in the class-per se, remember that C++ will give you a copy constructor for free. Well if you have dynamic data, this copy constructor must be overwritten. It also gives you a = operator which is essentially the same thing.

    Anyways, with the way i set up the classes above you can continue and add more vertexes to each level, you probably need a max of 4 (QUAD) but hey u can go 5 or 6 or 7.... etc or x.

    So in your vector you do this:

    PHP Code:
    vector<FACE*> vec;

    // ...

    // somewhere in the input loop
    // suppose you read in 4 vertexes and wanna add it to the list
    vec.push(new QUAD(a,b,c,d));

    // or how about 2
    vec.push(new PLANE(a,b));

    // or etc...
    vec.push(new FACE(a)); 
    Ofcourse, this sollution will still have an associated if/else/switch statement, but it makes for a nice clean getaway.
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  8. #8

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157
    MoMad and Z,
    Thanks for working with me on this. I just wrote this small sample using MoMad's format above.

    I left out face, plane and quad to keep it simple. I want to start with a VERTEX, a 3D point in space (I use x,y,z). I want TRIANGLE to inherit three vertices....I'll call these 3D points s,t,u.

    Code:
    #include <stdio.h>
    #include <cstdlib>
    
    struct VERTEX {
      VERTEX (float a, float b, float c) : x(a), y(b), z(c) {}
      float x, y, z;
    };
    struct TRIANGLE : public VERTEX {
      TRIANGLE (VERTEX a, VERTEX b, VERTEX c) : s(a), t(b), u(c) {}
      VERTEX s, t, u;
    };
    
    int main(int argc, char *argv[])
    { 
      VERTEX a,b,c;
      vector<VERTEX*> v;
      a.x=12.0;
      a.y=15.5;
      a.z=14.5;
      b.x=16.0;
      b.y=13.5;
      b.z=14.5;
      c.x=18.0;
      c.y=10.5;
      c.z=14.5;
      v.push(new TRIANGLE(a,b,c));
      system("pause");
      return 0;
    }
    I am getting compiler errors regarding the second struct above...something about 'no matching function call for VERTEX::VERTEX'. Now, I suspect I am missing some important concepts here that I didn't glean from your earlier postings. Any more light on the subject would be helpful.

    Regards,
    ChuckB

  9. #9
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    Be careful with those copy constructors:
    Code:
    class x()
    {
    public:    
        x(){p=new char[10];}
        ~x(){if(p) delete p; p = NULL;}
        private:
             char * p;
    };
    
    ...
    
    x* y = new x;
    x* z = new x(y);
    delete y;
    delete z;
    Chuck, try just adding a trivial VERTEX constructor:
    Code:
    struct VERTEX{
        VERTEX(){}
        ...
    };
    Chuck, why are you inheriting TRIANGLE from VERTEX? This doesnt make sense, as you end up with a class that essentially looks like this:
    Code:
    struct TRIANGLE
    {
        VERTEX s, t, u;
         float x, y, z;
    };
    Z.

  10. #10
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Z, I said that as long as you dont have dynamic data (new/delete created data), you are fine using the copy constructor provided. But it looks like MSVC doesnt support the "free" stuff you get with C++ classes.

    do it like this then:
    PHP Code:
    struct VERTEX {
      
    VERTEX (const VERTEXv) : x(v.x), y(v.y), z(v.z) {}
      
    VERTEX (float a=0.0float b=0.0float c=0.0) : x(a), y(b), z(c) {}
      
    float xyz;
    }

    struct FACE {
      
    FACE(VERTEX a) : x(a) {}
      
    VERTEX x;
    }

    // needs FACE and VERTEX
    struct PLANE : public FACE {
      
    PLANE  (VERTEX aVERTEX b) : FACE(a), y(b) {}
      
    VERTEX y;
    }

    // needs FACE and VERTEX
    struct TRIANGLE : public FACE {
      
    TRIANGLE (VERTEX aVERTEX bVERTEX c) : FACE(a), y(b), z(c) {}
      
    VERTEX y,z;
    }

    // needs FACE and VERTEX
    struct QUAD : public FACE {
      
    QUAD (VERTEX aVERTEX bVERTEX cVERTEX d) : FACE(a), y(b), z(c), w(d) {}
      
    VERTEX y,z,w;

    If you just wanna use TRIANGLE you will need FACE and VERTEX at least. Now this code should work wether VC gives you your rights or not!

    BTW: Learn the initialization list, alot of times, when you write polymorphism code (inheritance and deriving, etc) you will be REQUIRED to backward pass base member initializations only thru the initilizer list. (eh, *** did i just say?) English: You will be required to use the initilizer list when you derive a class (if you want to initialize the base members).

    E.G
    PHP Code:
    class Base {
      public:
        
    Base (int a 0) : x(a) {}

      protected:
        
    bool done;

      private:
        
    int x;
    }; 
    // <-------------- dont forget semi-colon

    class DerivedFromBase : public Base {
      public:
        
    DerivedFromBase (int abool d) : Base(a), done(d) {}
        
    // you see how you have direct access to done but not to a?
        // private says only the class that owns it and friend classes
        // can see it or access it.  protected says, self, friends, and 
        // derived child classes can see it and access it.  The only way
        // you can initialize private data is by calling a function that
        // does this, like the constructor (a special function).
    }; 
    [edit]
    BTW: I changed the vertex constructor to default the vertex to {0.0, 0.0, 0.0} if nothing gets passed. Thus default and trivial constructor.
    Last edited by MoMad; Oct 1st, 2002 at 01:26 PM.
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  11. #11
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    Dont initialize anything in your default VERTEX constructor. Doing so can be pointless in many situations(ie, you are going to fill it anyway, what is the point of 3 float copys?). Also, you dont HAVE to use initializer lists(i dont). To call a constructor of a Base class, simply call it in the derived constructor (ie, "Base(a)"). Nothing wrong there...

    I would have to say, though, that this is a bad use of inheritance. Read my thoughts on RTTI a few posts up =).

    Z.

  12. #12

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157
    Hi,
    Here is my fundamental problem to following this thread. I know how to create structures and classes. However, MoMad's format for a class differs from what I have seen. I understand inheritance and I have a program that does just that...but not this style.

    Is this a class or not...

    Code:
    // needs FACE and VERTEX
    struct PLANE : public FACE {
      PLANE  (VERTEX a, VERTEX b) : FACE(a), y(b) {}
      VERTEX y;
    }
    If it is not, is it a C++ way to do structures?
    If it is a class...I am used to seeing it written as

    Code:
    class PLANE: public FACE(
      VERTEX s, t;
      public:
      
      PLANE (VERTEX a, VERTEX b){  //constructor
        s=a;
        t=b;
      }
      ~PLANE(){}  //destructor
    }
    Z, I understood in concept what I was doing was wrong...just couldn't see clearly what was being explained.
    MoMad, I have to figure out what this format is you are using because it is new to me...and I hope somehow it explains my need for dynamic stuff. :-)

    I'll look for some web resources I can download and review that explains more clearly what you guys have been writing about.

    Feeling a bit fustrated right now...need to do some more reading. :-)

    Regards,
    ChuckB

  13. #13
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    so sorry.
    in C++ a struct is just a class with all methods and members "public" as opposed to class having all members and variables "private" by default.

    So you can just write that as a class instead of struct, but be sure to put public: where appropriate or you would not be able to say obj.x (will not be able to access members and variables)..

    FACE(a) just says "initialize the face with this parameter"
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  14. #14
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Originally posted by Zaei
    Dont initialize anything in your default VERTEX constructor. Doing so can be pointless in many situations(ie, you are going to fill it anyway, what is the point of 3 float copys?). Also, you dont HAVE to use initializer lists(i dont). To call a constructor of a Base class, simply call it in the derived constructor (ie, "Base(a)"). Nothing wrong there...

    I would have to say, though, that this is a bad use of inheritance. Read my thoughts on RTTI a few posts up =).

    Z.
    Alright how about this then:
    PHP Code:
    class VERTEX {
    public:
      
    VERTEX () {}
      
    VERTEX (const VERTEXv) : x(v.x), y(v.y), z(v.z) {}
      
    VERTEX (float afloat bfloat c) : x(a), y(b), z(c) {}
      
    float xyz;

    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  15. #15
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Ok, I think i might've went too fast explaining my logic on this:


    PHP Code:
     // you want to have a dynamic way of adding vertexes right?

    // Here is the vertex class
    class VERTEX {
    public:
      
    VERTEX () {}
      
    VERTEX (const VERTEXv) : x(v.x), y(v.y), z(v.z) {}
      
    VERTEX (float afloat bfloat c) : x(a), y(b), z(c) {}
      
    float xyz;
    };

    // Now here is a class that will give you however many number of vertexes u want
    class FACES {
      private:
        
    int vertCount;
        
    VERTEX pVertexes;

      public:
        
    FACES () : vertexes(0), vertCount(0) {}
        
    // i wont make a cc but theres no need for it really

        // initialize with space for how many vertecies
        
    bool Init (int count) {
           
    Release ();
           
    vertCount count;
           if (
    vertCount 0) {
             
    vertexes = new VERTEX vertCount ];
             return 
    true;
           }
           return 
    false;
        }

        
    // add to the list
        
    bool AddVert (VERTEX vertint index) {
          if (
    index || index >= vertCount) {
            return 
    false;
          }
          
    vertexes[index]->vert->x;
          
    vertexes[index]->vert->y;
          
    vertexes[index]->vert->z;
          return 
    true;
       }

        
    // Resize the list (if you change ur mind)
        
    bool Resize (int newsize) {
          if (
    newsize <= vertCount) {
            return 
    false;
          }
          
    VERTEX pVert = new VERTEX[newsize];
          if (
    pVert) {
            for (
    int i 0vertCounti++) {
              
    pVert[i].vertexes[i].x;
              
    pVert[i].vertexes[i].y;
              
    pVert[i].vertexes[i].z;
           }
           
    Release ();
           
    vertexes pVert;
           
    vertCount newsize;
           return 
    true;
         }
         return 
    false;
       }

        
    // Release all associated memory
        
    void Release () {
           if (
    vertexesdelete [] vertexes;
           
    vertCount 0;
           
    vertexes 0;
        }

        
    // Get method (returns an array)
        
    VERTEX GetVertexes () { return pVertexes; }
        
    int GetCount () const { return vertCount; }
    };

    // also you can overload the iostream operators << and >> 
    I dont really have much time to put the actual code right now, but i hope this idea is more understandable than my previous one.

    [edit] Aaah what the hell, i added the code (look again)[/edit]
    Last edited by MoMad; Oct 1st, 2002 at 03:42 PM.
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  16. #16
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    That works, MoMad, but using a vector would be safer, and only add (I believe) one pointer's worth of storage usage.

    And there IS a need for a copy constructor in your code. See the code I posted above =).

    Chuck: When using C++, the only difference between a struct and a class is that a struct defaults to having public members, while a class defaults to private. That is the ONLY difference.

    So yes, it IS a class, only instead of using a usual looking function for a constructor, it uses the initializer list. You can do a bit of reading on that.

    As to my posts about the usage of inheritance in this instance... let me demonstrate:
    Code:
    struct p
    {
       float x, y, z;
    };
    struct tri : public p
    {
       p a, b, c;
    };
    struct face : public p
    {
       p a, b, c, d;
    };
    ...
    p* stuff = new tri[10];
    stuff[0].a.x = 0; // cant do this, a doesnt exist
    You see? Since p only contains 3 floats, You dont actually know how many vertices are hiding in a p*.

    Z.

  17. #17
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    I guess if you use a vector, it defeats the purpose of this class that i posted, and it will be much safer to use a vector but you need to do the inheritance stuff if you're gonna do a vector because ther all wont be the same size (or perhaps a vector of vectors).
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  18. #18
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Originally posted by Zaei

    ...
    p* stuff = new tri[10];
    stuff[0].a.x = 0; // cant do this, a doesnt exist
    [/code]
    typecast it to tri! ((tri *) stuff[0]).a.x works. But when you are dealing with having a base class thats the same as the child class, then it really starts looking weird.
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  19. #19
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    How do you guarentee that it IS a tri?
    Code:
    vector<p*> v;
    v.push_back(new p);
    v.push_back(new tri);
    v.push_back(new p);
    v.push_back(new face);
    Z.

  20. #20
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    duh, i kno, but if you wrote the code wouldnt you know?
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  21. #21
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    Not necessarily...
    Code:
    void LoadFromFile(..., vector<p*>& v)
    {
        ...
        if(prim_type == string("face"))
        {
             v.push_back(new face(face_data));
        }
        if(prim_type == string("tri"))
        {
              v.push_back(new tri(face_data));
        }
        ...
    }

    Z.

  22. #22

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157
    WOW!
    I really appreciate this discussion. MoMad...that's a lot of coding...thanks!

    Z, I am going to look at the code you wrote...
    v.push_back(new tri);
    the idea of pushing an object 'tri' is new to me inside the ( ).

    I read chapters 4 & 5 tonight from ANSI/ISO C++ Professional Programmer's Handbook by Danny Kale (Online Version). It helped me to understand that a struct is a shorthand for class...except everything is public in a struct...and a class is by default private.

    I even understand the constructor style used above and the related initialization.

    I will study the code here and try to get a variation working in my test program....and I will utilize vectors...as I finally understand them enough to use them. :-)

    To put all of this together I intend on writing a program that will read a basic .OBJ 3D file that includes vertices for a 3D model and various face sizes: triangle, quads, etc. Reading the file, parsing each individual line, loading into the appropriate sized vector and error handling are my goal. All in C++ of course... :-)

    Thanks!
    Regards,
    ChuckB

  23. #23
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    Just be sure that you can get the pointer back , or you end up with a memory leak =).

    Z.

  24. #24
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Doesnt pop_back give it back to you?

    PHP Code:

    ptr;

    do {
      
    ptr v.pop_back();
      if (
    ptr)
        
    delete ptr;
    } while (
    ptr); 
    ... maybe not, im not too familiar with vector, but i know its basic functions and i think i kno but with a push, there should be a pop right? lol.
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  25. #25
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    No, it was just a general warning.. ie, dont do this:
    Code:
    strcpy(new char[128], "Hello, World!");
    pop_back removes the last element, you would probably be better off using an iterator...

    Z.

  26. #26

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157
    Hi,
    Can you explain something about "for_each"? I figured this was related to this thread since it includes a class.

    Code:
    //this came from The Standard C++ Library
    class PrintIn{
      public:
        void operator()(int elem) const {
          cout  << elem << ' ';
        }                      
    };
    
    
    int main()
    {
      . . . . 
    
      for_each(coll.begin(), coll.end(), PrintIn());
    
      . . . .
    }
    I understand that PrintIn is the class name. I know there are no constructors here so a default constructor is used. I know also that what is happening is operator overloading. Forcing the '( )' to receive an int from the calling function. This PrintIn() becomes the third argument in the for_each above.

    How could I eliminate the class PrintIn and simply type an expression for the 3rd argument that does the same thing?

    Something like 'cout << int elem'. This doesn't work of course, but this would help me to understand more thoroughly.
    Regards,
    ChuckB

  27. #27
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    for_each is an STL algortim that performs a function on all elements on a range specified by two iterators, so in other words it does something for each element within the range, the last parameter is the unary function to which for_each passes each element, in this case PrintIn, which is a functor (function object), a class that acts as a function. The compilers tends to inline functors better than regular functions and functors can have a private state as well (which i personally dislike, as much as i dislike OOP in general)

    no you can't type the expression inline, maybe if you tweak with macros, but C++ is an old language, they didn't know of the problems with the complexity before they came..
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  28. #28
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Function pointers cannot be inlined, a member function of an object can be, and the object itself is 0 bytes large if it doesn't contain data or virtual functions. It is therefore more efficient than a function pointer (which you could pass, nothing wrong with it).

    MoMad: if you think about it you class hierarchy is a very bad example of OOP. It revolts against any definition of inheritance I've heard or read. Especially the "is a" connection. "A quad IS A triangle"? Doesn't fit. I'd say go with Zs templated version. Derive it from a common base class FACE:

    Code:
    class BASE_FACE {
    public:
      // This is to find out the number of vertices
      virtual unsigned int GetVertexCount() = 0;
    };
    
    template<unsigned int nVertices>
    class FACE : public BASE_FACE {
    public: // for easier use
      VERTEX arV[nVertices];
      virtual unsigned int GetVertexCount() {
        return nVertices;
      };
    };
    
    vector<FACE_BASE*> v;
    
    v.push_back(new FACE<3>);
    v.push_back(new FACE<10>);
    Just be extremly careful with this. The vector doesn't delete objects for you. Before you remove an item from the vector you must ALWAYS first call delete on it (or get a copy of the pointer and call delete later). This include a vector that goes out of scope.

    An even better solution is this: only use triangles as faces. No current 3D car accepts other faces anyway as they are not guaranteed to be plane, so why bother having them in the first place?
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  29. #29

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157
    Kedaman, Thanks for clarifying the function object 'functor'.

    CornedBee, I didn't know 3D cards support only triangles. I was experimenting with anim8or 3D software and noticed that when I exported an .OBJ file, it had faces with 3 or 4 points...I read the spec later for .OBJ files, and it implied that a face could consist of many points...which is what started me on this thread in the beginning.

    I suppose I could only deal with triangles and ignore other polygons OR have my program convert polygons to triangles...so as not to lose any mesh data. Let me kick that idea around.

    Regards,
    ChuckB

  30. #30
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    I think the X loader converts all higher faces to sets of triangles.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  31. #31
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Originally posted by Zaei
    No, it was just a general warning.. ie, dont do this:
    Code:
    strcpy(new char[128], "Hello, World!");
    pop_back removes the last element, you would probably be better off using an iterator...

    Z.
    But strcpy returns that new char[128] anyways... so you can say:

    char * strptr = strcpy(new char[128], "Hello, World!");

    Originally posted by CornedBee
    Especially the "is a" connection. "A quad IS A triangle"?
    Thats why I didnt use TRIANGLE as the base class, but I see what you mean though. The template works better in this case, but you can typedef the different templates anyways.. so that you will have a set amount of vertexes in any case so make use of this.

    Use what CornedBee wrote, with a little bit of adition:

    PHP Code:

    // the typedefs should look like
    typedef FACE<3TRI_FACE;
    typedef FACE<4QUAD_FACE;
    // etc
    // when u are adding, you can just say new TRI_FACE or whatever
    // this is just an alias for FACE<3>.  Also you can pass in stuff to
    // the constructor

    //...

    // this could be in a clear function (it just clears the memory used)
    FACE_BASE ptr;

    while (
    ptr v.back()) { // get the last element
      
    if (ptr) { // if it exists, delete it
        
    delete ptr;
        
    ptr 0;

        
    v.pop_back (); // and erase it from the vector
      
    }
       
    // now the pointer to the last element is decremented.

    hope that helps
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  32. #32
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    I know, MoMad, but the way I typed it, you lose the pointer =). You might see a REAL newbie do that occasionally =).

    Chuck, the reason 3d Cards support only triangles is that A) you can make any polygon with a set of triangles, and B) triangles cannot be concave (for instance, a quad shaped so that it forms a v shape is concave), which allows for certain optimizations for rendering.

    Z.

  33. #33
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Oh, and I forgot:

    Copy constructors are defined implicitly. They are also called implicitly. But if you want to call a copy constructor explicitly you need to define it explicitly. And you may not call the copy constructor in the copy constructor itself (think about it a little, it would be an endless recursion).

    Here's another case where you must use a constructor list:
    Code:
    class A {
    public:
      const int m_cnSomething;
    };
    How do you initialize this? Global constants can be initialized like this:
    const int c_Constant = 4;
    Static member constants the same way:
    Code:
    class B {
    public:
      static const int sc_Whee;
    };
    const int B::sc_Whee = 5;
    (Side note: Sun thought this syntax to be confusing and changed it in Java)

    Does this work with member constants too?
    Code:
    class A {
    public:
      const int m_cnSomething;
    };
    // No, compiler error!
    const int A::m_cnSomething = 0;
    
    
    class A {
    public:
    // No, compiler error!
      const int m_cnSomething = 1;
    };
    Since the constant is defined per instance we need a place to initialize it per instance: the constructor!
    Code:
    class A {
    public:
      const int m_cnSomething;
      // Sorry, assignment to const illegal!
      A(int i) { m_cnSomething = i; };
    };
    There is only one way to correctly initialize constants: the constructor list.
    Code:
    class A {
    public:
      const int m_cnSomething;
      // Sorry, assignment to const illegal!
      A(int i) : m_cnSomething(i) {};
    };

    Of course there was absolutly no point in writing such a long post for something that nobody cares for, but I don't care either.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  34. #34
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Wow, I didnt know you can assign a variable to a constant... isnt there some rules about that?

    its like saying:

    const int num = i;
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  35. #35
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    const means not mutable, but when you first initiate a constant its not assigning, the constant has to have a value, const only means that it can't be changed after that (although i think thats what CB tried to explain..)
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  36. #36
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    I see... So I never thought of it this way, maybe thats why I never successfully made a const variable inside a class: (i always used enums )

    enum {
    MAX_VARS = 10;
    }

    on another note, how is squirrel coming? I havent seen any download links or anywhere to get a piece of it on the site... Are you hosting it somewhere else? Is it open source? Can I beta test it or take a look at it (sneak peek or whatever the deal is?)
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  37. #37
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    I've just updated my site, check the link in my sig. The compiler is going to be out soon for beta testing, right now i'm revising the most crucial change in the language so far, which has to extends the complexity of contructs beyond the scope limits of lamda calculus. If the latest change turns out to be successful then the compiler should be out quite soon, otherways I will have to come up with something new..
    My site is totally renewed, the latest changes in syntax are updated and the summary is corrected, also there's some example code on squirrel just to show how the abstraction works, when the language definitions are out you wont be working with such lowlevel matters though, so its not going to look that scary, if you don't like math or logic then its easy to hide..
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  38. #38

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157
    Hi,
    I have chosen to use the .OBJ file format for 3D objects. With freeware 'Anim8or' (www.anim8or.com) I can import 3DS files, edit or create and then export in .OBJ file format.

    The .OBJ format is easy.

    g Fuselage
    # No. points 2328:
    v -96.6345 9.10905 42.9418
    . . .
    # No. faces 4632:
    f 1//4633 1166//5894 584//5282
    . . .

    'v' means vertex and 'f' means face. All faces are triangles. I have two structures VERTEX and FACE (triangle). I read No. of points and create a VERTEX vector with 2328 elements...4632 with the the FACE vector. Works great!! Even loads into OpenGL program.

    Here is the problem. The 'g' stands for group. There can be several groups in a .OBJ file. I.e. fuselage, cockpit, landinggear, etc.

    ?????????????????????????????
    How do I generate several different VERTEX vectors and FACE vectors for the file?? I will not know how many groups to create until the file is read. Any suggestions?

    Incidently, I am not using the 'texture' or 'normal' values at present...just vertices and faces.

    I am including the function that parses each string read from a file. I would appreciate any ideas on making the function smaller and/or more efficient. There is not error checking.

    Code:
    //process string read from file and places into appropriate vectors
    void ProcessData(string s)
    {
      VERTEX vtemp ={0.0f,0.0f,0.0f};
      FACE ftemp={0,0,0};
      
      //Parses string = "# No. points 2328:"
      if(s.substr(0,12)=="# No. points"){
        mbGetVertex=true;
        mbGetFace=false;
        int g=s.find(":");
        s= s.substr(13,g-12);
        mnVertices=atoi(s.c_str());
        cout << mnVertices << endl;
        v.reserve(mnVertices +1);
      }
      
      //Parses string = "v 104.17 2.36533 -13.3778"
      if((s.substr(0,2)=="v ")&&(mbGetVertex==true)){
        mnVertexPos++;
        int g=0;
        int h=0;
     
        for (int m=2;m< s.size();m++){
          if((s.substr(m,1)==" ") &&(g!=0))
            h=m;
          if((s.substr(m,1)==" ")&&(g==0)){ 
            g=m; //stores second space
          }
        }
        string t=s.substr(2,g-2);
        vtemp.x=atof(t.c_str());
        t=s.substr(g+1,h-g);
        vtemp.y=atof(t.c_str());
        t=s.substr(h+1);
        vtemp.z=atof(t.c_str());
        v.push_back(vtemp);  }
      
      //Parse string = "# No. faces 4632:"
      if(s.substr(0,11)=="# No. faces"){
        mbGetFace=true;
        mbGetVertex=false;
          int g=s.find(":");
          s= s.substr(12,g-11);
          mnFaces=atoi(s.c_str());
          cout << mnFaces << endl;
          f.reserve(mnFaces);
      }
      
      //Parse string = "f 35//4667 746//5444 1559//6291"
      if((s.substr(0,2)=="f ")&&(mbGetFace==true)){
        mnFacePos++;
        int g=0;
        int h=0;
     
        for (int m=2;m< s.size();m++){
          if((s.substr(m,1)==" ") &&(g!=0))
            h=m;
          if((s.substr(m,1)==" ")&&(g==0)){ 
            g=m; //stores second space
           }
        }
        int fs;
        string t=s.substr(2,g-2);
        fs = t.find("/");
        t=t.substr(0,fs);
        ftemp.a = atoi(t.c_str());
          
        t=s.substr(g+1,h-g);
        fs = t.find("/");
        t=t.substr(0,fs);
        ftemp.b = atoi(t.c_str());
    
        t=s.substr(h+1);
        fs = t.find("/");
        t=t.substr(0,fs);
        ftemp.c = atoi(t.c_str());
        f.push_back(ftemp);
       }
    }
    Regards,
    ChuckB
    I learn Robotics, Electronics and Game Programming at http://www.gameinstitute.com

  39. #39
    Frenzied Member Zaei's Avatar
    Join Date
    Jul 2002
    Location
    My own little world...
    Posts
    1,710
    Need a GROUP struct =).

    GROUP holds the number of faces and vertices in the group. Just read each group individually, and then add each to a vector of groups.

    Z.

  40. #40

    Thread Starter
    Addicted Member ChuckB's Avatar
    Join Date
    Jul 2002
    Location
    South Carolina, USA
    Posts
    157
    Let me see if I follow what you are saying...

    typedef struct GROUP {
    VERTEX v;
    FACE f;
    };

    vector<GROUP> g;
    g.reserve(1); //I like using 1 as first location...skip 0 pos.

    //read 1st group...

    vector<VERTEX> g[1].v;
    vector<FACE> g[1].f;
    g[1].v.reserve(number of vertices of 1st group);
    g[1].f.reserve(number of faces of 1st group);


    Is this what you are saying? How about my formatting above..does that look correct?

    Regards,
    ChuckB
    I learn Robotics, Electronics and Game Programming at http://www.gameinstitute.com

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width