#pragma once
#define BRCHSPNUM 1000
#define DEFAUTLUR 10
#define DEFAULTDR 10
#define DEFAULTH 15
#define DEFAULTA 5
#define PI 3.1415926
#define MAX(x,y) (x>y)?x:y 
#define MINFLOORS 4
#define MINPERCIRCLE 6
#include "math.h"
#include <iostream>
#include <fstream>
#define PARSESAMPLE
/*this class generating meta shapes*/
/**MetaModel generator:
Function: Create a meta model on demand, write to vertex buffer and index buffer
Parameters(LBranch):
@upperRadius: the radius of the upper hemisphere
@downRadius : the radius of the downside hemisphere
@height     : the height of the cylinder body (two hemispheres radiuses are not included)
@area		: the maximum lattice size .This parameter controls the sample rate. The smaller the denser the sampling

Parameters(LLeaves)(LLeave is a rectangle):
@length		: the length of the leaf
@width		: the width of the leaf
@gridV		: how many grids in verticle direction	(1 by default)
@gridH		: how many grids in horizontal direction (1 by default)

Parameters(In common)
@startindex : the start index of the index buffer, 0 by default.
@vertexBuffer: the vertexBuffer passed in, each vertex occupied eight floats, 3(position)+3(normals)+2(uv)
@indexBuffer: the index Buffer passed in. The model space is a left hand system, triangles are anti-clockwise

****************************************************************************************
Usage:
a simple example is provided:

MetaModels meta = MetaModels(LBranch);		\\instantiate an instance
meta.setUDHA(2,3,5,0.5);					\\set upperRadius=2,downRadius=3,height=5,area=0.5
meta.setStartIndex(1);
BFSize  size = meta.getDataSize(LBranch);	\\obtain memory size needed, help with allocating memory

float *vbuffer = (float *)malloc(size.vBuffer);
float *ibuffer = (float *)malloc(size.iBuffer);
meta.bindBuffers(vbuffer,ibuffer);			\\bind the buffers to meta
meta.genModels();							\\generate the model
meta.saveAsObj();							\\save as .obj file for checking

*****************************************************************************************

another example to create a leave:
MetaModels meta = MetaModels(LLeaves);
meta.setLenWidth(4,3);						\\set length=4, width=3
meta.setGrid(4,3);							\\set gridH=4, gridV=3
BFSize  size = meta.getDataSize(LLeaves);

float *vbuffer = (float *)malloc(size.vBuffer);
float *ibuffer = (float *)malloc(size.iBuffer);
meta.bindBuffers(vbuffer,ibuffer);			\\bind the buffers to meta
meta.genModels();							\\generate the model
meta.saveAsObj();							\\save as .obj file for checking



**/

/*
Nov.24 2018, close the function of dense sampling on the cylinder body.
To resume, close the macro PARSESAMPLE
*/


enum LShapes
{
	LBranch = 0,
	LLeaves = 1,
};

typedef struct BFSize
{
	int vBuffer;
	int iBuffer;
}BSize;

class MetaModels
{
public:
	MetaModels();
	MetaModels(LShapes model);
	MetaModels(LShapes model, float *vertexbuffer, unsigned int *indexBuffer, unsigned int startindex);
	
	BSize getDataSize(LShapes model);

	//bind buffers
	void bindBuffers(float *vbuffer, unsigned int *ibuffer);

	//parameters settings
	void setUpperRadius(float r);
	void setDownRadius(float r);
	void setHeight(float h);
	void setUDHA(float ur, float dr, float h, float a);
	void setTriArea(float tarea);
	void setStartIndex(unsigned int start);

	//parameters about leaves
	void setLength(float l);
	void setWidth(float w);
	void setLenWidth(float l, float w);
	void setGrid(unsigned int h, unsigned int v);

	//generating the model
	void genModels();

	//dummy method for testing
	void saveAsObj();

	~MetaModels();

private:
	LShapes m;
	float *vertexBuffer;
	unsigned int	*indexBuffer;
	float upperRadius, downRadius, height;
	float maxTriArea;
	float length, width;
	unsigned int gridH, gridV;
	unsigned int startindex;
};

