Sphere::Sphere(glm::vec3 pos, float radius, unsigned int rings, unsigned int sectors)
{
    m_pos = m_centerPos = pos;
    m_radius = radius;
    m_rings = rings;
    m_sectors = sectors;

    CreateBuffers();
    GenerateVertices();
    GenerateIndexes();
    GenerateNormals();
}
/*
=================
idSurface_Patch::SubdivideExplicit
=================
*/
void idSurface_Patch::SubdivideExplicit( int horzSubdivisions, int vertSubdivisions, bool genNormals, bool removeLinear ) {
	int i, j, k, l;
	idDrawVert sample[3][3];
	int outWidth = ((width - 1) / 2 * horzSubdivisions) + 1;
	int outHeight = ((height - 1) / 2 * vertSubdivisions) + 1;
	idDrawVert *dv = new idDrawVert[ outWidth * outHeight ];

	// generate normals for the control mesh
	if ( genNormals ) {
		GenerateNormals();
	}

	int baseCol = 0;
	for ( i = 0; i + 2 < width; i += 2 ) {
		int baseRow = 0;
		for ( j = 0; j + 2 < height; j += 2 ) {
			for ( k = 0; k < 3; k++ ) {
				for ( l = 0; l < 3; l++ ) {
					sample[k][l] = verts[ ((j + l) * width) + i + k ];
				}
			}
			SampleSinglePatch( sample, baseCol, baseRow, outWidth, horzSubdivisions, vertSubdivisions, dv );
			baseRow += vertSubdivisions;
		}
		baseCol += horzSubdivisions;
	}
	verts.SetNum( outWidth * outHeight );
	for ( i = 0; i < outWidth * outHeight; i++ ) {
		verts[i] = dv[i];
	}

	delete[] dv;

	width = maxWidth = outWidth;
	height = maxHeight = outHeight;
	expanded = false;

	if ( removeLinear ) {
		Expand();
		RemoveLinearColumnsRows();
		Collapse();
	}

	// normalize all the lerped normals
	if ( genNormals ) {
		for ( i = 0; i < width * height; i++ ) {
			verts[i].normal.Normalize();
		}
	}

	GenerateIndexes();
}
/*
=================
idSurface_Patch::Subdivide
=================
*/
void idSurface_Patch::Subdivide( float maxHorizontalError, float maxVerticalError, float maxLength, bool genNormals ) {
	int			i, j, k, l;
	idDrawVert	prev, next, mid;
	idVec3		prevxyz, nextxyz, midxyz;
	idVec3		delta;
	float		maxHorizontalErrorSqr, maxVerticalErrorSqr, maxLengthSqr;

	// generate normals for the control mesh
	if ( genNormals ) {
		GenerateNormals();
	}

	maxHorizontalErrorSqr = Square( maxHorizontalError );
	maxVerticalErrorSqr = Square( maxVerticalError );
	maxLengthSqr = Square( maxLength );

	Expand();

	// horizontal subdivisions
	for ( j = 0; j + 2 < width; j += 2 ) {
		// check subdivided midpoints against control points
		for ( i = 0; i < height; i++ ) {
			for ( l = 0; l < 3; l++ ) {
				prevxyz[l] = verts[i*maxWidth + j+1].xyz[l] - verts[i*maxWidth + j  ].xyz[l];
				nextxyz[l] = verts[i*maxWidth + j+2].xyz[l] - verts[i*maxWidth + j+1].xyz[l];
				midxyz[l] = (verts[i*maxWidth + j  ].xyz[l] + verts[i*maxWidth + j+1].xyz[l] * 2.0f +
														   verts[i*maxWidth + j+2].xyz[l] ) * 0.25f;
			}

			if ( maxLength > 0.0f ) {
				// if the span length is too long, force a subdivision
				if ( prevxyz.LengthSqr() > maxLengthSqr || nextxyz.LengthSqr() > maxLengthSqr ) {
					break;
				}
			}
			// see if this midpoint is off far enough to subdivide
			delta = verts[i*maxWidth + j+1].xyz - midxyz;
			if ( delta.LengthSqr() > maxHorizontalErrorSqr ) {
				break;
			}
		}

		if ( i == height ) {
			continue;	// didn't need subdivision
		}

		if ( width + 2 >= maxWidth ) {
			ResizeExpanded( maxHeight, maxWidth + 4 );
		}

		// insert two columns and replace the peak
		width += 2;

		for ( i = 0; i < height; i++ ) {
			idSurface_Patch::LerpVert( verts[i*maxWidth + j  ], verts[i*maxWidth + j+1], prev );
			idSurface_Patch::LerpVert( verts[i*maxWidth + j+1], verts[i*maxWidth + j+2], next );
			idSurface_Patch::LerpVert( prev, next, mid );

			for ( k = width - 1; k > j + 3; k-- ) {
				verts[i*maxWidth + k] = verts[i*maxWidth + k-2];
			}
			verts[i*maxWidth + j+1] = prev;
			verts[i*maxWidth + j+2] = mid;
			verts[i*maxWidth + j+3] = next;
		}

		// back up and recheck this set again, it may need more subdivision
		j -= 2;
	}

	// vertical subdivisions
	for ( j = 0; j + 2 < height; j += 2 ) {
		// check subdivided midpoints against control points
		for ( i = 0; i < width; i++ ) {
			for ( l = 0; l < 3; l++ ) {
				prevxyz[l] = verts[(j+1)*maxWidth + i].xyz[l] - verts[j*maxWidth + i].xyz[l];
				nextxyz[l] = verts[(j+2)*maxWidth + i].xyz[l] - verts[(j+1)*maxWidth + i].xyz[l];
				midxyz[l] = (verts[j*maxWidth + i].xyz[l] + verts[(j+1)*maxWidth + i].xyz[l] * 2.0f +
														verts[(j+2)*maxWidth + i].xyz[l] ) * 0.25f;
			}

			if ( maxLength > 0.0f ) {
				// if the span length is too long, force a subdivision
				if ( prevxyz.LengthSqr() > maxLengthSqr || nextxyz.LengthSqr() > maxLengthSqr ) {
					break;
				}
			}
			// see if this midpoint is off far enough to subdivide
			delta = verts[(j+1)*maxWidth + i].xyz - midxyz;
			if ( delta.LengthSqr() > maxVerticalErrorSqr ) {
				break;
			}
		}

		if ( i == width ) {
			continue;	// didn't need subdivision
		}

		if ( height + 2 >= maxHeight ) {
			ResizeExpanded( maxHeight + 4, maxWidth );
		}

		// insert two columns and replace the peak
		height += 2;

		for ( i = 0; i < width; i++ ) {
			LerpVert( verts[j*maxWidth + i], verts[(j+1)*maxWidth + i], prev );
			LerpVert( verts[(j+1)*maxWidth + i], verts[(j+2)*maxWidth + i], next );
			LerpVert( prev, next, mid );

			for ( k = height - 1; k > j + 3; k-- ) {
				verts[k*maxWidth + i] = verts[(k-2)*maxWidth + i];
			}
			verts[(j+1)*maxWidth + i] = prev;
			verts[(j+2)*maxWidth + i] = mid;
			verts[(j+3)*maxWidth + i] = next;
		}

		// back up and recheck this set again, it may need more subdivision
		j -= 2;
	}

	PutOnCurve();

	RemoveLinearColumnsRows();

	Collapse();

	// normalize all the lerped normals
	if ( genNormals ) {
		for ( i = 0; i < width * height; i++ ) {
			verts[i].normal.Normalize();
		}
	}

	GenerateIndexes();
}