//create a vertex buffer for efficiently rendering cubes
LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage)
{
	LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage);

	ret->allocateBuffer(8, 64, true);

	LLStrider<LLVector3> pos;
	LLStrider<U16> idx;

	ret->getVertexStrider(pos);
	ret->getIndexStrider(idx);

	pos[0] = LLVector3(-1,-1,-1);
	pos[1] = LLVector3(-1,-1, 1);
	pos[2] = LLVector3(-1, 1,-1);
	pos[3] = LLVector3(-1, 1, 1);
	pos[4] = LLVector3( 1,-1,-1);
	pos[5] = LLVector3( 1,-1, 1);
	pos[6] = LLVector3( 1, 1,-1);
	pos[7] = LLVector3( 1, 1, 1);

	for (U32 i = 0; i < 64; i++)
	{
		idx[i] = sOcclusionIndices[i];
	}

	ret->flush();

	return ret;
}
Example #2
0
void create_vertex_buffers_from_model(LLModel* model, std::vector<LLPointer <LLVertexBuffer> >& vertex_buffers)
{
#if 0 //VECTORIZE THIS ?
	vertex_buffers.clear();
	
	for (S32 i = 0; i < model->getNumVolumeFaces(); ++i)
	{
		const LLVolumeFace &vf = model->getVolumeFace(i);
		U32 num_vertices = vf.mNumVertices;
		U32 num_indices = vf.mNumIndices;

		if (!num_vertices || ! num_indices)
		{
			continue;
		}

		LLVertexBuffer* vb =
			new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0, 0);
		
		vb->allocateBuffer(num_vertices, num_indices, TRUE);

		LLStrider<LLVector3> vertex_strider;
		LLStrider<LLVector3> normal_strider;
		LLStrider<LLVector2> tc_strider;
		LLStrider<U16> index_strider;

		vb->getVertexStrider(vertex_strider);
		vb->getNormalStrider(normal_strider);
		vb->getTexCoord0Strider(tc_strider);

		vb->getIndexStrider(index_strider);

		// build vertices and normals
		for (U32 i = 0; (S32)i < num_vertices; i++)
		{
			*(vertex_strider++) = vf.mVertices[i].mPosition;
			*(tc_strider++) = vf.mVertices[i].mTexCoord;
			LLVector3 normal = vf.mVertices[i].mNormal;
			normal.normalize();
			*(normal_strider++) = normal;
		}

		// build indices
		for (U32 i = 0; i < num_indices; i++)
		{
			*(index_strider++) = vf.mIndices[i];
		}


		vertex_buffers.push_back(vb);
	}
#endif
}
Example #3
0
BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
{
	LLFastTimer ftm(FTM_GEO_SKY);
	LLStrider<LLVector3>	vertices;
	LLStrider<LLVector2>	texCoords;
	LLStrider<U16>			indices;

#if DOME_SLICES
	{
		mFanVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
		mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE);

		BOOL success = mFanVerts->getVertexStrider(vertices)
			&& mFanVerts->getTexCoord0Strider(texCoords)
			&& mFanVerts->getIndexStrider(indices);

		if(!success) 
		{
			llerrs << "Failed updating WindLight sky geometry." << llendl;
		}

		buildFanBuffer(vertices, texCoords, indices);

		mFanVerts->flush();
	}

	{
		const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024;
		const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK;
		const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcVertexSize(data_mask);

		const U32 total_stacks = getNumStacks();

		const U32 verts_per_stack = getNumSlices();

		// each seg has to have one more row of verts than it has stacks
		// then round down
		const U32 stacks_per_seg = (max_verts - verts_per_stack) / verts_per_stack;

		// round up to a whole number of segments
		const U32 strips_segments = (total_stacks+stacks_per_seg-1) / stacks_per_seg;

		llinfos << "WL Skydome strips in " << strips_segments << " batches." << llendl;

		mStripsVerts.resize(strips_segments, NULL);

		LLTimer timer;
		timer.start();

		for (U32 i = 0; i < strips_segments ;++i)
		{
			LLVertexBuffer * segment = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
			mStripsVerts[i] = segment;

			U32 num_stacks_this_seg = stacks_per_seg;
			if ((i == strips_segments - 1) && (total_stacks % stacks_per_seg) != 0)
			{
				// for the last buffer only allocate what we'll use
				num_stacks_this_seg = total_stacks % stacks_per_seg;
			}

			// figure out what range of the sky we're filling
			const U32 begin_stack = i * stacks_per_seg;
			const U32 end_stack = begin_stack + num_stacks_this_seg;
			llassert(end_stack <= total_stacks);

			const U32 num_verts_this_seg = verts_per_stack * (num_stacks_this_seg+1);
			llassert(num_verts_this_seg <= max_verts);

			const U32 num_indices_this_seg = 1+num_stacks_this_seg*(2+2*verts_per_stack);
			llassert(num_indices_this_seg * sizeof(U16) <= max_buffer_bytes);

			segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE);

			// lock the buffer
			BOOL success = segment->getVertexStrider(vertices)
				&& segment->getTexCoord0Strider(texCoords)
				&& segment->getIndexStrider(indices);

			if(!success) 
			{
				llerrs << "Failed updating WindLight sky geometry." << llendl;
			}

			// fill it
			buildStripsBuffer(begin_stack, end_stack,  vertices, texCoords, indices);

			// and unlock the buffer
			segment->flush();
		}
	
		llinfos << "completed in " << llformat("%.2f", timer.getElapsedTimeF32()) << "seconds" << llendl;
	}
#else
	mStripsVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
	
	const F32 RADIUS = LLWLParamManager::sParamMgr->getDomeRadius();

	LLPointer<LLVertexBuffer> temp = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
	temp->allocateBuffer(12, 60, TRUE);

	BOOL success = temp->getVertexStrider(vertices)
		&& temp->getIndexStrider(indices);

	if (success)
	{
		for (U32 i = 0; i < 12; i++)
		{
			*vertices++ = icosahedron_vert[i];
		}

		for (U32 i = 0; i < 60; i++)
		{
			*indices++ = icosahedron_ind[i];
		}
	}


	LLPointer<LLVertexBuffer> temp2;
	
	for (U32 i = 0; i < 8; i++)
	{
		temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
		subdivide(*temp, temp2);
		temp = temp2;
	}
	
	temp->getVertexStrider(vertices);
	for (S32 i = 0; i < temp->getNumVerts(); i++)
	{
		LLVector3 v = vertices[i];
		v.normVec();
		vertices[i] = v*RADIUS;
	}

	temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
	chop(*temp, temp2);

	mStripsVerts->allocateBuffer(temp2->getNumVerts(), temp2->getNumIndices(), TRUE);
	
	success = mStripsVerts->getVertexStrider(vertices)
		&& mStripsVerts->getTexCoordStrider(texCoords)
		&& mStripsVerts->getIndexStrider(indices);

	LLStrider<LLVector3> v;
	temp2->getVertexStrider(v);
	LLStrider<U16> ind;
	temp2->getIndexStrider(ind);

	if (success)
	{
		for (S32 i = 0; i < temp2->getNumVerts(); ++i)
		{
			LLVector3 vert = *v++;
			vert.normVec();
			F32 z0 = vert.mV[2];
			F32 x0 = vert.mV[0];
			
			vert *= RADIUS;
			
			*vertices++ = vert;
			*texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f);
		}

		for (S32 i = 0; i < temp2->getNumIndices(); ++i)
		{
			*indices++ = *ind++;
		}
	}

	mStripsVerts->flush();
#endif

	updateStarColors();
	updateStarGeometry(drawable);

	LLPipeline::sCompiles++;

	return TRUE;
}
Example #4
0
BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER);
	LLFace *face;

	if (drawable->getNumFaces() < 1)
	{
		LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
		drawable->addFace(poolp, NULL);
	}
	face = drawable->getFace(0);

//	LLVector2 uvs[4];
//	LLVector3 vtx[4];

	LLStrider<LLVector3> verticesp, normalsp;
	LLStrider<LLVector2> texCoordsp;
	LLStrider<U16> indicesp;
	U16 index_offset;


	// A quad is 4 vertices and 6 indices (making 2 triangles)
	static const unsigned int vertices_per_quad = 4;
	static const unsigned int indices_per_quad = 6;

	static const LLCachedControl<bool> render_transparent_water("RenderTransparentWater",false);
	const S32 size = (render_transparent_water && !LLGLSLShader::sNoFixedFunction) ? 16 : 1;
	const S32 num_quads = size * size;
	face->setSize(vertices_per_quad * num_quads,
				  indices_per_quad * num_quads);
	
	LLVertexBuffer* buff = face->getVertexBuffer();
	if (!buff)
	{
		buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
		buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
		face->setIndicesIndex(0);
		face->setGeomIndex(0);
		face->setVertexBuffer(buff);
	}
	else
	{
		buff->resizeBuffer(face->getGeomCount(), face->getIndicesCount());
	}
		
	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
		
	LLVector3 position_agent;
	position_agent = getPositionAgent();
	face->mCenterAgent = position_agent;
	face->mCenterLocal = position_agent;

	S32 x, y;
	F32 step_x = getScale().mV[0] / size;
	F32 step_y = getScale().mV[1] / size;

	const LLVector3 up(0.f, step_y * 0.5f, 0.f);
	const LLVector3 right(step_x * 0.5f, 0.f, 0.f);
	const LLVector3 normal(0.f, 0.f, 1.f);

	F32 size_inv = 1.f / size;

	for (y = 0; y < size; y++)
	{
		for (x = 0; x < size; x++)
		{
			S32 toffset = index_offset + 4*(y*size + x);
			position_agent = getPositionAgent() - getScale() * 0.5f;
			position_agent.mV[VX] += (x + 0.5f) * step_x;
			position_agent.mV[VY] += (y + 0.5f) * step_y;

			*verticesp++  = position_agent - right + up;
			*verticesp++  = position_agent - right - up;
			*verticesp++  = position_agent + right + up;
			*verticesp++  = position_agent + right - up;

			*texCoordsp++ = LLVector2(x*size_inv, (y+1)*size_inv);
			*texCoordsp++ = LLVector2(x*size_inv, y*size_inv);
			*texCoordsp++ = LLVector2((x+1)*size_inv, (y+1)*size_inv);
			*texCoordsp++ = LLVector2((x+1)*size_inv, y*size_inv);
			
			*normalsp++   = normal;
			*normalsp++   = normal;
			*normalsp++   = normal;
			*normalsp++   = normal;

			*indicesp++ = toffset + 0;
			*indicesp++ = toffset + 1;
			*indicesp++ = toffset + 2;

			*indicesp++ = toffset + 1;
			*indicesp++ = toffset + 3;
			*indicesp++ = toffset + 2;
		}
	}
	
	buff->flush();

	mDrawable->movePartition();
	LLPipeline::sCompiles++;
	return TRUE;
}
Example #5
0
void LLSprite::updateFace(LLFace &face)
{
	LLViewerCamera &camera = *LLViewerCamera::getInstance();

	// First, figure out how many vertices/indices we need.
	U32 num_vertices, num_indices;
	U32 vertex_count = 0;
	
	// Get the total number of vertices and indices
	if (mFollow)
	{
		num_vertices = 4;
		num_indices = 6;
	}
	else
	{
		num_vertices = 4;
		num_indices = 12;
	}

	face.setSize(num_vertices, num_indices);
	
	if (mFollow) 
	{
		sCameraUp = camera.getUpAxis();
		sCameraRight = -camera.getLeftAxis();
		sCameraPosition = camera.getOrigin();
		sNormal = -camera.getAtAxis();
		if (mUseCameraUp)
		{
			// these need to live here because the height/width may change between render calls
			mScaledUp = sCameraUp;
			mScaledRight = sCameraRight;

			mScaledUp *= mHeightDiv2;
			mScaledRight *= mWidthDiv2;

			mA = mPosition + mScaledRight + mScaledUp;
			mB = mPosition - mScaledRight + mScaledUp;
			mC = mPosition - mScaledRight - mScaledUp;
			mD = mPosition + mScaledRight - mScaledUp;
		}
		else
		{
			// The up vector is perpendicular to the camera vector...
			LLVector3 camera_vec = mPosition - sCameraPosition;
			mScaledRight = camera_vec % LLVector3(0.f, 0.f, 1.f);
			mScaledUp = -(camera_vec % mScaledRight);
			mScaledUp.normalize();
			mScaledRight.normalize();
			mScaledUp *= mHeightDiv2;
			mScaledRight *= mWidthDiv2;

			mA = mPosition + mScaledRight + mScaledUp;
			mB = mPosition - mScaledRight + mScaledUp;
			mC = mPosition - mScaledRight - mScaledUp;
			mD = mPosition + mScaledRight - mScaledUp;
		}
	}
	else
	{
		// this is equivalent to how it was done before. . . 
		// we need to establish a way to 
		// identify the orientation of a particular sprite rather than
		// just banging it in on the x,z plane if it's not following the camera.

		LLVector3 x_axis;
		LLVector3 y_axis;

		F32 dot = sNormal * LLVector3(0.f, 1.f, 0.f);
		if (dot == 1.f || dot == -1.f)
		{
			x_axis.setVec(1.f, 0.f, 0.f);
			y_axis.setVec(0.f, 1.f, 0.f);
		}
		else
		{
			x_axis = sNormal % LLVector3(0.f, -1.f, 0.f);
			x_axis.normalize();

			y_axis = sNormal % x_axis;
		}

		LLQuaternion yaw_rot(mYaw, sNormal);

		// rotate axes by specified yaw
		x_axis = x_axis * yaw_rot;
		y_axis = y_axis * yaw_rot;

		// rescale axes by width and height of sprite
		x_axis = x_axis * mWidthDiv2;
		y_axis = y_axis *  mHeightDiv2;

		mA = -x_axis + y_axis;
		mB = x_axis + y_axis;
		mC = x_axis - y_axis;
		mD = -x_axis - y_axis;

		mA += mPosition;
		mB += mPosition;
		mC += mPosition;
		mD += mPosition;
	}

	face.setFaceColor(mColor);

	LLStrider<LLVector3> verticesp;
	LLStrider<LLVector3> normalsp;
	LLStrider<LLVector2> tex_coordsp;
	LLStrider<U16> indicesp;
	U16 index_offset;

	// Setup face
	if (!face.getVertexBuffer())
	{	
		LLVertexBuffer* buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | 
												LLVertexBuffer::MAP_TEXCOORD0,
												GL_STREAM_DRAW_ARB);
		buff->allocateBuffer(4, 12, TRUE);
		face.setGeomIndex(0);
		face.setIndicesIndex(0);
		face.setVertexBuffer(buff);
	}
		
	index_offset = face.getGeometry(verticesp,normalsp,tex_coordsp, indicesp);

	*tex_coordsp = LLVector2(0.f, 0.f);
	*verticesp = mC;
	tex_coordsp++;
	verticesp++;
	vertex_count++;

	*tex_coordsp = LLVector2(0.f, 1.f);
	*verticesp = mB;
	tex_coordsp++;
	verticesp++;
	vertex_count++;

	*tex_coordsp = LLVector2(1.f, 1.f);
	*verticesp = mA;
	tex_coordsp++;
	verticesp++;
	vertex_count++;

	*tex_coordsp = LLVector2(1.f, 0.0f);
	*verticesp = mD;
	tex_coordsp++;
	verticesp++;
	vertex_count++;

	// Generate indices, since they're easy.
	// Just a series of quads.
	*indicesp++ = index_offset;
	*indicesp++ = 2 + index_offset;
	*indicesp++ = 1 + index_offset;

	*indicesp++ = index_offset;
	*indicesp++ = 3 + index_offset;
	*indicesp++ = 2 + index_offset;

	if (!mFollow)
	{
		*indicesp++ = 0 + index_offset;
		*indicesp++ = 1 + index_offset;
		*indicesp++ = 2 + index_offset;
		*indicesp++ = 0 + index_offset;
		*indicesp++ = 2 + index_offset;
		*indicesp++ = 3 + index_offset;
	}

	face.getVertexBuffer()->setBuffer(0);
	face.mCenterAgent = mPosition;
}
Example #6
0
void LLVOTree::updateMesh()
{
	LLMatrix4 matrix;
	
	// Translate to tree base  HACK - adjustment in Z plants tree underground
	const LLVector3 &pos_agent = getPositionAgent();
	//gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
	LLMatrix4 trans_mat;
	trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
	trans_mat *= matrix;
	
	// Rotate to tree position and bend for current trunk/wind
	// Note that trunk stiffness controls the amount of bend at the trunk as 
	// opposed to the crown of the tree
	// 
	const F32 TRUNK_STIFF = 22.f;
	
	LLQuaternion rot = 
		LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) *
		LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) *
		getRotation();

	LLMatrix4 rot_mat(rot);
	rot_mat *= trans_mat;

	F32 radius = getScale().magVec()*0.05f;
	LLMatrix4 scale_mat;
	scale_mat.mMatrix[0][0] = 
		scale_mat.mMatrix[1][1] =
		scale_mat.mMatrix[2][2] = radius;

	scale_mat *= rot_mat;

//	const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f;
//	const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f;

	F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec());
	
	S32 stop_depth = 0;
	F32 alpha = 1.0;
	

	U32 vert_count = 0;
	U32 index_count = 0;
	
	calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches);

	LLFace* facep = mDrawable->getFace(0);
	LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
	buff->allocateBuffer(vert_count, index_count, TRUE);
	facep->setVertexBuffer(buff);
	
	LLStrider<LLVector3> vertices;
	LLStrider<LLVector3> normals;
	LLStrider<LLVector2> tex_coords;
	LLStrider<U16> indices;
	U16 idx_offset = 0;

	buff->getVertexStrider(vertices);
	buff->getNormalStrider(normals);
	buff->getTexCoord0Strider(tex_coords);
	buff->getIndexStrider(indices);

	genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
	
	mReferenceBuffer->flush();
	buff->flush();
}
BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
{
	LLStrider<LLVector3> verticesp;
	LLStrider<LLVector3> normalsp;
	LLStrider<LLVector2> texCoordsp;
	LLStrider<U16> indicesp;
	S32 index_offset;
	LLFace *face;	

	LLDrawPoolGround *poolp = (LLDrawPoolGround*) gPipeline.getPool(LLDrawPool::POOL_GROUND);

	if (drawable->getNumFaces() < 1)
		drawable->addFace(poolp, NULL);
	face = drawable->getFace(0); 
		
	if (!face->getVertexBuffer())
	{
		face->setSize(5, 12);
		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
		buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
		face->setGeomIndex(0);
		face->setIndicesIndex(0);
		face->setVertexBuffer(buff);
	}
	
	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
	if (-1 == index_offset)
	{
		return TRUE;
	}

	///////////////////////////////////////
	//
	//
	//
	LLVector3 at_dir = LLViewerCamera::getInstance()->getAtAxis();
	at_dir.mV[VZ] = 0.f;
	if (at_dir.normVec() < 0.01)
	{
		// We really don't care, as we're not looking anywhere near the horizon.
	}
	LLVector3 left_dir = LLViewerCamera::getInstance()->getLeftAxis();
	left_dir.mV[VZ] = 0.f;
	left_dir.normVec();

	// Our center top point
	LLColor4 ground_color = gSky.getFogColor();
	ground_color.mV[3] = 1.f;
	face->setFaceColor(ground_color);
	
	*(verticesp++)  = LLVector3(64, 64, 0);
	*(verticesp++)  = LLVector3(-64, 64, 0);
	*(verticesp++)  = LLVector3(-64, -64, 0);
	*(verticesp++)  = LLVector3(64, -64, 0);
	*(verticesp++)  = LLVector3(0, 0, -1024);
	
	
	// Triangles for each side
	*indicesp++ = index_offset + 0;
	*indicesp++ = index_offset + 1;
	*indicesp++ = index_offset + 4;

	*indicesp++ = index_offset + 1;
	*indicesp++ = index_offset + 2;
	*indicesp++ = index_offset + 4;

	*indicesp++ = index_offset + 2;
	*indicesp++ = index_offset + 3;
	*indicesp++ = index_offset + 4;

	*indicesp++ = index_offset + 3;
	*indicesp++ = index_offset + 0;
	*indicesp++ = index_offset + 4;

	*(texCoordsp++) = LLVector2(0.f, 0.f);
	*(texCoordsp++) = LLVector2(1.f, 0.f);
	*(texCoordsp++) = LLVector2(1.f, 1.f);
	*(texCoordsp++) = LLVector2(0.f, 1.f);
	*(texCoordsp++) = LLVector2(0.5f, 0.5f);
	
	face->getVertexBuffer()->flush();
	LLPipeline::sCompiles++;
	return TRUE;
}