/** @file GLG3D/VAR.h @maintainer Morgan McGuire, morgan@graphics3d.com @created 2001-05-29 @edited 2004-01-06 */ #ifndef GLG3D_VAR_H #define GLG3D_VAR_H #include "GLG3D/RenderDevice.h" #include "GLG3D/getOpenGLState.h" #include "GLG3D/glFormat.h" #include "GLG3D/VARArea.h" namespace G3D { /** A pointer to an array of vertices, colors, or normals in video memory. It is safe to copy these (the pointer will be copied, not the video memory). There is no destructor because the memory referenced is freed when the parent VARArea is reset or freed. */ class VAR { private: friend class RenderDevice; VARAreaRef area; /** For VBO_MEMORY, this is the offset. For MAIN_MEMORY, this is a pointer to the block of uploaded memory */ void* _pointer; /** Size of one element */ size_t elementSize; int numElements; uint64 generation; GLenum underlyingRepresentation; /** The initial size this VAR was allocated with. */ size_t _maxSize; void init(const void* sourcePtr, int _numElements, VARAreaRef _area, GLenum glformat, size_t eltSize); void update(const void* sourcePtr, int _numElements, GLenum glformat, size_t eltSize); /** Performs the actual memory transfer (like memcpy). The dstPtrOffset is the number of bytes to add to _pointer when performing the transfer. */ void uploadToCard(const void* sourcePtr, int dstPtrOffset, size_t size); void set(int index, const void* value, GLenum glformat, size_t eltSize); // The following are called by RenderDevice void vertexPointer() const; void normalPointer() const; void colorPointer() const; void texCoordPointer(unsigned int unit) const; void vertexAttribPointer(unsigned int attribNum, bool normalize) const; public: /** Creates an invalid VAR */ VAR(); /** Uploads the memory. The element type is inferred from the pointer type by the preprocessor. Sample usage:
	    // Once at the beginning of the program
        VARAreaRef area = VARArea::create(1024 * 1024);

        //----------
        // Store data in main memory
	    Array vertex;
        Array     index;
		
        //... fill out vertex & index arrays

        //------------
        // Upload to graphics card every frame
        area.reset();
		VAR varray(vertex, area);
        renderDevice->beginIndexedPrimitives();
    		renderDevice->setVertexArray(varray);
            renderDevice->sendIndices(RenderDevice::TRIANGLES, index);
        renderDevice->endIndexedPrimitives();
	  
See GLG3D_Demo for examples. */ template VAR(const T* sourcePtr, int _numElements, VARAreaRef _area) { init(sourcePtr, _numElements, _area, glFormatOf(T), sizeof(T)); } template VAR(const Array& source, VARAreaRef _area) { init(source.getCArray(), source.size(), _area, glFormatOf(T), sizeof(T)); } template void update(const T* sourcePtr, int _numElements) { update(sourcePtr, _numElements, glFormatOf(T), sizeof(T)); } /** Overwrites existing data with data of the same size or smaller. Convenient for changing part of a G3D::VARArea without reseting the area (and thereby deallocating the other G3D::VAR arrays in it). */ template void update(const Array& source) { update(source.getCArray(), source.size(), glFormatOf(T), sizeof(T)); } /** Overwrites a single element of an existing array without changing the number of elements. This is faster than calling update for large arrays, but slow if many set calls are made. Typically used to change a few key vertices, e.g., the single dark cap point of a directional light's shadow volume. */ template void set(int index, const T& value) { set(index, &value, glFormatOf(T), sizeof(T)); } /** Returns true if this VAR can be used for rendering (i.e. contains data and the parent VARArea has not been reset). */ bool valid() const; /** Maximum size that can be loaded via update into this VAR. */ inline size_t maxSize() const { if (valid()) { return _maxSize; } else { return 0; } } }; } #endif