#include "Mesh.h"

//=======================================================================
//=======================================================================

void Mesh::loadLW5( )
{
	int chunklen,chunkname,subchunkname,subchunklen;
	int i,number,vtable[256];
	Vector3 p;
	float r;
	Color color,spec;
	UINT8 *chunks, *chunkend,*subchunkend,*vertexPointer = NULL;

	chunks = m_readptr;

	m_boundingBoxMin.set(FLT_MAX,FLT_MAX,FLT_MAX);
	m_boundingBoxMax.set(-FLT_MAX,-FLT_MAX,-FLT_MAX);
	m_boundingRadius = 0.0f;

// read file and find out surface,vertex and polygon counts
	m_nextchunkptr = chunks;
	while(m_nextchunkptr < m_fileend)
	{
		m_readptr = m_nextchunkptr;
		chunkname = readID4();
		chunklen = readU4();
		chunkend = m_readptr + chunklen;
		m_nextchunkptr = chunkend;
		if( chunklen & 1 ) m_nextchunkptr++;	//if size is odd, add 1 padding

		switch(chunkname)
		{
		case 'PNTS':
			vertexPointer = m_readptr;
			m_vertices.resize( chunklen / 12 );
			for(i=0;i<m_vertices.size();i++)
			{
				p = readVEC12();
				m_vertices[i].m_position = p;
				m_vertices[i].m_normal.set(0,0,0);
				m_vertices[i].m_triangleUsing = -1;
				if( p.x > m_boundingBoxMax.x ) m_boundingBoxMax.x = p.x;
				if( p.x < m_boundingBoxMin.x ) m_boundingBoxMin.x = p.x;
				if( p.y > m_boundingBoxMax.y ) m_boundingBoxMax.y = p.y;
				if( p.y < m_boundingBoxMin.y ) m_boundingBoxMin.y = p.y;
				if( p.z > m_boundingBoxMax.z ) m_boundingBoxMax.z = p.z;
				if( p.z < m_boundingBoxMin.z ) m_boundingBoxMin.z = p.z;

				r = dot(p, p);
				if(r > m_boundingRadius) m_boundingRadius = r;
			}
			break;
		case 'SRFS':
			while(m_readptr < chunkend)
			{
				static Surface s;
				s.m_name = readS0();
				s.m_polygons = 0;
				m_surfaces.push_back( s );
			}
			break;
		default:
			break;
		}
	}

	m_nextchunkptr = chunks;
	while(m_nextchunkptr < m_fileend)
	{
		m_readptr = m_nextchunkptr;
		chunkname = readID4();
		chunklen = readU4();
		chunkend = m_readptr + chunklen;
		m_nextchunkptr = chunkend;
		if( chunklen & 1 ) m_nextchunkptr++;	//if size is odd, add 1 padding

		switch(chunkname)
		{
		case 'POLS':
			while(m_readptr < chunkend)
			{
				int vert = readU2();
				if(vert >= 3)
				{
					for(i=0;i<vert;i++)
					{
						vtable[i] = readU2();
					}
				}
				else
				{
					m_readptr += 2*vert;
				}

				int surf = readI2();
				if(vert >= 3)
				{
					static Triangle t;
					static Vector3 n,e1,e2;
					t.m_surface = SS::abs(surf) - 1;
					SS_ASSERT( t.m_surface < m_surfaces.size() );
					m_surfaces[t.m_surface].m_polygons += vert-2;
					t.m_n[0] = -1;
					t.m_n[1] = -1;
					t.m_n[2] = -1;

					e1 = m_vertices[vtable[1]].m_position;
					e1 -= m_vertices[vtable[0]].m_position;
					e2 = m_vertices[vtable[vert-1]].m_position;
					e2 -= m_vertices[vtable[0]].m_position;
					n = cross(e1,e2);
					n.normalize();

					for(i=0;i<vert-2;i++)
					{
						t.m_v[0] = vtable[0];
						t.m_v[1] = vtable[i+1];
						t.m_v[2] = vtable[i+2];
						t.m_normal = n;
						
						m_vertices[t.m_v[0]].m_triangleUsing = (m_triangles.size()<<2)|0;
						m_vertices[t.m_v[1]].m_triangleUsing = (m_triangles.size()<<2)|1;
						m_vertices[t.m_v[2]].m_triangleUsing = (m_triangles.size()<<2)|2;

						e1 = m_vertices[t.m_v[1]].m_position;
						e1 -= m_vertices[t.m_v[0]].m_position;
						e2 = m_vertices[t.m_v[2]].m_position;
						e2 -= m_vertices[t.m_v[0]].m_position;
						e1 = cross(e1,e2);
						t.m_area = 0.5f * e1.length();
						m_triangles.push_back( t );
					}
					for(i=0;i<vert;i++)
					{
						m_vertices[vtable[i]].m_normal += n;
					}
				}

				if(surf < 0)	//surface number, if <0 detail polygons follow
				{
					for(i=0;i<readU2();i++) //number of detail polygons
					{
						m_readptr += 2 * readU2(); //number of vertices
					}
				}
			}
			break;
		case 'SURF':
			for(number=0;number<m_surfaces.size();number++)
			{
				if(!strcmp((char *)m_readptr,m_surfaces[number].m_name.c_str())) goto foundName;
			}
			SS_ASSERT(0);		//surface not found
			break;
foundName:
			readS0();

			m_nextsubchunkptr = m_readptr;
			while(m_nextsubchunkptr < chunkend)
			{
				m_readptr = m_nextsubchunkptr;
				subchunkname = readID4();
				subchunklen = readU2();
				subchunkend = m_readptr + subchunklen;
				m_nextsubchunkptr = subchunkend;
				if( subchunklen & 1 ) m_nextsubchunkptr++;	//if size is odd, add 1 padding

				switch(subchunkname)
				{
				case 'COLR':
					m_surfaces[number].m_color.r = readU1();
					m_surfaces[number].m_color.g = readU1();
					m_surfaces[number].m_color.b = readU1();
					m_surfaces[number].m_color.a = 255;
					break;
				}
			}
			break;
		default:
			break;
		}
	}

	m_boundingRadius = float(sqrt( m_boundingRadius ));
	static Vector3 up(0,1,0);
	for(i=0;i<m_vertices.size();i++)
	{
		m_vertices[i].m_normal.normalize();
		m_vertices[i].m_t1 = cross(up, m_vertices[i].m_normal);
		m_vertices[i].m_t2 = cross(m_vertices[i].m_normal, m_vertices[i].m_t1);
    if( (float)SS::fabs(dot(up, m_vertices[i].m_normal)) > 0.999f ) m_vertices[i].m_reliable = false;
		else m_vertices[i].m_reliable = true;
	}
}

//=======================================================================
//=======================================================================
