Boost logo

Boost Users :

From: Václav Haisman (v.haisman_at_[hidden])
Date: 2007-11-17 05:39:48


Robert Dailey wrote, On 16.11.2007 20:58:
> Hi,
>
> Right now I'm trying to develop a tricky structure that MAY contain any
> of the following information:
>
> - Vertex coordinates (x,y,z)
> - Color components (r, g, b)
> - Texture coordinates (u, v)
>
> Basically, I'd end up having a structure that looks like this (with all
> information included):
>
> struct Vertex
> {
> float x,y,z; // vertex coordinates
> unsigned char r, g, b; // color components
> double u,v; // texture coordinates
> };
[...snipped...]
Boost.Optional comes to my mind. But can you live with one extra bool for
each of the optional structures? Or Boost.Variant but you still end up with
bigger structures than is strictly necessary.

If you care about the memory and in your specific case you could exploit that
the structures share common initial sequence (9.2/16). But then you will have
to sprinkle your source with lots of reinterpret_casts or use lots of macros.

Neither is perfect, it is up to you to weight the possibilities.

--
wilx

#include <iostream>
#include <boost/variant.hpp>
#include <boost/optional.hpp>

struct Bools
{
  bool a : 1;
  bool b : 1;
  bool c : 1;
};

struct Vertex1
{
  float x,y,z; // vertex coordinates
  unsigned char r, g, b; // color components
  double u,v; // texture coordinates
};

struct Vertex2
{
  float x,y,z; // vertex coordinates
  bool has_rgb;
  unsigned char r, g, b; // color components
  bool has_texture;
  double u,v; // texture coordinates
};

struct Vertex3
{
  float x,y,z; // vertex coordinates
  unsigned char r, g, b; // color components
  bool has_rgb : 1;
  bool has_texture : 1;
  double u,v; // texture coordinates
};

struct BaseVertex
{
  float x,y,z;
  bool has_rgb : 1;
  bool has_texture : 1;
};

struct RGBVertex : public BaseVertex
{
  unsigned char r, g, b; // color components
};

struct TxtVertex : public BaseVertex
{
  double u, v; // texture coordinates
};

struct RGBTxtVertex : public BaseVertex
{
  unsigned char r, g, b; // color components
  double u, v; // texture coordinates
};

union UniversalVertex
{
  BaseVertex base;
  RGBVertex rgb;
  TxtVertex txt;
  RGBTxtVertex rgb_txt;
};

namespace C
{

struct BaseVertex
{
  float x,y,z;
  bool has_rgb : 1;
  bool has_texture : 1;
};

struct RGBVertex
{
  float x,y,z;
  bool has_rgb : 1;
  bool has_texture : 1;
  unsigned char r, g, b; // color components
};

struct TxtVertex
{
  float x,y,z;
  bool has_rgb : 1;
  bool has_texture : 1;
  double u, v; // texture coordinates
};

struct RGBTxtVertex
{
  float x,y,z;
  bool has_rgb : 1;
  bool has_texture : 1;
  unsigned char r, g, b; // color components
  double u, v; // texture coordinates
};

union UniversalVertex
{
  BaseVertex base;
  RGBVertex rgb;
  TxtVertex txt;
  RGBTxtVertex rgb_txt;

  UniversalVertex (UniversalVertex const & other)
  {
    switch (base.has_rgb | (base.has_texture))
      {
      case 0:
        base = other.base;
        break;

      case 1:
        rgb = other.rgb;
        break;

      case 2:
        txt = other.txt;
        break;
        
      case 3:
        rgb_txt = other.rgb_txt;
      }
  }
};

}

namespace B
{

  typedef boost::variant<C::BaseVertex, C::RGBVertex, C::TxtVertex,
                         C::RGBTxtVertex> UniversalVertex;

}

namespace O
{

  struct RGB
  {
    unsigned char r, g, b;
  };

  struct Txt
  {
    double u, v;
  };

  struct UniversalVertex
  {
    float x, y, z;
    boost::optional<RGB> rgb;
    boost::optional<Txt> txt;
  };

}

#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
#define PRINT_SIZEOF(x) {std::cout << "sizeof (" STRINGIFY(x) "): " << sizeof (x) << std::endl;}

int
main ()
{
  PRINT_SIZEOF (Bools);
  PRINT_SIZEOF (Vertex1);
  PRINT_SIZEOF (Vertex2);
  PRINT_SIZEOF (Vertex3);

  PRINT_SIZEOF (BaseVertex);
  PRINT_SIZEOF (RGBVertex);
  PRINT_SIZEOF (TxtVertex);
  PRINT_SIZEOF (RGBTxtVertex);
  PRINT_SIZEOF (UniversalVertex);

  PRINT_SIZEOF (C::BaseVertex);
  PRINT_SIZEOF (C::RGBVertex);
  PRINT_SIZEOF (C::TxtVertex);
  PRINT_SIZEOF (C::RGBTxtVertex);
  PRINT_SIZEOF (C::UniversalVertex);

  PRINT_SIZEOF (B::UniversalVertex);

  PRINT_SIZEOF (O::UniversalVertex);

  PRINT_SIZEOF (UniversalVertex[2]);
  PRINT_SIZEOF (C::UniversalVertex[2]);
  PRINT_SIZEOF (B::UniversalVertex[2]);
  PRINT_SIZEOF (O::UniversalVertex[2]);
}




Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net