示例#1
0
void CDX10Renderer::DrawEllipse(const TVector2& _rv2Position, const float _kfWidth, const float _kfHeight)
{
	m_pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP);

	//fill vertex buffer with vertices
	TVertex* pVerts = 0;

	// Set vertex buffer
	UINT stride = sizeof( TVertex );
	UINT offset = 0;
	m_pDevice->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

	m_pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**) &pVerts);

	const int kiCirclePoints = 32;
	for(int i = 0; i < kiCirclePoints; ++i)
	{
		float fAngle = (2.0f * 3.14159265359f / static_cast<float>(kiCirclePoints)) * i;
		
		pVerts[i] = TVertex(TVector3(_rv2Position.x + _kfWidth * 0.5f * cos(fAngle), _rv2Position.y + _kfHeight * 0.5f * sin(fAngle), 0), m_uiPenColour);
	}

	pVerts[kiCirclePoints] = TVertex(TVector3(pVerts[0].x, pVerts[0].y, 0), m_uiPenColour);

	m_pVertexBuffer->Unmap();
	m_pDevice->Draw(kiCirclePoints + 1, 0);
}
示例#2
0
void CDX10Renderer::DrawEllipseFill(const TVector2& _rv2Position, const float _kfWidth, const float _kfHeight, const bool _kHasBorder)
{
	m_pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

	//fill vertex buffer with vertices
	TVertex* pVerts = 0;

	// Set vertex buffer
	UINT stride = sizeof( TVertex );
	UINT offset = 0;
	m_pDevice->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

	m_pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**) &pVerts);

	const int kiCirclePoints = 20;
	const int kiMaxInc = kiCirclePoints * 3;

	for(int i = 0; i < kiMaxInc; i += 3)
	{
		float fAngleA = (2.0f * 3.14159265359f / static_cast<float>(kiCirclePoints)) * i;
		float fAngleB = (2.0f * 3.14159265359f / static_cast<float>(kiCirclePoints)) * (i + 1);
		
		pVerts[i] = TVertex(TVector3(_rv2Position.x + _kfWidth * 0.5f * cos(fAngleA), _rv2Position.y + _kfHeight * 0.5f * sin(fAngleA), 0), m_uiBrushColour);
		pVerts[i + 1] = TVertex(TVector3(_rv2Position.x + _kfWidth * 0.5f * cos(fAngleB), _rv2Position.y + _kfHeight * 0.5f * sin(fAngleB), 0), m_uiBrushColour);
		pVerts[i + 2] = TVertex(TVector3(_rv2Position.x, _rv2Position.y, 0), m_uiBrushColour);
	}

	m_pVertexBuffer->Unmap();
	m_pDevice->Draw(kiMaxInc, 0);

	if(_kHasBorder)
		DrawEllipse(_rv2Position, _kfWidth, _kfHeight);
}
示例#3
0
void NodeControl::drawBody(GlInterface &gl)
{
	drawBackground(gl);

	//Draw connectors underneath selection outline
	drawChildren(gl);

	if(selected)
	{
		Color col = (isInFocus() ? Color(0.3f, 1.0f, 0.3f, 1.0f) : Color(0.1f, 0.75f, 0.75f, 1.0f));

		std::vector<TVertex> points;
		points.reserve(5);

		points.push_back(TVertex(APoint(0, 0), col));
		points.push_back(TVertex(APoint(0, size.y), col));
		points.push_back(TVertex(size, col));
		points.push_back(TVertex(APoint(size.x, 0), col));
		points.push_back(TVertex(APoint(0, 0), col));

		gl.drawShape(GL_LINE_STRIP, points);
	}

	//TODO: rest of body design (title, description, colors, etc)
}
示例#4
0
int Load3ds::CompileObjects()
{
#ifdef GRAPHICS_DEBUG
	FILE* file = NULL;
	file = fopen("normals.out", "w+");
	assert( file );
#endif

	int j = 0;
	TVector3<float> position, normal;
	TVector2<float> texCoord;

	// the number of faces * 3: 3 indices per face
	for (int i = 0; i < mModelData->mFaceCount * 3; i+=3)
	{
		mMesh->addTriangleIndices(mModelData->mFaces[ i ], 
			mModelData->mFaces[i + 1], mModelData->mFaces[i + 2]);
	}

	// set up all the information: position, normal and eventually
	// the texture coordinates, and compile them into our TVertex class
	for (int i = 0; i < mModelData->mVertexCount; i++)
	{
		j = i * 3;

		position.setX( mModelData->mVertices[ j ] );
		position.setY( mModelData->mVertices[j + 1] );
		position.setZ( mModelData->mVertices[j + 2] );

		normal.setX( mModelData->mNormals[ j ] );
		normal.setY( mModelData->mNormals[j + 1] );
		normal.setZ( mModelData->mNormals[j + 2] );

#ifdef GRAPHICS_DEBUG
		fprintf(file, "%i: X: %f, Y: %f, Z: %f\n", i, normal.x(), normal.y(), 
			normal.z());
#endif

		if ( mModelData->mContainsTexCoords )
		{
			// stride: one face -> 2 texture coordinates
			j = i * 2;

			texCoord.setX( mModelData->mTexCoords[ j ] );
			texCoord.setY( mModelData->mTexCoords[j + 1] );
		}

		mMesh->addVertex( TVertex(normal, position, texCoord) );
	}

#ifdef GRAPHICS_DEBUG
	fclose( file );
#endif

	return 1;
}
示例#5
0
void CDX10Renderer::DrawRectangleFill(const TRect& _krRect, const bool _kHasBorder)
{
	m_pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

	//fill vertex buffer with vertices
	TVertex* pVerts = 0;

	// Set vertex buffer
	UINT stride = sizeof( TVertex );
	UINT offset = 0;
	m_pDevice->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

	m_pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**) &pVerts);

	pVerts[0] = TVertex(TVector3(_krRect.x1, _krRect.y2, 0), m_uiBrushColour);
	pVerts[1] = TVertex(TVector3(_krRect.x1, _krRect.y1, 0), m_uiBrushColour);
	pVerts[2] = TVertex(TVector3(_krRect.x2, _krRect.y2, 0), m_uiBrushColour);
	pVerts[3] = TVertex(TVector3(_krRect.x1, _krRect.y1, 0), m_uiBrushColour);
	pVerts[4] = TVertex(TVector3(_krRect.x2, _krRect.y1, 0), m_uiBrushColour);
	pVerts[5] = TVertex(TVector3(_krRect.x2, _krRect.y2, 0), m_uiBrushColour);

	m_pVertexBuffer->Unmap();
	m_pDevice->Draw(6, 0);

	if(_kHasBorder)
		DrawRectangle(_krRect);
}
示例#6
0
void CDX10Renderer::DrawRectangleFill(const TVector2& _rv2Position, const float _kfWidth, const float _kfHeight, const bool _kHasBorder)
{
	m_pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

	//fill vertex buffer with vertices
	TVertex* pVerts = 0;

	// Set vertex buffer
	UINT stride = sizeof( TVertex );
	UINT offset = 0;
	m_pDevice->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

	m_pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**) &pVerts);

	pVerts[0] = TVertex(TVector3(_rv2Position.x - _kfWidth * 0.5f, _rv2Position.y + _kfHeight * 0.5f, 0), m_uiBrushColour);
	pVerts[1] = TVertex(TVector3(_rv2Position.x - _kfWidth * 0.5f, _rv2Position.y - _kfHeight * 0.5f, 0), m_uiBrushColour);
	pVerts[2] = TVertex(TVector3(_rv2Position.x + _kfWidth * 0.5f, _rv2Position.y + _kfHeight * 0.5f, 0), m_uiBrushColour);
	pVerts[3] = TVertex(TVector3(_rv2Position.x - _kfWidth * 0.5f, _rv2Position.y - _kfHeight * 0.5f, 0), m_uiBrushColour);
	pVerts[4] = TVertex(TVector3(_rv2Position.x + _kfWidth * 0.5f, _rv2Position.y + _kfHeight * 0.5f, 0), m_uiBrushColour);
	pVerts[5] = TVertex(TVector3(_rv2Position.x + _kfWidth * 0.5f, _rv2Position.y - _kfHeight * 0.5f, 0), m_uiBrushColour);

	m_pVertexBuffer->Unmap();
	m_pDevice->Draw(6, 0);

	if(_kHasBorder)
		DrawRectangle(_rv2Position, _kfWidth, _kfHeight);
}
示例#7
0
void NodeGraphDisplay::draw(GlInterface &gl)
{
	if(visible && isolateViewport(gl))
	{
		//Draw background
		drawBackground(gl);
		//Draw graph behind nodes
		drawGraph(gl);

		//Draw nodes
		drawChildren(gl);

		transformGl(gl);

		//Draw selection rect
		if(selectionRect.space != TSpace::INVALID)
		{
			std::vector<TVertex> points;
			points.reserve(5);

			Color col(0.0f, 1.0f, 1.0f, 1.0f);

			APoint	p1 = selectionRect.pos,
					p2 = p1 + selectionRect.size;

			points.push_back(TVertex(p1, col));
			points.push_back(TVertex(APoint(p1.x, p2.y), col));
			points.push_back(TVertex(p2, col));
			points.push_back(TVertex(APoint(p2.x, p1.y), col));
			points.push_back(TVertex(p1, col));

			//Draw rect
			gl.drawShape(GL_LINE_STRIP, points);
		}

		untransformGl(gl);
		restoreViewport(gl);
	}
}
示例#8
0
void NodeGraphDisplay::drawGraph(GlInterface &gl)
{
	AVec	graph_step = virtualToAbsoluteVec(BASE_GRAPH_STEP),
			inv_graph_step = AVec(1.0f/graph_step.x, 1.0f/graph_step.y),
			dist_to_origin = virtualToAbsolutePoint(APoint(0, 0)),
			dist_after_origin = size - dist_to_origin;
	
	APoint	first_offset = APoint(fmod(dist_to_origin.x, graph_step.x), fmod(dist_to_origin.y, graph_step.y)),
			last_offset = APoint(fmod(dist_after_origin.x, graph_step.x), fmod(dist_after_origin.y, graph_step.y));
	Point2i lines_before_origin = Point2i(floor(dist_to_origin.x*inv_graph_step.x), floor(dist_to_origin.y*inv_graph_step.y)),
			lines_after_origin = Point2i(floor(dist_after_origin.x*inv_graph_step.x), floor(dist_after_origin.y*inv_graph_step.y)),
			num_lines = lines_before_origin + Vec2i(1, 1) + lines_after_origin;

	std::vector<TVertex> points;
	points.reserve(2*(num_lines.x + num_lines.y));

	//Add vertical lines
	int i = 0;
	for(float x = first_offset.x; x < size.x; x += graph_step.x, i++)
	{
		Color c = (i != lines_before_origin.x ? Color(0.0f, 0.0f, 0.0f, 1.0f) : Color(1.0f, 0.0f, 0.0f, 1.0f));
		points.push_back(TVertex(APoint(x, 0.0f), c));
		points.push_back(TVertex(APoint(x, size.y), c));
	}

	//Add horizontal lines
	i = 0;
	for(float y = first_offset.y; y < size.y; y += graph_step.y, i++)
	{
		Color c = (i != lines_before_origin.y ? Color(0.0f, 0.0f, 0.0f, 1.0f) : Color(1.0f, 0.0f, 0.0f, 1.0f));
		points.push_back(TVertex(APoint(0.0f, y), c));
		points.push_back(TVertex(APoint(size.x, y), c));
	}

	//Draw lines
	gl.drawShape(GL_LINES, points);
}
示例#9
0
void CDX10Renderer::DrawPolygon(TVector2* _pPoints, int _iPoints)
{
	m_pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP);

	//fill vertex buffer with vertices
	TVertex* pVerts = 0;

	// Set vertex buffer
	UINT stride = sizeof( TVertex );
	UINT offset = 0;
	m_pDevice->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

	m_pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**) &pVerts);

	for(int i = 0; i < _iPoints; ++i)
	{
		pVerts[i] = TVertex(TVector3(_pPoints[i].x, _pPoints[i].y, 0), m_uiPenColour);
	}

	pVerts[_iPoints] = TVertex(TVector3(_pPoints[0].x, _pPoints[0].y, 0), m_uiPenColour);

	m_pVertexBuffer->Unmap();
	m_pDevice->Draw(_iPoints + 1, 0);
}
示例#10
0
void NodeConnectionControl::draw(GlInterface &gl)
{
	if(visible)
	{
		if(fromNode)
			pFrom = fromNode->getConnectorPoint(fromNc->ioType);
		if(toNode)
			pTo = toNode->getConnectorPoint(toNc->ioType);
		adjustPos();

		const float	length = (pTo - pFrom).length(),
					angle = atan2(pTo.y - pFrom.y, pTo.x - pFrom.x),
					cos_a = cos(angle),
					sin_a = sin(angle);

		APoint start = pFrom;
		AVec step = AVec(cos_a, sin_a);
		AVec perp = AVec(sin_a, -cos_a);

		step.normalize();
		perp.normalize();

		//Multiply color channels by background color
		Color	color_mult = bgStateColors[cState],
				inactive_col(inactiveColor.r*color_mult.r, inactiveColor.g*color_mult.g, inactiveColor.b*color_mult.b, inactiveColor.a*color_mult.a),
				base_col(baseColor.r*color_mult.r, baseColor.g*color_mult.g, baseColor.b*color_mult.b, baseColor.a*color_mult.a),
				arrow_col(arrowColor.r*color_mult.r, arrowColor.g*color_mult.g, arrowColor.b*color_mult.b, arrowColor.a*color_mult.a);

		std::vector<TVertex> points;
		//points.reserve(2*ceil((length - ARROW_LENGTH)/spacing)*(length > ARROW_LENGTH));
		Color col;
		
		/*
		for(float r = 0.0f; r < length - ARROW_LENGTH; r += spacing, even = !even)
		{
			APoint p = start + step*r;
			float	omega_t = SIN_OMEGA*PHYSICS_CLOCK.t,
					phi = SIN_K*r*0.05f,

					height1 = amplitude*(sin(omega_t + phi) + 0.5f)*(sin(omega_t + phi*0.25f) + 1.0f)*0.5f,	//height of sin wave
					offset = width*0.0*amplitude*cos(omega_t*1.0 + phi*0.5f),
					tilt = 0.0f*amplitude*cos(omega_t + phi*0.2),

					even_mult = even ? lerp(1.0f, 0.5f, height) : 1.0f;

			//TODO: Make it look more like its rotating
			//		Maybe have a separate height for each line endpoint with different phases?

			height1 *= even_mult;

			col = lerp(inactive_col, base_col, height1);


			AVec	height_vec1 = perp*lerp(width, (width + radius)*height, amplitude),
					height_vec2 = perp*lerp(width
					tilt_vec = step*tilt,
					offset_vec = perp*offset;

			points.push_back(TVertex(p - height_vec - tilt_vec + offset_vec, col));
			points.push_back(TVertex(p + height_vec + tilt_vec + offset_vec, col));
		}
		*/

		//Add rotating line vertices
		for(float r = 0.0f; r < length - ARROW_LENGTH; r += spacing)
		{
			APoint p = start + step*r;
			float	omega_t = SIN_OMEGA*Clock::getGlobalTime(),
					phi = -SIN_K*r,

					height = amplitude*sin(omega_t + phi),	//height of sin wave
					offset = 0.0f,//amplitude*cos(omega_t*0.5f + phi*0.05f),
					tilt = 2.0f*amplitude*cos(-omega_t + phi);

			//TODO: Make it look more like its rotating

			col = lerp(inactive_col, base_col, -abs(height)*(1.0f + 2.0f*std::max(0.0f, 8.0f*amplitude*(cos(-omega_t*2.0f + phi*0.01f) - 0.9f))));
			//col = lerp(col, Color(0.5f, 0.5f, 0.0f, 1.0f), std::max(0.0f, amplitude*sin(omega_t*40.0f + phi*3.0f)));

			AVec	height_vec = perp*(width + radius*height),
					tilt_vec = step*tilt,
					offset_vec = perp*offset;

			points.push_back(TVertex(p - height_vec - tilt_vec + offset_vec, col));
			points.push_back(TVertex(p + height_vec + tilt_vec + offset_vec, col));
		}


		//Draw lines
		gl.drawShape(GL_LINES, points);
		points.clear();

		col = lerp(inactive_col, arrow_col, amplitude);
		
		//Add arrow point vertices
		points.push_back(TVertex(start + step*(length - ARROW_LENGTH) - perp*width*1.5f, col));
		points.push_back(TVertex(start + step*(length - ARROW_LENGTH) + perp*width*1.5f, col));
		points.push_back(TVertex(start + step*length, col));

		//Draw arrow
		gl.drawShape(GL_TRIANGLES, points);
	}
}
示例#11
0
void MidiDisplay::drawData(GlInterface &gl)
{
	//(Up here for now to minimize flickering)
	s_time cursor_time = (cursor ? cursor->getSampleRange().start : 0);

	//Get view origin/size in absolute space
	APoint	av_pos = gl.viewToAbsolutePoint(APoint(0, 0));
	AVec	av_size = gl.viewToAbsoluteVec(gl.getCurrView().size);

				//Samples per pixel
	const float a_spp = samplesPerPixel,
				a_pps = 1.0f/a_spp,
				v_spp = gl.absoluteToViewVec(AVec(samplesPerPixel, 0)).x,
				v_pps = 1.0f/v_spp,

				//Chunks per pixel
				a_cpp = a_spp*AUDIO_CHUNK_SIZE,
				a_ppc = a_pps*AUDIO_CHUNK_SIZE,
				v_cpp = v_spp*AUDIO_CHUNK_SIZE,
				v_ppc = v_pps*AUDIO_CHUNK_SIZE,

				//Seconds per pixel
				a_secpp = secondsPerPixel,
				a_ppsec = 1.0f/a_secpp,
				v_secpp = gl.absoluteToViewVec(AVec(secondsPerPixel, 0)).x,
				v_ppsec = 1.0f/v_secpp,

				note_mult = 1.0f/NUM_MIDI_NOTES;	//Normalizes MidiIndex between 0 and 1

	//Left-most point, starting from bottom
	APoint origin(0, size.y);

	//Position adjustment values
	double	t_offset = (double)(av_pos.x*a_secpp),
			t_length = (double)(av_size.x*a_secpp),
			end_t = t_offset + t_length;

	//std::cout << t_offset << "\n";

	TimeRange r(t_offset, end_t);

	//Get intersecting notes
	ConstMidiData midi = midiData->getConstNotes(r);
	

	s_time	sample_offset = (s_time)(av_pos.x*a_spp), 
			num_samples = (s_time)ceil(av_size.x*a_spp),
			first_chunk_so = sample_offset % AUDIO_CHUNK_SIZE,
			last_chunk_so = (first_chunk_so + num_samples) % AUDIO_CHUNK_SIZE,
			total_samples = first_chunk_so + num_samples + last_chunk_so;



	////DRAW////

	std::vector<TVertex> points;
	points.reserve(2*midi.size());
	Color col(0.0f, 0.0f, 0.0f, 1.0f);

	for(auto n : midi)
	{
		float	height = origin.y - origin.y*((float)n->index*note_mult),
				x1 = (float)n->range.start*a_ppsec,
				//x2 = (float)(n->isFinished() ? n->end : (float)cursor_time/TEMP_SAMPLERATE)*a_ppsec;
				x2 = (float)n->range.end*a_ppsec;

		points.push_back(TVertex(APoint(x1, height), col));
		points.push_back(TVertex(APoint(x2, height), col));
	}
	gl.drawShape(GL_LINES, points);

	points.clear();
	col = Color(1.0f, 1.0f, 0.0f, 1.0f);

	//Draw stoppers
	/*
	for(auto n : midi)
	{
		float height = origin.y - origin.y*((float)n->index*note_mult);
		for(auto st : n->stoppers)
		{
			float x = (float)(n->range.start + st.offset)*a_ppsec;
			points.push_back(TVertex(APoint(x, height), col));
		}
	}
	gl.drawShape(GL_POINTS, points);
	*/

	//Draw chunk lines
	if(DRAW_CHUNK_LINES)
	{
		//Convert seconds to chunks
		c_time num_chunks = (c_time)ceil((float)total_samples/(float)AUDIO_CHUNK_SIZE);

		points.clear();
		points.reserve(2*num_chunks);
		col = Color(0.4f, 0.4f, 0.9f, 0.3f);

		float x = av_pos.x + (AUDIO_CHUNK_SIZE - first_chunk_so)*a_pps;

		for(c_time c = 0; c < num_chunks; c++, x += a_ppc)
		{
			points.push_back(TVertex(APoint(x, 0.0f), col));
			points.push_back(TVertex(APoint(x, size.y), col));
		}

		gl.drawShape(GL_LINES, points);
		points.clear();
	}
	
	//Draw cursor
	if(cursor)
	{
		float x = (float)cursor_time/TEMP_SAMPLERATE*a_ppsec;
		
		gl.setColor(0.8f, 0.8f, 0.1f);
		gl.drawLine(APoint(x, 0.0f), APoint(x, size.y));
	}

	//TEST
	//gl.setColor(1.0f, 0.0f, 0.0f);
	//gl.drawLine(APoint(end_t*v_ppsec, 0), APoint(end_t*v_ppsec, size.y));
}
示例#12
0
void AudioDisplay::drawData(GlInterface &gl)
{
	//(Up here for now to minimize flickering)
	s_time cursor_time = (cursor ? cursor->getSampleRange().start : 0);
	c_time num_data_chunks = audioData->size();

	//Get view origin/size in absolute space
	APoint	av_pos = gl.viewToAbsolutePoint(APoint(0, 0));
	AVec	v_size = gl.getCurrView().size,
			av_size = gl.viewToAbsoluteVec(v_size);

	const float
				//Basic multipliers
				sample_mult = 1.0f/AUDIO_MAX_AMPLITUDE,	//Multiplier to transform an AudioSample to a 0.0 to 1.0 scale
				chunk_mult = 1.0f/AUDIO_CHUNK_SIZE,		//Multiplier to convert samples to chunks
				a_to_v = gl.absoluteToViewVec(AVec(1.0, 0.0f)).x,	//Converts absolute sizes to view sizes
				v_to_a = 1.0f/a_to_v,
			
				//Samples per physical pixel in absolute and view spaces
				//TODO: Figure out whether this should be in absolute or view space
				a_spp = samplesPerPixel,
				a_pps = 1.0f/a_spp,
				v_spp = gl.absoluteToViewVec(AVec(samplesPerPixel, 0)).x,
				v_pps = a_to_v*a_pps,//1.0f/v_spp,

				//Chunks per pixel
				a_cpp = a_spp*chunk_mult,
				a_ppc = (float)AUDIO_CHUNK_SIZE*a_pps,
				v_cpp = v_spp*chunk_mult,
				v_ppc = (float)AUDIO_CHUNK_SIZE*v_pps;
			

	//Left-most point, centered vertically (VIRTUAL SPACE)
	APoint origin(0, size.y/2.0f);

	//Sample values
	s_time	sample_offset = (s_time)(av_pos.x*a_spp), 
			num_samples = (s_time)ceil(av_size.x*a_spp),
			first_chunk_so = sample_offset % AUDIO_CHUNK_SIZE,
			last_chunk_so = AUDIO_CHUNK_SIZE - (first_chunk_so + num_samples) % AUDIO_CHUNK_SIZE,
			total_samples = first_chunk_so + num_samples + last_chunk_so;

	//Chunk values
	c_time	start_chunk = (c_time)(sample_offset*chunk_mult),
			num_chunks = (c_time)ceil(total_samples*chunk_mult),
			last_chunk = start_chunk + num_chunks;

	//Check for errors
	if (sample_offset < 0 || start_chunk >= num_data_chunks || num_chunks <= 0)
	{
		std::cout << "ERROR --> \n";

		if(sample_offset < 0)
			std::cout << "\t\tSAMPLE_OFFSET LESS THAN 0\n";
		if (start_chunk >= num_data_chunks)
			std::cout << "\t\tSTART_CHUNK_TOO_BIG\n";
		if(num_chunks <= 0)
			std::cout << "\t\tNUM_CHUNKS <= 0\n";

		std::cout << "\tSAMPLE_OFFSET:  " << sample_offset << "\n";
		std::cout << "\tSTART_CHUNK:    " << start_chunk << "\n";
		std::cout << "\tNUM CHUNKS:     " << num_chunks << "\n";

		return;
	}
	
	if(start_chunk + num_chunks > num_data_chunks)
		num_chunks = num_data_chunks - start_chunk;
	
	//Get chunk sizes to sample (one sample per on-screen pixel)
	float	desired_chunk_size = v_pps*(float)AUDIO_CHUNK_SIZE;
	s_time	actual_chunk_size = (s_time)ceil(desired_chunk_size);
	float	actual_to_desired = desired_chunk_size/(float)actual_chunk_size;		//Converts sampled chunk to desired chunk
	

	const AudioChunk** pData = (const AudioChunk**)((*audioData).data() + start_chunk);
	
	//Number of pixels up until start_chunk
	float start_px = start_chunk*a_ppc;

	//Allocate space for sampled chunks
	AudioChunk	**s_data = new AudioChunk*[num_chunks];
	for(c_time i = 0; i < num_chunks; i++)
		s_data[i] = new AudioChunk(actual_chunk_size);

	//Sample chunks
	AStatus status = sampleChunks(pData, s_data, num_chunks, SampleMethod::AVERAGE, false);

	if(!statusGood(status))
	{
		std::cout << "AUDIO DISPLAY -->\n" << status << "\n";
		return;
	}

	////DRAW////
	std::vector<TVertex> points;
	Color col;

	//Draw status highlights
	if(drawStatuses)
	{
		for(c_time c = 0; c < num_chunks; c++)
		{
			//Set status color
			switch(pData[c]->getStatus())
			{
			case DataStatus::CLEAN:
				gl.setColor(0.5f, 0.65f, 0.55f);
				break;
			case DataStatus::DIRTY:
				gl.setColor(0.65f, 0.5f, 0.5f);
				break;
			default:
				//Unknown status
				gl.setColor(1.0f, 0.0f, 1.0f);
			}

			//Draw current chain
			gl.drawRect(APoint((start_chunk + c)*a_ppc, 0.0f), AVec(a_ppc, size.y));
		}

		/*
		DataStatus curr_status = pData[0]->getStatus();
		ChunkRange c_r(-1, -1);

		for(c_time c = 0; c < num_chunks; c++)
		{
			c_time d_c = start_chunk + c;
			DataStatus d_status = pData[c]->getStatus();
			bool continue_chain = (d_status == curr_status);

			if(continue_chain || c + 1 == num_chunks)
			{
				//Continue chain
				c_r.start = (c_r.start < 0 ? d_c : c_r.start);
				c_r.end = d_c + 1;
			}

			if(!continue_chain || c + 1 == num_chunks)
			{
				//Set status color
				switch(curr_status)//aData[d_c]->status)
				{
				case DataStatus::CLEAN:
					gl.setColor(0.5f, 0.65f, 0.55f);
					break;
				case DataStatus::DIRTY:
					gl.setColor(0.65f, 0.5f, 0.5f);
					break;
				default:
					//Unknown status
					gl.setColor(1.0f, 0.0f, 1.0f);
				}

				//Draw current chain
				gl.drawRect(APoint(c_r.start*a_ppc, 0.0f), AVec(c_r.length()*a_ppc, size.y));

				//Start new chain
				c_r.start = d_c;
				c_r.end = d_c + 1;
				curr_status = d_status;
			}
		}
		*/
	}
	
	//Draw center line
	gl.setColor(0.2f, 0.2f, 0.2f, 1.0f);
	gl.drawLine(APoint(start_px, origin.y), APoint(start_px + total_samples*a_pps, origin.y));
	
	//TEST: Draw every data point (to compare approximation with)
	if(Keyboard::keyDown(Keys::K_Q))
	{
		points.clear();
		points.reserve(num_samples);
		col = Color(1.0f, 0.0f, 0.0f, 1.0f);

		const c_time	c_start = (flipChunks ? (num_chunks - 1) : 0),
						c_step = (flipChunks ? -1 : 1);
		const s_time	s_start = (flipChunkSamples ? (AUDIO_CHUNK_SIZE - 1) : 0),
						s_step = (flipChunkSamples ? -1 : 1);

		for(c_time c = c_start; (!flipChunks && c < num_chunks) || (flipChunks && c >= 0); c += c_step)
		{
			const AudioSample *c_data = pData[c]->getData();

			for(s_time s = s_start; (!flipChunkSamples && s < AUDIO_CHUNK_SIZE) || (flipChunkSamples && s >= 0); s += s_step)
			{
				//Calculate number of samples from the start (adjusting for flipped data or chunks)
				s_time s_x = (flipChunks ? (num_chunks - 1 - c) : c)*AUDIO_CHUNK_SIZE
								+ (flipChunkSamples ? (AUDIO_CHUNK_SIZE - 1 - s) : s);

				APoint p(start_px + s_x*a_pps, origin.y - origin.y*(float)c_data[s]*sample_mult);
				points.push_back(TVertex(p, col));
			}
		}
		gl.drawShape(GL_LINE_STRIP, points);
	}


	//Draw lines connecting samples (with approximate, sampled data)
	points.clear();
	points.reserve(num_chunks*desired_chunk_size);
	col = Color(0.0f, 0.0f, 0.0f, 1.0f);

	const c_time	c_start = (flipChunks ? (num_chunks - 1) : 0),
					c_step = (flipChunks ? -1 : 1);
	const s_time	s_start = (flipChunkSamples ? (actual_chunk_size - 1) : 0),
					s_step = (flipChunkSamples ? -1 : 1);

	for(c_time c = c_start; (!flipChunks && c < num_chunks) || (flipChunks && c >= 0); c += c_step)
	{
		const AudioSample *c_data = s_data[c]->getData();

		for(s_time s = s_start; (!flipChunkSamples && s < actual_chunk_size) || (flipChunkSamples && s >= 0); s += s_step)
		{
			const s_time s_x = (flipChunks ? (num_chunks - 1 - c) : c)*actual_chunk_size
								+ (flipChunkSamples ? (actual_chunk_size - 1 - s) : s);

			APoint p(start_px + s_x*actual_to_desired*v_to_a, origin.y - origin.y*(float)c_data[s]*sample_mult);
			points.push_back(TVertex(p, col));
		}
	}
	gl.drawShape(GL_LINE_STRIP, points);

	/*
	glBegin(GL_LINE_STRIP);
		glColor3f(0.0f, 0.0f, 0.0f);
		
		s_time sample = 0;
		for(c_time c = 0; c < num_chunks; c++)
		{
			std::vector<AudioSample>	&c_data = s_data[c]->data;

			for(s_time s = first_chunk_po*(c == 0); s < actual_chunk_size && sample < num_samples; s++, sample++)
			{
				GlPoint gl_pos = toGlPoint(APoint((float)sample*chunk_ratio, origin.y*(1.0f - (float)c_data[s]*sample_mult)), vv_size);
				
				glVertex2f(gl_pos.x, gl_pos.y);
			}
		}
	glEnd();
	*/

	/*
	//Draw lines connecting samples (as squares)
	glBegin(GL_QUADS);
		glColor3f(0.0f, 0.0f, 0.0f);
		
		s_time sample = 0;
		for(c_time c = 0; c < num_chunks; c++)
		{
			std::vector<AudioSample>	&c_data_max = s_max[c]->data,
										&c_data_min = s_min[c]->data;

			for(s_time s = first_chunk_po*(c == 0); s < actual_chunk_size && sample < num_pixels; s++, sample++)
			{
				float p_x = (float)sample*chunk_ratio;

				GlPoint gl_pos_max = toGlPoint(APoint(p_x - 0.5f, origin.y*(1.0f - (float)c_data_max[s]*sample_mult)), vv_size),
						gl_pos_min = toGlPoint(APoint(p_x + 0.5f, origin.y*(1.0f - (float)c_data_min[s]*sample_mult)), vv_size);
				
				//Draw vertical bar from max to min -- 1 pixel wide
				glVertex2f(gl_pos_max.x, gl_pos_max.y);
				glVertex2f(gl_pos_max.x, gl_pos_min.y);
				glVertex2f(gl_pos_min.x, gl_pos_max.y);
				glVertex2f(gl_pos_min.x, gl_pos_min.y);

			}
		}
	glEnd();
	*/
	
	if(DRAW_CHUNK_LINES)
	{
		points.clear();
		points.reserve(2*num_chunks);
		col = Color(0.4f, 0.4f, 0.9f, 0.3f);

		float x = av_pos.x + (AUDIO_CHUNK_SIZE - first_chunk_so)*a_pps;
		
		for(c_time c = 0; c < num_chunks; c++, x += a_ppc)
		{
			if(pData[c]->NOTE_ON)
			{
				gl.setColor(Color(1.0f, 0.0f, 0.0f, 0.5f));
				gl.drawRect(APoint(x - AUDIO_CHUNK_SIZE*a_pps, 0.0f), AVec(AUDIO_CHUNK_SIZE*a_pps, size.y));
			}
			
			col = Color(0.4f, 0.4f, 0.9f, 0.3f);

			points.push_back(TVertex(APoint(x, 0.0f), col));
			points.push_back(TVertex(APoint(x, size.y), col));
		}

		gl.drawShape(GL_LINES, points);
		points.clear();
	}
	

	//Draw cursor
	if(cursor)
	{
		float x = cursor_time*a_pps;
		
		gl.setColor(0.8f, 0.8f, 0.1f);
		gl.drawLine(APoint(x, 0.0f), APoint(x, size.y));
	}
	
	//Release sampled data
	if(s_data)
	{
		for(int i = 0; i < num_chunks; i++)
			delete s_data[i];
		delete[] s_data;
	}

	/*
	if(s_max)
	{
		for(int i = 0; i < num_chunks; i++)
			delete s_max[i];
		delete[] s_max;
	}
	if(s_min)
	{
		for(int i = 0; i < num_chunks; i++)
			delete s_min[i];
		delete[] s_min;
	}
	*/
}