Example #1
0
// [BB] Small helper function for MDL_ROLLAGAINSTANGLE.
float gl_RollAgainstAngleHelper ( const AActor *actor )
{
	float angleDiff = ANGLE_TO_FLOAT ( R_PointToAngle ( actor->x, actor->y ) ) - ANGLE_TO_FLOAT ( actor->angle );
	if ( angleDiff > 180 )
		angleDiff -= 360;
	else if ( angleDiff < -180 )
		angleDiff += 360;
	if ( actor->z > viewz )
		angleDiff *= -1;
	if ( ( angleDiff < 90 ) && ( angleDiff > - 90 ) )
		angleDiff *= -1;
	return angleDiff;
}
Example #2
0
	// construct a new ViewShifter, to temporarily shift camera viewpoint
	ViewShifter(EyeView eyeView, player_t * player, FGLRenderer& renderer_param) {
		renderer = &renderer_param;
		saved_viewx = viewx;
		saved_viewy = viewy;

		float xf = FIXED2FLOAT(viewx);
		float yf = FIXED2FLOAT(viewy);
		float yaw = DEG2RAD( ANGLE_TO_FLOAT(viewangle) );

		float eyeShift = vr_ipd / 2.0;
		if (eyeView == EYE_VIEW_LEFT)
			eyeShift = -eyeShift;
		float vh = 41.0;
		if (player != NULL)
			vh = FIXED2FLOAT(player->mo->ViewHeight);
		float mapunits_per_meter = vh/(0.95 * vr_player_height_meters);
		float eyeShift_mapunits = eyeShift * mapunits_per_meter;

		xf += sin(yaw) * eyeShift_mapunits;
		yf -= cos(yaw) * eyeShift_mapunits;
		// Printf("eyeShift_mapunits (ViewShifter) = %.1f\n", eyeShift_mapunits);

		viewx = FLOAT2FIXED(xf);
		viewy = FLOAT2FIXED(yf);
		renderer->SetCameraPos(viewx, viewy, viewz, viewangle);
		renderer->SetViewMatrix(false, false);
	}
Example #3
0
void gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture)
{
	// only manipulate the texture matrix if needed.
	if (secplane->xoffs != 0 || secplane->yoffs != 0 ||
		secplane->xscale != FRACUNIT || secplane->yscale != FRACUNIT ||
		secplane->angle != 0 || 
		gltexture->TextureWidth() != 64 ||
		gltexture->TextureHeight() != 64)
	{
		float uoffs = FIXED2FLOAT(secplane->xoffs) / gltexture->TextureWidth();
		float voffs = FIXED2FLOAT(secplane->yoffs) / gltexture->TextureHeight();

		float xscale1=FIXED2FLOAT(secplane->xscale);
		float yscale1=FIXED2FLOAT(secplane->yscale);
		if (gltexture->tex->bHasCanvas)
		{
			yscale1 = 0 - yscale1;
		}
		float angle=-ANGLE_TO_FLOAT(secplane->angle);

		float xscale2=64.f/gltexture->TextureWidth();
		float yscale2=64.f/gltexture->TextureHeight();

		gl_RenderState.mTextureMatrix.loadIdentity();
		gl_RenderState.mTextureMatrix.scale(xscale1 ,yscale1,1.0f);
		gl_RenderState.mTextureMatrix.translate(uoffs,voffs,0.0f);
		gl_RenderState.mTextureMatrix.scale(xscale2 ,yscale2,1.0f);
		gl_RenderState.mTextureMatrix.rotate(angle,0.0f,0.0f,1.0f);
		gl_RenderState.EnableTextureMatrix(true);
	}
}
Example #4
0
//==========================================================================
//
//
//
//==========================================================================
void ADynamicLight::Activate(AActor *activator)
{
	//Super::Activate(activator);
	flags2&=~MF2_DORMANT;	

	m_currentIntensity = float(m_intensity[0]);
	m_tickCount = 0;

	if (lighttype == PulseLight)
	{
		float pulseTime = ANGLE_TO_FLOAT(this->angle) / TICRATE;
		
		m_lastUpdate = level.maptime;
		m_cycler.SetParams(float(m_intensity[1]), float(m_intensity[0]), pulseTime);
		m_cycler.ShouldCycle(true);
		m_cycler.SetCycleType(CYCLE_Sin);
		m_currentIntensity = (BYTE)m_cycler.GetVal();
	}
}
Example #5
0
//==========================================================================
//
//
//
//==========================================================================
void ADynamicLight::Tick()
{
	if (vid_renderer == 0)
	{
		return;
	}
	if (IsOwned())
	{
		if (!target || !target->state)
		{
			this->Destroy();
			return;
		}
		if (target->flags & MF_UNMORPHED) return;
	}

	// Don't bother if the light won't be shown
	if (!IsActive()) return;

	// I am doing this with a type field so that I can dynamically alter the type of light
	// without having to create or maintain multiple objects.
	switch(lighttype)
	{
	case PulseLight:
	{
		float diff = (level.maptime - m_lastUpdate) / (float)TICRATE;
		
		m_lastUpdate = level.maptime;
		m_cycler.Update(diff);
		m_currentIntensity = m_cycler.GetVal();
		break;
	}

	case FlickerLight:
	{
		BYTE rnd = randLight();
		float pct = ANGLE_TO_FLOAT(angle)/360.f;
		
		m_currentIntensity = float(m_intensity[rnd >= pct * 255]);
		break;
	}

	case RandomFlickerLight:
	{
		int flickerRange = m_intensity[1] - m_intensity[0];
		float amt = randLight() / 255.f;
		
		m_tickCount++;
		
		if (m_tickCount > ANGLE_TO_FLOAT(angle))
		{
			m_currentIntensity = float(m_intensity[0] + (amt * flickerRange));
			m_tickCount = 0;
		}
		break;
	}

#if 0
	// These need some more work elsewhere
	case ColorFlickerLight:
	{
		BYTE rnd = randLight();
		float pct = ANGLE_TO_FLOAT(angle)/360.f;
		
		m_currentIntensity = m_intensity[rnd >= pct * 255];
		break;
	}

	case RandomColorFlickerLight:
	{
		int flickerRange = m_intensity[1] - m_intensity[0];
		float amt = randLight() / 255.f;
		
		m_tickCount++;
		
		if (m_tickCount > ANGLE_TO_FLOAT(angle))
		{
			m_currentIntensity = m_intensity[0] + (amt * flickerRange);
			m_tickCount = 0;
		}
		break;
	}
#endif

	case SectorLight:
	{
		float intensity;
		float scale = args[LIGHT_SCALE] / 8.f;
		
		if (scale == 0.f) scale = 1.f;
		
		intensity = Sector->lightlevel * scale;
		intensity = clamp<float>(intensity, 0.f, 255.f);
		
		m_currentIntensity = intensity;
		break;
	}

	case PointLight:
		m_currentIntensity = float(m_intensity[0]);
		break;
	}

	UpdateLocation();
}
Example #6
0
//==========================================================================
//
//  Calculate sky texture
//
//==========================================================================
void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect)
{
	FPortal *portal = sector->portals[plane];
	if (portal != NULL)
	{
		if (GLPortal::instack[1-plane]) return;
		type=RENDERWALL_SECTORSTACK;
		this->portal = portal;
	}
	else if (sector->GetTexture(plane)==skyflatnum)
	{
		GLSkyInfo skyinfo;
		ASkyViewpoint * skyboxx = sector->GetSkyBox(plane);

		// JUSTHIT is used as an indicator that a skybox is in use.
		// This is to avoid recursion

		if (!gl_noskyboxes && skyboxx && GLRenderer->mViewActor!=skyboxx && !(skyboxx->flags&MF_JUSTHIT))
		{
			type=RENDERWALL_SKYBOX;
			skybox=skyboxx;
		}
		else
		{
			int sky1 = sector->sky;
			memset(&skyinfo, 0, sizeof(skyinfo));
			if ((sky1 & PL_SKYFLAT) && (sky1 & (PL_SKYFLAT-1)))
			{
				const line_t *l = &lines[(sky1&(PL_SKYFLAT-1))-1];
				const side_t *s = l->sidedef[0];
				int pos;
				
				if (level.flags & LEVEL_SWAPSKIES && s->GetTexture(side_t::bottom).isValid())
				{
					pos = side_t::bottom;
				}
				else
				{
					pos = side_t::top;
				}

				FTextureID texno = s->GetTexture(pos);
				skyinfo.texture[0] = FMaterial::ValidateTexture(texno, false, true);
				if (!skyinfo.texture[0] || skyinfo.texture[0]->tex->UseType == FTexture::TEX_Null) goto normalsky;
				skyinfo.skytexno1 = texno;
				skyinfo.x_offset[0] = ANGLE_TO_FLOAT(s->GetTextureXOffset(pos));
				skyinfo.y_offset = FIXED2FLOAT(s->GetTextureYOffset(pos));
				skyinfo.mirrored = !l->args[2];
			}
			else
			{
			normalsky:
				if (level.flags&LEVEL_DOUBLESKY)
				{
					skyinfo.texture[1]=FMaterial::ValidateTexture(sky1texture, false, true);
					skyinfo.x_offset[1] = GLRenderer->mSky1Pos;
					skyinfo.doublesky = true;
				}
				
				if ((level.flags&LEVEL_SWAPSKIES || (sky1==PL_SKYFLAT) || (level.flags&LEVEL_DOUBLESKY)) &&
					sky2texture!=sky1texture)	// If both skies are equal use the scroll offset of the first!
				{
					skyinfo.texture[0]=FMaterial::ValidateTexture(sky2texture, false, true);
					skyinfo.skytexno1=sky2texture;
					skyinfo.sky2 = true;
					skyinfo.x_offset[0] = GLRenderer->mSky2Pos;
				}
				else
				{
					skyinfo.texture[0]=FMaterial::ValidateTexture(sky1texture, false, true);
					skyinfo.skytexno1=sky1texture;
					skyinfo.x_offset[0] = GLRenderer->mSky1Pos;
				}
			}
			if (skyfog>0) 
			{
				skyinfo.fadecolor=Colormap.FadeColor;
				skyinfo.fadecolor.a=0;
			}
			else skyinfo.fadecolor=0;

			type=RENDERWALL_SKY;
			sky=UniqueSkies.Get(&skyinfo);
		}
	}
	else if (allowreflect && sector->GetReflect(plane) > 0)
	{
		if ((plane == sector_t::ceiling && viewz > sector->ceilingplane.d) ||
			(plane == sector_t::floor && viewz < -sector->floorplane.d)) return;
		type=RENDERWALL_PLANEMIRROR;
		planemirror = plane == sector_t::ceiling? &sector->ceilingplane : &sector->floorplane;
	}
	else return;
	PutWall(0);
}
Example #7
0
//==========================================================================
//
//  Calculate sky texture
//
//==========================================================================
void GLWall::SkyTexture(int sky1,ASkyViewpoint * skyboxx, bool ceiling)
{
	// JUSTHIT is used as an indicator that a skybox is in use.
	// This is to avoid recursion
	if (!gl_noskyboxes && !(gl.flags&RFL_NOSTENCIL) && skyboxx && viewactor!=skyboxx && !(skyboxx->flags&MF_JUSTHIT))
	{
		if (!skyboxx->Mate) 
		{
			type=RENDERWALL_SKYBOX;
			skybox=skyboxx;
		}
		else 
		{
			static GLSectorStackInfo stackinfo;
			if (ceiling && GLPortal::inlowerstack) return;
			if (!ceiling && GLPortal::inupperstack) return;
			type=RENDERWALL_SECTORSTACK;
			stackinfo.deltax = skyboxx->Mate->x - skyboxx->x;
			stackinfo.deltay = skyboxx->Mate->y - skyboxx->y;
			stackinfo.deltaz = 0;
			stackinfo.isupper= ceiling;
			stack=&stackinfo;
		}
	}
	else
	{
		if (skyboxx && skyboxx->Mate) return;

		// VC's optimizer totally screws up if this is made local...
		static GLSkyInfo skyinfo;

		memset(&skyinfo, 0, sizeof(skyinfo));
		if ((sky1 & PL_SKYFLAT) && (sky1 & (PL_SKYFLAT-1)) && !(gl.flags&RFL_NOSTENCIL))
		{
			const line_t *l = &lines[(sky1&(PL_SKYFLAT-1))-1];
			const side_t *s = &sides[l->sidenum[0]];
			int pos;
			
			if (level.flags & LEVEL_SWAPSKIES && s->GetTexture(side_t::bottom).isValid())
			{
				pos = side_t::bottom;
			}
			else
			{
				pos = side_t::top;
			}

			FTextureID texno = s->GetTexture(pos);
			skyinfo.texture[0] = FGLTexture::ValidateTexture(texno);
			if (!skyinfo.texture[0] || skyinfo.texture[0]->tex->UseType == FTexture::TEX_Null) goto normalsky;
			skyinfo.skytexno1 = texno;
			skyinfo.x_offset[0] = ANGLE_TO_FLOAT(s->GetTextureXOffset(pos));
			skyinfo.y_offset = TO_GL(s->GetTextureYOffset(pos));
			skyinfo.mirrored = !l->args[2];
		}
		else
		{
		normalsky:
			if (level.flags&LEVEL_DOUBLESKY)
			{
				skyinfo.texture[1]=FGLTexture::ValidateTexture(sky1texture);
				if (!skyinfo.texture[1]) return;
				skyinfo.x_offset[1] = gl_sky1pos;
				skyinfo.doublesky = true;
			}
			
			if ((level.flags&LEVEL_SWAPSKIES || (sky1==PL_SKYFLAT && !(gl.flags&RFL_NOSTENCIL)) || (level.flags&LEVEL_DOUBLESKY)) &&
				sky2texture!=sky1texture)	// If both skies are equal use the scroll offset of the first!
			{
				skyinfo.texture[0]=FGLTexture::ValidateTexture(sky2texture);
				skyinfo.skytexno1=sky2texture;
				skyinfo.x_offset[0] = gl_sky2pos;
			}
			else
			{
				skyinfo.texture[0]=FGLTexture::ValidateTexture(sky1texture);
				skyinfo.skytexno1=sky1texture;
				skyinfo.x_offset[0] = gl_sky1pos;
			}
			if (!skyinfo.texture[0]) return;

		}
		if (skyfog>0) 
		{
			skyinfo.fadecolor=Colormap.FadeColor;
			skyinfo.fadecolor.a=0;
		}
		else skyinfo.fadecolor=0;

		type=RENDERWALL_SKY;
		sky = &skyinfo;
	}
	PutWall(0);
}
Example #8
0
void gl_RenderModel(GLSprite * spr, int cm)
{
	// [BB/EP] Take care of gl_fogmode and ZADF_FORCE_GL_DEFAULTS.
	OVERRIDE_FOGMODE_IF_NECESSARY

	FSpriteModelFrame * smf = spr->modelframe;


	// Setup transformation.
	gl.MatrixMode(GL_MODELVIEW);
	gl.PushMatrix();
	gl.DepthFunc(GL_LEQUAL);
	// [BB] In case the model should be rendered translucent, do back face culling.
	// This solves a few of the problems caused by the lack of depth sorting.
	// TO-DO: Implement proper depth sorting.
	if (!( spr->actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] ))
	{
		gl.Enable(GL_CULL_FACE);
		glFrontFace(GL_CW);
	}

	int translation = 0;
	if ( !(smf->flags & MDL_IGNORETRANSLATION) )
		translation = spr->actor->Translation;


	// y scale for a sprite means height, i.e. z in the world!
	float scaleFactorX = FIXED2FLOAT(spr->actor->scaleX) * smf->xscale;
	float scaleFactorY = FIXED2FLOAT(spr->actor->scaleX) * smf->yscale;
	float scaleFactorZ = FIXED2FLOAT(spr->actor->scaleY) * smf->zscale;
	float pitch = 0;
	float rotateOffset = 0;
	float angle = ANGLE_TO_FLOAT(spr->actor->angle);

	// [BB] Workaround for the missing pitch information.
	if ( (smf->flags & MDL_PITCHFROMMOMENTUM) )
	{
		const double x = static_cast<double>(spr->actor->velx);
		const double y = static_cast<double>(spr->actor->vely);
		const double z = static_cast<double>(spr->actor->velz);
		// [BB] Calculate the pitch using spherical coordinates.
		
		pitch = float(atan( z/sqrt(x*x+y*y) ) / M_PI * 180);
	}

	if( smf->flags & MDL_ROTATING )
	{
		const float time = smf->rotationSpeed*GetTimeFloat()/200.f;
		rotateOffset = float((time - xs_FloorToInt(time)) *360.f );
	}

	if (gl_fogmode != 2 && (GLRenderer->mLightCount == 0 || !gl_light_models))
	{
		// Model space => World space
		gl.Translatef(spr->x, spr->z, spr->y );

		if ( !(smf->flags & MDL_ALIGNANGLE) )
			gl.Rotatef(-angle, 0, 1, 0);
		// [BB] Change the angle so that the object is exactly facing the camera in the x/y plane.
		else
			gl.Rotatef( -ANGLE_TO_FLOAT ( R_PointToAngle ( spr->actor->x, spr->actor->y ) ), 0, 1, 0);

		// [BB] Change the pitch so that the object is vertically facing the camera (only makes sense combined with MDL_ALIGNANGLE).
		if ( (smf->flags & MDL_ALIGNPITCH) )
		{
			const fixed_t distance = R_PointToDist2( spr->actor->x - viewx, spr->actor->y - viewy );
			const float pitch = RAD2DEG ( atan2( FIXED2FLOAT ( spr->actor->z - viewz ), FIXED2FLOAT ( distance ) ) );
			gl.Rotatef(pitch, 0, 0, 1);
		}

		// [BB] Workaround for the missing pitch information.
		if (pitch != 0)	gl.Rotatef(pitch, 0, 0, 1);

		// [BB] Special flag for flat, beam like models.
		if ( (smf->flags & MDL_ROLLAGAINSTANGLE) )
			gl.Rotatef( gl_RollAgainstAngleHelper ( spr->actor ), 1, 0, 0);

		// Model rotation.
		// [BB] Added Doomsday like rotation of the weapon pickup models.
		// The rotation angle is based on the elapsed time.

		if( smf->flags & MDL_ROTATING )
		{
			gl.Translatef(smf->rotationCenterX, smf->rotationCenterY, smf->rotationCenterZ);
			gl.Rotatef(rotateOffset, smf->xrotate, smf->yrotate, smf->zrotate);
			gl.Translatef(-smf->rotationCenterX, -smf->rotationCenterY, -smf->rotationCenterZ);
		} 		

		// Scaling and model space offset.
		gl.Scalef(scaleFactorX, scaleFactorZ, scaleFactorY);

		// [BB] Apply zoffset here, needs to be scaled by 1 / smf->zscale, so that zoffset doesn't depend on the z-scaling.
		gl.Translatef(0., smf->zoffset / smf->zscale, 0.);

		gl_RenderFrameModels( smf, spr->actor->state, spr->actor->tics, RUNTIME_TYPE(spr->actor), cm, NULL, NULL, translation );
	}
	else
	{
		Matrix3x4 ModelToWorld;
		Matrix3x4 NormalTransform;

		// For radial fog we need to pass coordinates in world space in order to calculate distances.
		// That means that the local transformations cannot be part of the modelview matrix

		ModelToWorld.MakeIdentity();

		// Model space => World space
		ModelToWorld.Translate(spr->x, spr->z, spr->y);

		if ( !(smf->flags & MDL_ALIGNANGLE) )
			ModelToWorld.Rotate(0,1,0, -angle);
		// [BB] Change the angle so that the object is exactly facing the camera in the x/y plane.
		else
			ModelToWorld.Rotate(0,1,0, -ANGLE_TO_FLOAT ( R_PointToAngle ( spr->actor->x, spr->actor->y ) ) );

		// [BB] Change the pitch so that the object is vertically facing the camera (only makes sense combined with MDL_ALIGNANGLE).
		if ( (smf->flags & MDL_ALIGNPITCH) )
		{
			const fixed_t distance = R_PointToDist2( spr->actor->x - viewx, spr->actor->y - viewy );
			const float pitch = RAD2DEG ( atan2( FIXED2FLOAT ( spr->actor->z - viewz ), FIXED2FLOAT ( distance ) ) );
			ModelToWorld.Rotate(0,0,1,pitch);
		}

		// [BB] Workaround for the missing pitch information.
		if (pitch != 0) ModelToWorld.Rotate(0,0,1,pitch);

		// [BB] Special flag for flat, beam like models.
		if ( (smf->flags & MDL_ROLLAGAINSTANGLE) )
			ModelToWorld.Rotate(1, 0, 0, gl_RollAgainstAngleHelper ( spr->actor ));

		// Model rotation.
		// [BB] Added Doomsday like rotation of the weapon pickup models.
		// The rotation angle is based on the elapsed time.

		if( smf->flags & MDL_ROTATING )
		{
			ModelToWorld.Translate(-smf->rotationCenterX, -smf->rotationCenterY, -smf->rotationCenterZ);
			ModelToWorld.Rotate(smf->xrotate, smf->yrotate, smf->zrotate, rotateOffset);
			ModelToWorld.Translate(smf->rotationCenterX, smf->rotationCenterY, smf->rotationCenterZ);
		}

		ModelToWorld.Scale(scaleFactorX, scaleFactorZ, scaleFactorY);

		// [BB] Apply zoffset here, needs to be scaled by 1 / smf->zscale, so that zoffset doesn't depend on the z-scaling.
		ModelToWorld.Translate(0., smf->zoffset / smf->zscale, 0.);

		if (!gl_light_models)
		{
			gl_RenderFrameModels( smf, spr->actor->state, spr->actor->tics, RUNTIME_TYPE(spr->actor), cm, &ModelToWorld, NULL, translation );
		}
		else
		{
			// The normal transform matrix only contains the inverse rotations and scalings but not the translations
			NormalTransform.MakeIdentity();

			NormalTransform.Scale(1.f/scaleFactorX, 1.f/scaleFactorZ, 1.f/scaleFactorY);
			if( smf->flags & MDL_ROTATING ) NormalTransform.Rotate(smf->xrotate, smf->yrotate, smf->zrotate, -rotateOffset);
			if (pitch != 0) NormalTransform.Rotate(0,0,1,-pitch);
			if (angle != 0) NormalTransform.Rotate(0,1,0, angle);

			gl_RenderFrameModels( smf, spr->actor->state, spr->actor->tics, RUNTIME_TYPE(spr->actor), cm, &ModelToWorld, &NormalTransform, translation );
		}

	}

	gl.MatrixMode(GL_MODELVIEW);
	gl.PopMatrix();
	gl.DepthFunc(GL_LESS);
	if (!( spr->actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] ))
		gl.Disable(GL_CULL_FACE);
}