void Screenport::WorldToView( const grinliz::Vector3F& world, grinliz::Vector2F* v ) const
{
	Matrix4 mvp;
	ViewProjection3D( &mvp );

	Vector4F p, r;
	p.Set( world, 1 );
	r = mvp * p;

	Vector2F v0, v1;
	Rectangle2F clipInView;
	Vector2F min = { 0, 0 };
	Vector2F max = { UIWidth(), UIHeight() };
	UIToView( min, &v0 );
	UIToView( max, &v1 );

	clipInView.FromPair( v0.x, v0.y, v1.x, v1.y );
	
	v->x = Interpolate( -1.0f, (float)clipInView.min.x,
						1.0f,  (float)clipInView.max.x,
						r.x/r.w );
	v->y = Interpolate( -1.0f, (float)clipInView.min.y,
						1.0f,  (float)clipInView.max.y,
						r.y/r.w );
}
Exemple #2
0
void DecalMesh::StreamOutMesh( ELightPass light, EPass pass )
{
	if ( pass == BLEND_PASS )
		return;
	GLASSERT( !Stencil() );	// separate render

	L3PERFTRACK

	const Vector3F& eye = Lilith3D::Instance()->GetCamera()->Eye();
	float dx = pos.x - eye.x;
	float dy = pos.y - eye.y;
	float dSquared = dx*dx + dy*dy - (size*size)*0.25f;

	// Stencil pass doesn't need individual state.
	if ( dSquared > OBJECT_FADEOUT_SQUARED )
		return;				// Has faded out. Do not draw.

	const Shader* shader = GetShader();

	if ( shader && light == SHADOW_PASS )
		return;
	if ( !shader ) {
		if ( light == BRIGHT_PASS )
			shader = ShaderManager::Instance()->GetShader( ShaderManager::DIFFUSE_SHADER );
		else if ( light == SHADOW_PASS )
			shader = ShaderManager::Instance()->GetShader( ShaderManager::DIFFUSE_SHADOW_SHADER );
		else
			GLASSERT( 0 );
	}
	GLASSERT( shader );

	float alpha = Alpha();
	if ( dSquared > OBJECT_FADE_SQUARED ) {
		alpha *= Clamp( Interpolate( OBJECT_FADE, 1.0f, OBJECT_FADEOUT, 0.0f, sqrtf( dSquared ) ), 0.0f, 1.0f );
	}
	glColor4f( Color().r, Color().g, Color().b, alpha );

	L3State state;
	state.blend = true;
	state.clamp = true;
	state.lighting = true;
	state.texture = texture;
	state.shader = shader;
	state.depthWrite = false;
	StateManager::Enable( state );

	Rectangle2F bounds;
	bounds.Set( AABB().min.x, AABB().min.y, AABB().max.x, AABB().max.y );

	glMatrixMode(GL_TEXTURE);
	glPushMatrix();
	glLoadMatrixf( texMat.x );
	//glMatrixMode(GL_MODELVIEW);

	Lilith3D::GetTerrainMesh()->RenderDecal( bounds, false );

	//glMatrixMode(GL_TEXTURE);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
}
Exemple #3
0
Rectangle2F MapScene::GridBounds2(int x, int y, bool useGutter)
{
	float gridSize = mapImage2.Width() / float(MAP2_SIZE);
	float gutter = useGutter ? gamui2D.TextHeightVirtual() * 0.25f : 0;

	Rectangle2F r;
	r.Set(mapImage2.X() + float(x)*gridSize + gutter,
		  mapImage2.Y() + float(y)*gridSize + gutter,
		  mapImage2.X() + float(x + 1)*gridSize - gutter,
		  mapImage2.Y() + float(y + 1)*gridSize - gutter);
	return r;
}
void Lilith3D::DrawShadowVolumes()
{
	/*	1. Render the scene, lights on
		2. Render shadow volume faces whose normals are away from the eye (back face).
		   Increment stencil buffer for each point that fails depth test.
		3. Render the shadow volume faces whose normals points towards the eye (front face).
		   Decrement the stencil buffer for each point that fails depth test.
		4. Render the scene in shadow where the stencil is !0.

		Steps 2 and 3 and done by the ShadowVolumeCache
	*/

	// ---- Set up shadow state ----
	L3State state;
	state.depthWrite = false;
	state.lighting = false;
	glColor3f( 1.0f, 1.0f, 1.0f );
	StateManager::Enable( state );

	// Turn off features, only write stencil:
	glShadeModel( GL_FLAT );
	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
	glEnable( GL_STENCIL_TEST );

	GLASSERT( glGetError() == GL_NO_ERROR );
	GLASSERT( shadowVolumeCache.NumIndex() == 0 );

	// Get the sun, and restrict it to a reasonable range.
	const SunMoon& sunMoon = timeClock.GetSunMoon();
	Vector3F sun = sunMoon.vector;

	// How far will a one unit high object cast a shadow? Hard to say,
	// but assume flat ground.
	Rectangle2F shadow;
	shadow.Zero();

	if ( sun.x > 0.0f ) shadow.min.x = -SHADOW_CAST_LENGTH;	//-sun.x / sun.z;	// adds a negative number
	else				shadow.max.x = SHADOW_CAST_LENGTH;	//-sun.x / sun.z;	// adds a positive number

	shadowVolumeCache.SetSun( sun );

	// Cull with extra shadow info (and revert this call before returning)
	//quadTree->DoCullingShadow( shadow, SHADOW_CASTER_MESH );

	// -- shadow CASTERS --
	StreamShadowList( quadTree->GetMeshRoot(), shadow );
	StreamShadowList( quadTree->GetMeshShadowRoot(), shadow );

	GLASSERT( glGetError() == GL_NO_ERROR );
	shadowVolumeCache.StreamToStencil();		// manages vertex state

	//quadTree->DoCulling( true );

	// Tree Decals
	// Sleazy trick. Add the stencils for the tree. If the z-test passes, we know it is
	// on the terrain, and the stencil count is incremented. These aren't proper shadows
	// since they don't change with the sun, but it looks better than stencil projected trees.
	glStencilFunc(GL_ALWAYS, 0, ~0);
	if ( GLEW_EXT_stencil_wrap )
		glStencilOp( GL_KEEP, GL_KEEP, GL_INCR_WRAP_EXT );	// fail, zfail, zpass
	else
		glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );

	DecalMesh::StreamAllStencilDecals( quadTree->GetDecalStencilRoot() );
	StateManager::Enable( state );	// The decal mesh uses an alpha test, so restore the current gl state

	// Now everything on top of the terrain - not currently used. Used to stream
	// decals, but they are handled above.
	// StreamStencilList( quadTree->GetMeshRoot() );
	//GLASSERT( !quadTree->GetMeshRoot() );	// if this fires, turn the stencil code back on.
	
	// Restore normal state. (except still no depth write)
	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	glShadeModel( GL_SMOOTH );
	//quadTree->DoCulling();
}
Exemple #5
0
void MapScene::DrawMap()
{
	CDynArray<Chit*> query;

	const ChitContext* context = lumosChitBag->Context();
	const Web& web = lumosChitBag->GetSim()->CalcWeb();

	Rectangle2I subBounds = MapBounds2();
	float map2X = float(subBounds.min.x) / float(NUM_SECTORS);
	float map2Y = float(subBounds.min.y) / float(NUM_SECTORS);
	RenderAtom subAtom = mapImage.GetRenderAtom();
	subAtom.tx0 = map2X;
	subAtom.ty1 = map2Y;
	subAtom.tx1 = map2X + float(MAP2_SIZE) / float(NUM_SECTORS);
	subAtom.ty0 = map2Y + float(MAP2_SIZE) / float(NUM_SECTORS);
	mapImage2.SetAtom(subAtom);

	for (Rectangle2IIterator it(subBounds); !it.Done(); it.Next()) {
		Vector2I sector = it.Pos();
		const SectorData& sd = worldMap->GetSectorData( sector );

		int i = (sector.x - subBounds.min.x);
		int j = (sector.y - subBounds.min.y);
		int index = j * MAP2_SIZE + i;

		CoreScript* coreScript = CoreScript::GetCore(sector);

		CStr<64> str = "";
		const char* owner = "";
		if (coreScript) {
			if ( coreScript->InUse() ) {
				owner = Team::Instance()->TeamName( coreScript->ParentChit()->Team() ).safe_str();
			}
		}
		str.Format( "%s\n%s", sd.name.safe_str(), owner );

		Rectangle2F r = GridBounds2(i, j, true);
		gridWidget[index].SetPos(r.min.x, r.min.y);
		gridWidget[index].SetSize(r.Width(), r.Height());
		gridWidget[index].Set(context, coreScript, lumosChitBag->GetHomeCore(), &web);
	}

	Vector2I homeSector = lumosChitBag->GetHomeSector();
	if ( !data->destSector.IsZero() && data->destSector != homeSector ) {
		const SectorData& sd = worldMap->GetSectorData( data->destSector );
		CStr<64> str;
		str.Format( "Grid Travel\n%s", sd.name.c_str() );
		gridTravel.SetText(  str.c_str() );
		gridTravel.SetEnabled( true );
	}
	else {
		gridTravel.SetText( "Grid Travel" );
		gridTravel.SetEnabled( false );
	}

	// --- MAIN ---
	Rectangle2I mapBounds = data->worldMap->Bounds();
	Rectangle2I map2Bounds;
	map2Bounds.Set(subBounds.min.x*SECTOR_SIZE, subBounds.min.y*SECTOR_SIZE, 
				   subBounds.max.x*SECTOR_SIZE + SECTOR_SIZE-1, subBounds.max.y*SECTOR_SIZE + SECTOR_SIZE-1);

	Vector2F playerPos = { 0, 0 };
	Chit* player = data->player;
	if ( player ) {
		playerPos = ToWorld2F(player->Position());
	}

	const float dx = mapImage.Width() / float(NUM_SECTORS);
	const float dy = mapImage.Height() / float(NUM_SECTORS);
	for (int j = 0; j < NUM_SECTORS; ++j) {
		for (int i = 0; i < NUM_SECTORS; ++i) {
			diplomacy[j*NUM_SECTORS + i].SetSize(dx, dy);
			diplomacy[j*NUM_SECTORS + i].SetPos(mapImage.X() + dx * float(i), mapImage.Y() + dy * float(j));
		}
	}

	bool inBounds = true;
	Vector2F v;

	for (int i = 0; i < 2; ++i) {
		const Rectangle2I& b = (i == 0) ? mapBounds : map2Bounds;

		v = ToUI(i, playerPos, b, &inBounds);
		playerMark[i].SetCenterPos(v.x, v.y);
		playerMark[i].SetVisible(inBounds);

		Vector2F pos = { float(homeSector.x * SECTOR_SIZE), float(homeSector.y * SECTOR_SIZE) };
		v = ToUI(i,pos, b, &inBounds);
		homeMark[i].SetPos(v.x, v.y);
		homeMark[i].SetVisible(inBounds && !homeSector.IsZero());

		pos.Set(float(data->destSector.x * SECTOR_SIZE), float(data->destSector.y * SECTOR_SIZE));
		v = ToUI(i,pos, b, &inBounds);
//		if (i == 0) {
//			travelMark.SetPos(v.x, v.y);
//			travelMark.SetVisible(inBounds && !data->destSector.IsZero());
//		}
		for (int k = 0; k < MAX_SQUADS; ++k) {
			v = ToUI(i, ToWorld2F(data->squadDest[k]), b, &inBounds);
			squadMark[i][k].SetCenterPos(v.x, v.y);
			squadMark[i][k].SetVisible(!data->squadDest[k].IsZero() && inBounds);
		}
	}
	{
		Vector2F world = { (float)map2Bounds.min.x, (float)map2Bounds.min.y };
		Vector2F pos = ToUI(0, world, mapBounds, 0);
		selectionMark.SetPos(pos.x, pos.y);
	}

	float scale = float(mapImage.Width()) / float(NUM_SECTORS);
	{
		webCanvas.Clear();

		for (int i = 1; i < web.NumNodes(); i++) {
			const MinSpanTree::Node& node = web.NodeAt(i);
			Vector2I s0 = node.parentPos;
			Vector2I s1 = node.pos;
			Vector2F p0 = { (float(s0.x) + 0.5f) * scale, (float(s0.y) + 0.5f) * scale };
			Vector2F p1 = { (float(s1.x) + 0.5f) * scale, (float(s1.y) + 0.5f) * scale };
			webCanvas.DrawLine(p0.x, p0.y, p1.x, p1.y, 1.0f + node.strength * 2.0f);
		}
	}

	CoreScript* homeCore = context->chitBag->GetHomeCore();
	CChitArray citizens;
	if (homeCore) {
		homeCore->Citizens(&citizens);
	}
	for (int i = 0; i < MAX_CITIZENS; ++i) {
		if (i < citizens.Size()) {
			Vector2F cPos = ToWorld2F(citizens[i]->Position());
			Vector2F pos = ToUI(0, cPos, mapBounds, 0);
			unitMarker[i].SetSize(8, 8);
			unitMarker[i].SetCenterPos(pos.x, pos.y);
			unitMarker[i].SetVisible(true);
		}
		else {
			unitMarker[i].SetVisible(false);
		}
	}

	for (int j = 0; j < NUM_SECTORS; ++j) {
		for (int i = 0; i < NUM_SECTORS; ++i) {
			diplomacy[i].SetAtom(RenderAtom());

			Vector2I sector = { i, j };
			CoreScript* core = CoreScript::GetCore(sector);
			RenderAtom atom;

			if (core && homeCore && homeCore->InUse() && core->InUse()) {
				ERelate relate = Team::Instance()->GetRelationship(core->ParentChit(), homeCore->ParentChit());
				if (relate == ERelate::FRIEND) atom = LumosGame::CalcUIIconAtom("friend");
				else if (relate == ERelate::NEUTRAL) atom = LumosGame::CalcUIIconAtom("neutral");
				else if (relate == ERelate::ENEMY) atom = LumosGame::CalcUIIconAtom("enemy");
				
				diplomacy[j*NUM_SECTORS + i].SetSize(scale*0.8f, scale*0.8f);
			}

			if (core && core->InUse() && Team::IsDeity(core->ParentChit()->Team())) {
				atom = LumosGame::CalcDeityAtom(core->ParentChit()->Team());
				diplomacy[j*NUM_SECTORS + i].SetSize(scale, scale);
			}

			diplomacy[j*NUM_SECTORS + i].SetAtom(atom);
			diplomacy[j*NUM_SECTORS + i].SetCenterPos(mapImage.X() + scale * (float(i) + 0.5f), mapImage.Y() + scale * (float(j) + 0.5f));
		}
	}
}
Exemple #6
0
void DecalMesh::StreamAllStencilDecals( Mesh* list )
{
	L3PERFTRACK

	// Sort everything to a vector, where it can be sorted. Then
	// sort on the texture since that is the only state that changes.
	unsigned count = 0;

	for( ; list; list = list->nextRender ) {
		GLASSERT( list->Type() == DECALMESH );
		renderVec[count] = (DecalMesh*) list;
		++count;
		GLASSERT( count < MAX_DECAL_STENCIL );	// start throwing away decals...
		if ( count == MAX_DECAL_STENCIL )
			break;
	}

	if ( count == 0 )
		return;

	std::sort( &renderVec[0], &renderVec[count], DecalMeshTexture() );
	const Texture* texture = renderVec[0]->DecalTexture();

	L3State state;
	state.lighting = false;
	state.alphaTest = 0.5f;
	state.texture = texture;
	state.clamp = true;
	state.depthWrite = false;
	StateManager::Enable( state );

	const Vector3F& eye = Lilith3D::Instance()->GetCamera()->Eye();

	glMatrixMode(GL_TEXTURE);
	glPushMatrix();
	bool suppress = false;

	for( unsigned i=0; i<count; ++i )
	{
		DecalMesh* decal = renderVec[i];

		float dx = decal->pos.x - eye.x;
		float dy = decal->pos.y - eye.y;
		float dSquared = dx*dx + dy*dy - (decal->size*decal->size)*0.25f;

		if ( dSquared > SHADOW_END_FADE_SQUARED ) {
			continue;
		}
		if ( decal->DecalTexture() != texture ) {
			state.texture = renderVec[i]->DecalTexture();
			StateManager::Enable( state );
		}

		Rectangle2F bounds;
		bounds.Set( decal->AABB().min.x, decal->AABB().min.y, decal->AABB().max.x, decal->AABB().max.y );

		glLoadMatrixf( decal->texMat.x );
		Lilith3D::GetTerrainMesh()->RenderDecal( bounds, suppress );
		suppress = true;
	}
	glMatrixMode(GL_TEXTURE);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
}