-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007-2010 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
#include "batch.h"
#include "bindable.h"
#include "buffer.h"
+#include "error.h"
#include "extension.h"
#include "nv_primitive_restart.h"
#include "vertexarray.h"
void Batch::set_data_type(DataType t)
{
if(t!=UNSIGNED_BYTE && t!=UNSIGNED_SHORT && t!=UNSIGNED_INT)
- throw InvalidParameterValue("Batch data type must be an unsigned integer");
+ throw invalid_argument("Batch::set_data_type");
if(t==UNSIGNED_BYTE && max_index>0xFE)
- throw InvalidState("UNSIGNED_BYTE can't hold all indices in Batch");
+ throw invalid_operation("Batch::set_data_type");
else if(t==UNSIGNED_SHORT && max_index>0xFFFE)
- throw InvalidState("UNSIGNED_SHORT can't hold all indices in Batch");
+ throw invalid_operation("Batch::set_data_type");
if(data_type==UNSIGNED_BYTE && t==UNSIGNED_SHORT)
expand_data<unsigned char, unsigned short>();
void Batch::use_index_buffer(Buffer *buf, Batch *prev)
{
if(buf && prev && prev->ibuf!=buf)
- throw InvalidParameterValue("Previous batch is not in the same buffer");
+ throw invalid_argument("Batch::use_index_buffer");
if(!buf)
{
void Batch::append(const vector<unsigned> &ind)
{
- data.reserve(data.size()+ind.size()*get_index_size());
+ if(ind.empty())
+ return;
+
+ if(data.empty())
+ min_index = max_index = ind.front();
+
for(vector<unsigned>::const_iterator i=ind.begin(); i!=ind.end(); ++i)
- append(*i);
+ {
+ min_index = min(min_index, *i);
+ max_index = max(max_index, *i);
+ }
+
+ if((data_type==UNSIGNED_BYTE || data_type==UNSIGNED_SHORT) && max_index>0xFFFE)
+ set_data_type(UNSIGNED_INT);
+ else if(data_type==UNSIGNED_BYTE && max_index>0xFE)
+ set_data_type(UNSIGNED_SHORT);
+
+ unsigned base = data.size();
+ data.resize(data.size()+ind.size()*get_index_size());
+ if(data_type==UNSIGNED_SHORT)
+ {
+ unsigned short *ptr = reinterpret_cast<unsigned short *>(&data[base]);
+ for(unsigned i=0; i<ind.size(); ++i)
+ ptr[i] = ind[i];
+ }
+ else if(data_type==UNSIGNED_INT)
+ {
+ unsigned *ptr = reinterpret_cast<unsigned *>(&data[base]);
+ for(unsigned i=0; i<ind.size(); ++i)
+ ptr[i] = ind[i];
+ }
+ else
+ {
+ for(unsigned i=0; i<ind.size(); ++i)
+ data[base+i] = ind[i];
+ }
}
void Batch::append(const Batch &other)
{
if(other.prim_type!=prim_type)
- throw InvalidParameterValue("Can't concatenate batches with different primitive types");
+ throw invalid_argument("Batch::append");
if(prim_type==LINE_STRIP || prim_type==LINE_LOOP)
- throw InvalidState("Can't concatenate line strips or loops");
+ throw incompatible_data("Batch::append");
else if(prim_type==POLYGON)
- throw InvalidState("Can't concatenate polygons");
+ throw incompatible_data("Batch::append");
else if(prim_type==TRIANGLE_FAN)
static RequireExtension _ext("GL_NV_primitive_restart");
BufferAlias<ELEMENT_ARRAY_BUFFER> alias(*ibuf);
Bind bind_ibuf(alias, true);
- glDrawRangeElements(prim_type, min_index, max_index, size(), data_type, (void *)ibuf_offset);
+ glDrawRangeElements(prim_type, min_index, max_index, size(), data_type, reinterpret_cast<void *>(ibuf_offset));
}
else
glDrawRangeElements(prim_type, min_index, max_index, size(), data_type, &data[0]);