Exemple #1
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);
	}
}
Exemple #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);
	}
void Plane::Set(secplane_t &plane)
{
   float a, b, c, d;

   a = FIXED2FLOAT(plane.a);
   b = FIXED2FLOAT(plane.b);
   c = FIXED2FLOAT(plane.c);
   d = FIXED2FLOAT(plane.d);

   m_normal.Set(a, c, b);
   //m_normal.Normalize(); the vector is already normalized
   m_d = d;
}
Exemple #4
0
void gl_RenderHUDModel(pspdef_t *psp, fixed_t ofsx, fixed_t ofsy, int cm)
{
	AActor * playermo=players[consoleplayer].camera;
	FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->state->sprite, psp->state->GetFrame());

	// [BB] No model found for this sprite, so we can't render anything.
	if ( smf == NULL )
		return;

	// [BB] The model has to be drawn independtly from the position of the player,
	// so we have to reset the GL_MODELVIEW matrix.
	gl.MatrixMode(GL_MODELVIEW);
	gl.PushMatrix();
	gl.LoadIdentity();
	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 (!( playermo->RenderStyle == LegacyRenderStyles[STYLE_Normal] ))
	{
		gl.Enable(GL_CULL_FACE);
		glFrontFace(GL_CCW);
	}

	// Scaling and model space offset.
	gl.Scalef(	
		smf->xscale,
		smf->zscale,	// y scale for a sprite means height, i.e. z in the world!
		smf->yscale);

	// [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.);

	// [BB] Weapon bob, very similar to the normal Doom weapon bob.
	gl.Rotatef(FIXED2FLOAT(ofsx)/4, 0, 1, 0);
	gl.Rotatef(-FIXED2FLOAT(ofsy-WEAPONTOP)/4, 1, 0, 0);

	// [BB] For some reason the jDoom models need to be rotated.
	gl.Rotatef(90., 0, 1, 0);

	gl_RenderFrameModels( smf, psp->state, psp->tics, playermo->player->ReadyWeapon->GetClass(), cm, NULL, NULL, 0 );

	gl.MatrixMode(GL_MODELVIEW);
	gl.PopMatrix();
	gl.DepthFunc(GL_LESS);
	if (!( playermo->RenderStyle == LegacyRenderStyles[STYLE_Normal] ))
		gl.Disable(GL_CULL_FACE);
}
Exemple #5
0
void GLPlaneMirrorPortal::DrawContents()
{
	if (renderdepth>r_mirror_recursions) 
	{
		ClearScreen();
		return;
	}

	int old_pm=PlaneMirrorMode;

	fixed_t planez = origin->ZatPoint(viewx, viewy);
	viewz = 2*planez - viewz;
	GLRenderer->mViewActor = NULL;
	PlaneMirrorMode = ksgn(origin->c);

	validcount++;

	PlaneMirrorFlag++;
	GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));
	ClearClipper();

	glEnable(GL_CLIP_PLANE0+renderdepth);
	// This only works properly for non-sloped planes so don't bother with the math.
	//double d[4]={origin->a/65536., origin->c/65536., origin->b/65536., FIXED2FLOAT(origin->d)};
	double d[4]={0, static_cast<double>(PlaneMirrorMode), 0, FIXED2FLOAT(origin->d)};
	glClipPlane(GL_CLIP_PLANE0+renderdepth, d);

	GLRenderer->DrawScene();
	glDisable(GL_CLIP_PLANE0+renderdepth);
	PlaneMirrorFlag--;
	PlaneMirrorMode=old_pm;
}
Exemple #6
0
void GLFlat::DrawSubsector(subsector_t * sub)
{
	FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
	if (plane.plane.a | plane.plane.b)
	{
		for (unsigned int k = 0; k < sub->numlines; k++)
		{
			vertex_t *vt = sub->firstline[k].v1;
			ptr->x = vt->fx;
			ptr->y = vt->fy;
			ptr->z = plane.plane.ZatPoint(vt->fx, vt->fy) + dz;
			ptr->u = vt->fx / 64.f;
			ptr->v = -vt->fy / 64.f;
			ptr++;
		}
	}
	else
	{
		float zc = FIXED2FLOAT(plane.plane.Zat0()) + dz;
		for (unsigned int k = 0; k < sub->numlines; k++)
		{
			vertex_t *vt = sub->firstline[k].v1;
			ptr->x = vt->fx;
			ptr->y = vt->fy;
			ptr->z = zc;
			ptr->u = vt->fx / 64.f;
			ptr->v = -vt->fy / 64.f;
			ptr++;
		}
	}
	GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);

	flatvertices += sub->numlines;
	flatprimitives++;
}
Exemple #7
0
static boolean RB_GenerateDecal(vtxlist_t *vl, int *drawcount)
{
    vtx_t *v;
    rbDecal_t *decal;
    float offset;
    int count;
    int i;

    v = &drawVertex[*drawcount];
    decal = (rbDecal_t*)vl->data;
    count = *drawcount;

    for(i = 0; i < decal->numpoints - 2; ++i)
    {
        RB_AddTriangle(count, count + 1 + i, count + 2 + i);
    }

    offset = 0;

    if(decal->type == DCT_UPPERWALL || decal->type == DCT_CEILING)
    {
        offset = FIXED2FLOAT(decal->initialStickZ - decal->stickSector->ceilingheight);
    }
    else if(decal->type == DCT_LOWERWALL || decal->type == DCT_FLOOR)
    {
        offset = FIXED2FLOAT(decal->initialStickZ - decal->stickSector->floorheight);
    }

    for(i = 0; i < decal->numpoints; ++i)
    {
        v[i].x = decal->points[i].x;
        v[i].y = decal->points[i].y;
        v[i].z = decal->points[i].z - offset;

        v[i].tu = decal->points[i].tu;
        v[i].tv = decal->points[i].tv;

        v[i].r =
        v[i].g =
        v[i].b =
        v[i].a = (byte)(decal->alpha * 255.0f);
    }

    *drawcount += decal->numpoints;
    return true;
}
Exemple #8
0
static void SkyVertex(int r, int c)
{
	angle_t topAngle= (angle_t)(c / (float)columns * ANGLE_MAX);
	angle_t sideAngle = maxSideAngle * (rows - r) / rows;
	fixed_t height = finesine[sideAngle>>ANGLETOFINESHIFT];
	fixed_t realRadius = FixedMul(scale, finecosine[sideAngle>>ANGLETOFINESHIFT]);
	fixed_t x = FixedMul(realRadius, finecosine[topAngle>>ANGLETOFINESHIFT]);
	fixed_t y = (!yflip) ? FixedMul(scale, height) : FixedMul(scale, height) * -1;
	fixed_t z = FixedMul(realRadius, finesine[topAngle>>ANGLETOFINESHIFT]);
	float fx, fy, fz;
	float color = r * 1.f / rows;
	float u, v;
	float timesRepeat;
	
	timesRepeat = (short)(4 * (256.f / texw));
	if (timesRepeat == 0.f) timesRepeat = 1.f;
	
	if (!foglayer)
	{
		gl_SetColor(255, 0, NULL, r==0? 0.0f : 1.0f);
		
		// And the texture coordinates.
		if(!yflip)	// Flipped Y is for the lower hemisphere.
		{
			u = (-timesRepeat * c / (float)columns) ;
			v = (r / (float)rows) + yAdd;
		}
		else
		{
			u = (-timesRepeat * c / (float)columns) ;
			v = 1.0f + ((rows-r)/(float)rows) + yAdd;
		}
		
		
		glTexCoord2f(skymirror? -u:u, v);
	}
	if (r != 4) y+=FRACUNIT*300;
	// And finally the vertex.
	fx =-FIXED2FLOAT(x);	// Doom mirrors the sky vertically!
	fy = FIXED2FLOAT(y);
	fz = FIXED2FLOAT(z);
	glVertex3f(fx, fy - 1.f, fz);
}
Exemple #9
0
void ADynamicLight::LinkLight()
{
	// mark the old light nodes
	FLightNode * node;
	
	node = touching_sides;
	while (node)
    {
		node->lightsource = NULL;
		node = node->nextTarget;
    }
	node = touching_subsectors;
	while (node)
    {
		node->lightsource = NULL;
		node = node->nextTarget;
    }

	if (radius>0)
	{
		// passing in radius*radius allows us to do a distance check without any calls to sqrtf
		::validcount++;
		subsector_t * subSec = R_PointInSubsector(x, y);
		if (subSec)
		{
			float fradius = FIXED2FLOAT(radius);
			CollectWithinRadius(subSec, fradius*fradius);
		}
	}
		
	// Now delete any nodes that won't be used. These are the ones where
	// m_thing is still NULL.
	
	node = touching_sides;
	while (node)
	{
		if (node->lightsource == NULL)
		{
			node = DeleteLightNode(node);
		}
		else
			node = node->nextTarget;
	}

	node = touching_subsectors;
	while (node)
	{
		if (node->lightsource == NULL)
		{
			node = DeleteLightNode(node);
		}
		else
			node = node->nextTarget;
	}
}
Exemple #10
0
//==========================================================================
//
//
//
//==========================================================================
void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort)
{
	GLFlat * fh=&flats[drawitems[head->itemindex].index];
	GLWall * ws=&walls[drawitems[sort->itemindex].index];
	GLWall * ws1;

	bool ceiling = fh->z > FIXED2FLOAT(viewz);


	if (ws->ztop[0]>fh->z && ws->zbottom[0]<fh->z)
	{
		// We have to split this wall!

		// WARNING: NEVER EVER push a member of an array onto the array itself.
		// Bad things will happen if the memory must be reallocated!
		GLWall w=*ws;
		AddWall(&w);

		ws1=&walls[walls.Size()-1];
		ws=&walls[drawitems[sort->itemindex].index];	// may have been reallocated!
		float newtexv = ws->uplft.v + ((ws->lolft.v - ws->uplft.v) / (ws->zbottom[0] - ws->ztop[0])) * (fh->z - ws->ztop[0]);

		// I make the very big assumption here that translucent walls in sloped sectors
		// and 3D-floors never coexist in the same level. If that were the case this
		// code would become extremely more complicated.
		if (!ceiling)
		{
			ws->ztop[1] = ws1->zbottom[1] = ws->ztop[0] = ws1->zbottom[0] = fh->z;
			ws->uprgt.v = ws1->lorgt.v = ws->uplft.v = ws1->lolft.v = newtexv;
		}
		else
		{
			ws1->ztop[1] = ws->zbottom[1] = ws1->ztop[0] = ws->zbottom[0] = fh->z;
			ws1->uplft.v = ws->lolft.v = ws1->uprgt.v = ws->lorgt.v=newtexv;
		}

		SortNode * sort2=SortNodes.GetNew();
		memset(sort2,0,sizeof(SortNode));
		sort2->itemindex=drawitems.Size()-1;

		head->AddToLeft(sort);
		head->AddToRight(sort2);
	}
	else if ((ws->zbottom[0]<fh->z && !ceiling) || (ws->ztop[0]>fh->z && ceiling))	// completely on the left side
	{
		head->AddToLeft(sort);
	}
	else
	{
		head->AddToRight(sort);
	}

}
void FSkyVertexBuffer::SkyVertex(int r, int c, bool yflip)
{
	static const angle_t maxSideAngle = ANGLE_180 / 3;
	static const fixed_t scale = 10000 << FRACBITS;

	angle_t topAngle= (angle_t)(c / (float)mColumns * ANGLE_MAX);
	angle_t sideAngle = maxSideAngle * (mRows - r) / mRows;
	fixed_t height = finesine[sideAngle>>ANGLETOFINESHIFT];
	fixed_t realRadius = FixedMul(scale, finecosine[sideAngle>>ANGLETOFINESHIFT]);
	fixed_t x = FixedMul(realRadius, finecosine[topAngle>>ANGLETOFINESHIFT]);
	fixed_t y = (!yflip) ? FixedMul(scale, height) : FixedMul(scale, height) * -1;
	fixed_t z = FixedMul(realRadius, finesine[topAngle>>ANGLETOFINESHIFT]);

	FSkyVertex vert;
	
	vert.color = r == 0 ? 0xffffff : 0xffffffff;
		
	// And the texture coordinates.
	if(!yflip)	// Flipped Y is for the lower hemisphere.
	{
		vert.u = (-c / (float)mColumns) ;
		vert.v = (r / (float)mRows);
	}
	else
	{
		vert.u = (-c / (float)mColumns);
		vert.v = 1.0f + ((mRows - r) / (float)mRows);
	}

	if (r != 4) y+=FRACUNIT*300;
	// And finally the vertex.
	vert.x =-FIXED2FLOAT(x);	// Doom mirrors the sky vertically!
	vert.y = FIXED2FLOAT(y) - 1.f;
	vert.z = FIXED2FLOAT(z);

	mVertices.Push(vert);
}
//==========================================================================
//
//
//
//==========================================================================
void GLSprite::SplitSprite(sector_t * frontsector, bool translucent)
{
    GLSprite copySprite;
    fixed_t lightbottom;
    float maplightbottom;
    unsigned int i;
    bool put=false;
    TArray<lightlist_t> & lightlist=frontsector->e->XFloor.lightlist;

    //y1+=y;
    //y2+=y;
    //y=0;
    for(i=0; i<lightlist.Size(); i++)
    {
        // Particles don't go through here so we can safely assume that actor is not NULL
        if (i<lightlist.Size()-1) lightbottom=lightlist[i+1].plane.ZatPoint(actor->x,actor->y);
        else lightbottom=frontsector->floorplane.ZatPoint(actor->x,actor->y);

        //maplighttop=FIXED2FLOAT(lightlist[i].height);
        maplightbottom=FIXED2FLOAT(lightbottom);
        if (maplightbottom<z2) maplightbottom=z2;

        if (maplightbottom<z1)
        {
            copySprite=*this;
            copySprite.lightlevel=*lightlist[i].p_lightlevel;
            copySprite.Colormap.CopyLightColor(*lightlist[i].p_extra_colormap);

            if (glset.nocoloredspritelighting)
            {
                int v = (copySprite.Colormap.LightColor.r + copySprite.Colormap.LightColor.g + copySprite.Colormap.LightColor.b )/3;
                copySprite.Colormap.LightColor.r=
                    copySprite.Colormap.LightColor.g=
                        copySprite.Colormap.LightColor.b=(255+v+v)/3;
            }

            if (!gl_isWhite(ThingColor))
            {
                copySprite.Colormap.LightColor.r=(copySprite.Colormap.LightColor.r*ThingColor.r)>>8;
                copySprite.Colormap.LightColor.g=(copySprite.Colormap.LightColor.g*ThingColor.g)>>8;
                copySprite.Colormap.LightColor.b=(copySprite.Colormap.LightColor.b*ThingColor.b)>>8;
            }

            z1=copySprite.z2=maplightbottom;
            vt=copySprite.vb=copySprite.vt+
                             (maplightbottom-copySprite.z1)*(copySprite.vb-copySprite.vt)/(z2-copySprite.z1);
            copySprite.PutSprite(translucent);
            put=true;
        }
Exemple #13
0
//==========================================================================
//
//
//
//==========================================================================
void GLDrawList::SortSpriteIntoPlane(SortNode * head,SortNode * sort)
{
	GLFlat * fh=&flats[drawitems[head->itemindex].index];
	GLSprite * ss=&sprites[drawitems[sort->itemindex].index];
	GLSprite * ss1;

	bool ceiling = fh->z > FIXED2FLOAT(viewz);

	if (ss->z1>fh->z && ss->z2<fh->z)
	{
		// We have to split this sprite!
		GLSprite s=*ss;
		AddSprite(&s);
		ss1=&sprites[sprites.Size()-1];
		ss=&sprites[drawitems[sort->itemindex].index];	// may have been reallocated!
		float newtexv=ss->vt + ((ss->vb-ss->vt)/(ss->z2-ss->z1))*(fh->z-ss->z1);

		if (!ceiling)
		{
			ss->z1=ss1->z2=fh->z;
			ss->vt=ss1->vb=newtexv;
		}
		else
		{
			ss1->z1=ss->z2=fh->z;
			ss1->vt=ss->vb=newtexv;
		}

		SortNode * sort2=SortNodes.GetNew();
		memset(sort2,0,sizeof(SortNode));
		sort2->itemindex=drawitems.Size()-1;

		head->AddToLeft(sort);
		head->AddToRight(sort2);
	}
	else if ((ss->z2<fh->z && !ceiling) || (ss->z1>fh->z && ceiling))	// completely on the left side
	{
		head->AddToLeft(sort);
	}
	else
	{
		head->AddToRight(sort);
	}

}
Exemple #14
0
float ADynamicLight::DistToSeg(seg_t *seg)
{
   float u, px, py;

   float seg_dx = FIXED2FLOAT(seg->v2->x - seg->v1->x);
   float seg_dy = FIXED2FLOAT(seg->v2->y - seg->v1->y);
   float seg_length_sq = seg_dx * seg_dx + seg_dy * seg_dy;

   u = (  FIXED2FLOAT(x - seg->v1->x) * seg_dx + FIXED2FLOAT(y - seg->v1->y) * seg_dy) / seg_length_sq;
   if (u < 0.f) u = 0.f; // clamp the test point to the line segment
   if (u > 1.f) u = 1.f;

   px = FIXED2FLOAT(seg->v1->x) + (u * seg_dx);
   py = FIXED2FLOAT(seg->v1->y) + (u * seg_dy);

   px -= FIXED2FLOAT(x);
   py -= FIXED2FLOAT(y);

   return (px*px) + (py*py);
}
Exemple #15
0
void RenderAutomap()
{
	size_t i;

	glDisable(GL_TEXTURE_2D);

	glColor4f(0.2,0.2,0,1);
	DrawQuad(0,0,1,1);

	glColor4f(1,1,1,1);

	glPushMatrix();

	glTranslatef(0.5, 0.5, 0);

	glScalef(-0.001, 0.001, 0.001);

	AActor *mo = consoleplayer().mo;
	if(mo)
		glTranslatef(FIXED2FLOAT(mo->x), FIXED2FLOAT(mo->y), 0);
	glRotatef(180, 0, 0, 1);

	glBegin(GL_LINES);

	// grid

	// walls
	for(i = 0; i < numlines; i++)
	{
		if (!(lines[i].flags & ML_MAPPED))
			continue;

		glVertex2f(FIXED2FLOAT(lines[i].v1->x), FIXED2FLOAT(lines[i].v1->y));
		glVertex2f(FIXED2FLOAT(lines[i].v2->x), FIXED2FLOAT(lines[i].v2->y));
	}

	// players
	for (i = 0; i < players.size(); i++)
	{
	}

	// things

	glEnd();

	glPopMatrix();
}
Exemple #16
0
void FDrawInfo::FloodLowerGap(seg_t * seg)
{
	wallseg ws;
	sector_t ffake, bfake;
	sector_t * fakefsector = gl_FakeFlat(seg->frontsector, &ffake, true);
	sector_t * fakebsector = gl_FakeFlat(seg->backsector, &bfake, false);

	vertex_t * v1, * v2;

	// Although the plane can be sloped this code will only be called
	// when the edge itself is not.
	fixed_t backz = fakebsector->floorplane.ZatPoint(seg->v1);
	fixed_t frontz = fakefsector->floorplane.ZatPoint(seg->v1);


	if (fakebsector->GetTexture(sector_t::floor) == skyflatnum) return;
	if (fakebsector->GetPlaneTexZ(sector_t::floor) > viewz) return;

	if (seg->sidedef == seg->linedef->sidedef[0])
	{
		v1=seg->linedef->v1;
		v2=seg->linedef->v2;
	}
	else
	{
		v1=seg->linedef->v2;
		v2=seg->linedef->v1;
	}

	ws.x1= FIXED2FLOAT(v1->x);
	ws.y1= FIXED2FLOAT(v1->y);
	ws.x2= FIXED2FLOAT(v2->x);
	ws.y2= FIXED2FLOAT(v2->y);

	ws.z2= FIXED2FLOAT(frontz);
	ws.z1= FIXED2FLOAT(backz);

	// Step1: Draw a stencil into the gap
	SetupFloodStencil(&ws);

	// Step2: Project the ceiling plane into the gap
	DrawFloodedPlane(&ws, ws.z1, fakebsector, false);

	// Step3: Delete the stencil
	ClearFloodStencil(&ws);
}
Exemple #17
0
//==========================================================================
//
// Draw the plane segment into the gap
//
//==========================================================================
void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling)
{
	GLSectorPlane plane;
	int lightlevel;
	FColormap Colormap;
	FMaterial * gltexture;

	plane.GetFromSector(sec, ceiling);

	gltexture=FMaterial::ValidateTexture(plane.texture, true);
	if (!gltexture) return;

	if (gl_fixedcolormap) 
	{
		Colormap.Clear();
		lightlevel=255;
	}
	else
	{
		Colormap=sec->ColorMap;
		if (gltexture->tex->isFullbright())
		{
			Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff;
			lightlevel=255;
		}
		else lightlevel=abs(ceiling? sec->GetCeilingLight() : sec->GetFloorLight());
	}

	int rel = getExtraLight();
	gl_SetColor(lightlevel, rel, Colormap, 1.0f);
	gl_SetFog(lightlevel, rel, &Colormap, false);
	gltexture->Bind();

	float fviewx = FIXED2FLOAT(viewx);
	float fviewy = FIXED2FLOAT(viewy);
	float fviewz = FIXED2FLOAT(viewz);

	gl_SetPlaneTextureRotation(&plane, gltexture);
	gl_RenderState.Apply();

	float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz);
	float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz);

	float px1 = fviewx + prj_fac1 * (ws->x1-fviewx);
	float py1 = fviewy + prj_fac1 * (ws->y1-fviewy);

	float px2 = fviewx + prj_fac2 * (ws->x1-fviewx);
	float py2 = fviewy + prj_fac2 * (ws->y1-fviewy);

	float px3 = fviewx + prj_fac2 * (ws->x2-fviewx);
	float py3 = fviewy + prj_fac2 * (ws->y2-fviewy);

	float px4 = fviewx + prj_fac1 * (ws->x2-fviewx);
	float py4 = fviewy + prj_fac1 * (ws->y2-fviewy);

	FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
	ptr->Set(px1, planez, py1, px1 / 64, -py1 / 64);
	ptr++;
	ptr->Set(px2, planez, py2, px2 / 64, -py2 / 64);
	ptr++;
	ptr->Set(px3, planez, py3, px3 / 64, -py3 / 64);
	ptr++;
	ptr->Set(px4, planez, py4, px4 / 64, -py4 / 64);
	ptr++;
	GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);

	gl_RenderState.EnableTextureMatrix(false);
}
Exemple #18
0
void GLWall::SetupLights()
{
	float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2};
	Plane p;

	lightdata.Clear();
	p.Init(vtx,4);

	if (!p.ValidNormal()) 
	{
		return;
	}
	for(int i=0;i<2;i++)
	{
		FLightNode *node;
		if (!seg->bPolySeg)
		{
			// Iterate through all dynamic lights which touch this wall and render them
			if (seg->sidedef)
			{
				node = seg->sidedef->lighthead[i];
			}
			else node = NULL;
		}
		else if (sub)
		{
			// To avoid constant rechecking for polyobjects use the subsector's lightlist instead
			node = sub->lighthead[i];
		}
		else node = NULL;

		while (node)
		{
			if (!(node->lightsource->flags2&MF2_DORMANT))
			{
				iter_dlight++;

				Vector fn, pos;

				float x = FIXED2FLOAT(node->lightsource->x);
				float y = FIXED2FLOAT(node->lightsource->y);
				float z = FIXED2FLOAT(node->lightsource->z);
				float dist = fabsf(p.DistToPoint(x, z, y));
				float radius = (node->lightsource->GetRadius() * gl_lights_size);
				float scale = 1.0f / ((2.f * radius) - dist);

				if (radius > 0.f && dist < radius)
				{
					Vector nearPt, up, right;

					pos.Set(x,z,y);
					fn=p.Normal();
					fn.GetRightUp(right, up);

					Vector tmpVec = fn * dist;
					nearPt = pos + tmpVec;

					Vector t1;
					int outcnt[4]={0,0,0,0};
					texcoord tcs[4];

					// do a quick check whether the light touches this polygon
					for(int i=0;i<4;i++)
					{
						t1.Set(&vtx[i*3]);
						Vector nearToVert = t1 - nearPt;
						tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
						tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;

						if (tcs[i].u<0) outcnt[0]++;
						if (tcs[i].u>1) outcnt[1]++;
						if (tcs[i].v<0) outcnt[2]++;
						if (tcs[i].v>1) outcnt[3]++;

					}
					if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) 
					{
						gl_GetLight(p, node->lightsource, Colormap.colormap, true, false, lightdata);
					}
				}
			}
			node = node->nextLight;
		}
	}
	int numlights[3];

	lightdata.Combine(numlights, gl.MaxLights());
	if (numlights[2] > 0)
	{
		draw_dlight+=numlights[2]/2;
		gl_RenderState.EnableLight(true);
		gl_RenderState.SetLights(numlights, &lightdata.arrays[0][0]);
	}
}
Exemple #19
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//
// Horizon Portal
//
// This simply draws the area in medium sized squares. Drawing it as a whole
// polygon creates visible inaccuracies.
//
// Originally I tried to minimize the amount of data to be drawn but there
// are 2 problems with it:
//
// 1. Setting this up completely negates any performance gains.
// 2. It doesn't work with a 360° field of view (as when you are looking up.)
//
//
// So the brute force mechanism is just as good.
//
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// GLHorizonPortal::DrawContents
//
//-----------------------------------------------------------------------------
void GLHorizonPortal::DrawContents()
{
	PortalAll.Clock();

	GLSectorPlane * sp=&origin->plane;
	FMaterial * gltexture;
	PalEntry color;
	float z;
	player_t * player=&players[consoleplayer];

	gltexture=FMaterial::ValidateTexture(sp->texture, true);
	if (!gltexture) 
	{
		ClearScreen();
		PortalAll.Unclock();
		return;
	}


	z=FIXED2FLOAT(sp->texheight);


	if (gltexture && gltexture->tex->isFullbright())
	{
		// glowing textures are always drawn full bright without color
		gl_SetColor(255, 0, NULL, 1.f);
		gl_SetFog(255, 0, &origin->colormap, false);
	}
	else 
	{
		int rel = getExtraLight();
		gl_SetColor(origin->lightlevel, rel, &origin->colormap, 1.0f);
		gl_SetFog(origin->lightlevel, rel, &origin->colormap, false);
	}


	gltexture->Bind(origin->colormap.colormap);

	gl_RenderState.EnableAlphaTest(false);
	gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
	gl_RenderState.Apply();


	bool pushed = gl_SetPlaneTextureRotation(sp, gltexture);

	float vx=FIXED2FLOAT(viewx);
	float vy=FIXED2FLOAT(viewy);

	// Draw to some far away boundary
	for(float x=-32768+vx; x<32768+vx; x+=4096)
	{
		for(float y=-32768+vy; y<32768+vy;y+=4096)
		{
			glBegin(GL_TRIANGLE_FAN);

			glTexCoord2f(x/64, -y/64);
			glVertex3f(x, z, y);

			glTexCoord2f(x/64 + 64, -y/64);
			glVertex3f(x + 4096, z, y);

			glTexCoord2f(x/64 + 64, -y/64 - 64);
			glVertex3f(x + 4096, z, y + 4096);

			glTexCoord2f(x/64, -y/64 - 64);
			glVertex3f(x, z, y + 4096);

			glEnd();

		}
	}

	float vz=FIXED2FLOAT(viewz);
	float tz=(z-vz);///64.0f;

	// fill the gap between the polygon and the true horizon
	// Since I can't draw into infinity there can always be a
	// small gap

	glBegin(GL_TRIANGLE_STRIP);

	glTexCoord2f(512.f, 0);
	glVertex3f(-32768+vx, z, -32768+vy);
	glTexCoord2f(512.f, tz);
	glVertex3f(-32768+vx, vz, -32768+vy);

	glTexCoord2f(-512.f, 0);
	glVertex3f(-32768+vx, z,  32768+vy);
	glTexCoord2f(-512.f, tz);
	glVertex3f(-32768+vx, vz,  32768+vy);

	glTexCoord2f(512.f, 0);
	glVertex3f( 32768+vx, z,  32768+vy);
	glTexCoord2f(512.f, tz);
	glVertex3f( 32768+vx, vz,  32768+vy);

	glTexCoord2f(-512.f, 0);
	glVertex3f( 32768+vx, z, -32768+vy);
	glTexCoord2f(-512.f, tz);
	glVertex3f( 32768+vx, vz, -32768+vy);

	glTexCoord2f(512.f, 0);
	glVertex3f(-32768+vx, z, -32768+vy);
	glTexCoord2f(512.f, tz);
	glVertex3f(-32768+vx, vz, -32768+vy);

	glEnd();

	if (pushed)
	{
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
	}

	PortalAll.Unclock();

}
void FNodeBuilder::ExtractMini (FMiniBSP *bsp)
{
	unsigned int i;

	bsp->bDirty = false;
	bsp->Verts.Resize(Vertices.Size());
	for (i = 0; i < Vertices.Size(); ++i)
	{
		bsp->Verts[i].set(Vertices[i].x, Vertices[i].y);
	}

	bsp->Subsectors.Resize(Subsectors.Size());
	memset(&bsp->Subsectors[0], 0, Subsectors.Size() * sizeof(subsector_t));

	bsp->Nodes.Resize(Nodes.Size());
	memcpy(&bsp->Nodes[0], &Nodes[0], Nodes.Size()*sizeof(node_t));
	for (i = 0; i < Nodes.Size(); ++i)
	{
		D(Printf(PRINT_LOG, "Node %d:\n", i));
		// Go backwards because on 64-bit systems, both of the intchildren are
		// inside the first in-game child.
		for (int j = 1; j >= 0; --j)
		{
			if (bsp->Nodes[i].intchildren[j] & 0x80000000)
			{
				D(Printf(PRINT_LOG, "  subsector %d\n", bsp->Nodes[i].intchildren[j] & 0x7FFFFFFF));
				bsp->Nodes[i].children[j] = (uint8_t *)&bsp->Subsectors[bsp->Nodes[i].intchildren[j] & 0x7fffffff] + 1;
			}
			else
			{
				D(Printf(PRINT_LOG, "  node %d\n", bsp->Nodes[i].intchildren[j]));
				bsp->Nodes[i].children[j] = &bsp->Nodes[bsp->Nodes[i].intchildren[j]];
			}
		}
		for (int j = 0; j < 2; ++j)
		{
			for (int k = 0; k < 4; ++k)
			{
				bsp->Nodes[i].bbox[j][k] = FIXED2FLOAT(bsp->Nodes[i].nb_bbox[j][k]);
			}
		}
	}

	if (GLNodes)
	{
		TArray<glseg_t> glsegs;
		for (i = 0; i < Subsectors.Size(); ++i)
		{
			uint32_t numsegs = CloseSubsector (glsegs, i, &bsp->Verts[0]);
			bsp->Subsectors[i].numlines = numsegs;
			bsp->Subsectors[i].firstline = &bsp->Segs[bsp->Segs.Size() - numsegs];
		}
		bsp->Segs.Resize(glsegs.Size());
		for (i = 0; i < glsegs.Size(); ++i)
		{
			bsp->Segs[i] = *(seg_t *)&glsegs[i];
		}
	}
	else
	{
		memcpy(&bsp->Subsectors[0], &Subsectors[0], Subsectors.Size()*sizeof(subsector_t));
		bsp->Segs.Resize(Segs.Size());
		for (i = 0; i < Segs.Size(); ++i)
		{
			const FPrivSeg *org = &Segs[SegList[i].SegNum];
			seg_t *out = &bsp->Segs[i];

			D(Printf(PRINT_LOG, "Seg %d: v1(%d) -> v2(%d)\n", i, org->v1, org->v2));

			out->v1 = &bsp->Verts[org->v1];
			out->v2 = &bsp->Verts[org->v2];
			out->backsector = org->backsector;
			out->frontsector = org->frontsector;
			if (org->sidedef != int(NO_SIDE))
			{
				out->linedef = Level.Lines + org->linedef;
				out->sidedef = Level.Sides + org->sidedef;
			}
			else	// part of a miniseg
			{
				out->linedef = NULL;
				out->sidedef = NULL;
			}
		}
		for (i = 0; i < bsp->Subsectors.Size(); ++i)
		{
			bsp->Subsectors[i].firstline = &bsp->Segs[(size_t)bsp->Subsectors[i].firstline];
		}
	}
}
Exemple #21
0
//==========================================================================
//
//
//
//==========================================================================
void GLWall::DrawDecal(DBaseDecal *decal)
{
	line_t * line=seg->linedef;
	side_t * side=seg->sidedef;
	int i;
	fixed_t zpos;
	int light;
	int rel;
	float a;
	bool flipx, flipy, loadAlpha;
	DecalVertex dv[4];
	FTextureID decalTile;
	

	if (decal->RenderFlags & RF_INVISIBLE) return;
	if (type==RENDERWALL_FFBLOCK && gltexture->isMasked()) return;	// No decals on 3D floors with transparent textures.

	//if (decal->sprite != 0xffff)
	{
		decalTile = decal->PicNum;
		flipx = !!(decal->RenderFlags & RF_XFLIP);
		flipy = !!(decal->RenderFlags & RF_YFLIP);
	}
	/*
	else
	{
	decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0];
	flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1;
	}
	*/

	FTexture *texture = TexMan[decalTile];
	if (texture == NULL) return;

	FMaterial *tex;


	if (texture->UseType == FTexture::TEX_MiscPatch)
	{
		// We need to create a clone of this texture where we can force the
		// texture filtering offset in.
		if (texture->gl_info.DecalTexture == NULL)
		{
			texture->gl_info.DecalTexture = new FCloneTexture(texture, FTexture::TEX_Decal);
		}
		tex = FMaterial::ValidateTexture(texture->gl_info.DecalTexture);
	}
	else tex = FMaterial::ValidateTexture(texture);


	// the sectors are only used for their texture origin coordinates
	// so we don't need the fake sectors for deep water etc.
	// As this is a completely split wall fragment no further splits are
	// necessary for the decal.
	sector_t *frontsector;

	// for 3d-floor segments use the model sector as reference
	if ((decal->RenderFlags&RF_CLIPMASK)==RF_CLIPMID) frontsector=decal->Sector;
	else frontsector=seg->frontsector;

	switch (decal->RenderFlags & RF_RELMASK)
	{
	default:
		// No valid decal can have this type. If one is encountered anyway
		// it is in some way invalid so skip it.
		return;
		//zpos = decal->z;
		//break;

	case RF_RELUPPER:
		if (type!=RENDERWALL_TOP) return;
		if (line->flags & ML_DONTPEGTOP)
		{
			zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
		}
		else
		{
			zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling);
		}
		break;
	case RF_RELLOWER:
		if (type!=RENDERWALL_BOTTOM) return;
		if (line->flags & ML_DONTPEGBOTTOM)
		{
			zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
		}
		else
		{
			zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor);
		}
		break;
	case RF_RELMID:
		if (type==RENDERWALL_TOP || type==RENDERWALL_BOTTOM) return;
		if (line->flags & ML_DONTPEGBOTTOM)
		{
			zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor);
		}
		else
		{
			zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
		}
	}
	
	if (decal->RenderFlags & RF_FULLBRIGHT)
	{
		light = 255;
		rel = 0;
	}
	else
	{
		light = lightlevel;
		rel = rellight + getExtraLight();
	}
	
	int r = RPART(decal->AlphaColor);
	int g = GPART(decal->AlphaColor);
	int b = BPART(decal->AlphaColor);
	FColormap p = Colormap;
	
	if (glset.nocoloredspritelighting)
	{
		int v = (Colormap.LightColor.r * 77 + Colormap.LightColor.g*143 + Colormap.LightColor.b*35)/255;
		p.LightColor = PalEntry(p.colormap, v, v, v);
	}
	
	float red, green, blue;
	
	if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha)
	{
		loadAlpha = true;
		p.colormap=CM_SHADE;

		if (glset.lightmode != 8)
		{
			gl_GetLightColor(light, rel, &p, &red, &green, &blue);
		}
		else
		{
			gl_GetLightColor(lightlevel, rellight, &p, &red, &green, &blue);
		}
		
		if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && gl_light_sprites)
		{
			float result[3];
			fixed_t x, y;
			decal->GetXY(seg->sidedef, x, y);
			gl_GetSpriteLight(NULL, x, y, zpos, sub, Colormap.colormap-CM_DESAT0, result, line, side == line->sidedef[0]? 0:1);
			if (glset.lightmode != 8)
			{
				red = clamp<float>(result[0]+red, 0, 1.0f);
				green = clamp<float>(result[1]+green, 0, 1.0f);
				blue = clamp<float>(result[2]+blue, 0, 1.0f);
			}
			else
			{
				gl_RenderState.SetDynLight(result[0], result[1], result[2]);
			}
		}

		BYTE R = xs_RoundToInt(r * red);
		BYTE G = xs_RoundToInt(g * green);
		BYTE B = xs_RoundToInt(b * blue);

		gl_ModifyColor(R,G,B, Colormap.colormap);

		red = R/255.f;
		green = G/255.f;
		blue = B/255.f;
	}	
	else
	{
		loadAlpha = false;
		
		red = 1.f;
		green = 1.f;
		blue = 1.f;
	}
	
	
	a = FIXED2FLOAT(decal->Alpha);
	
	// now clip the decal to the actual polygon
	float decalwidth = tex->TextureWidth(GLUSE_PATCH)  * FIXED2FLOAT(decal->ScaleX);
	float decalheight= tex->TextureHeight(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleY);
	float decallefto = tex->GetLeftOffset(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleX);
	float decaltopo  = tex->GetTopOffset(GLUSE_PATCH)  * FIXED2FLOAT(decal->ScaleY);

	
	float leftedge = glseg.fracleft * side->TexelLength;
	float linelength = glseg.fracright * side->TexelLength - leftedge;

	// texel index of the decal's left edge
	float decalpixpos = (float)side->TexelLength * decal->LeftDistance / (1<<30) - (flipx? decalwidth-decallefto : decallefto) - leftedge;

	float left,right;
	float lefttex,righttex;

	// decal is off the left edge
	if (decalpixpos < 0)
	{
		left = 0;
		lefttex = -decalpixpos;
	}
	else
	{
		left = decalpixpos;
		lefttex = 0;
	}
	
	// decal is off the right edge
	if (decalpixpos + decalwidth > linelength)
	{
		right = linelength;
		righttex = right - decalpixpos;
	}
	else
	{
		right = decalpixpos + decalwidth;
		righttex = decalwidth;
	}
	if (right<=left) return;	// nothing to draw

	// one texture unit on the wall as vector
	float vx=(glseg.x2-glseg.x1)/linelength;
	float vy=(glseg.y2-glseg.y1)/linelength;
		
	dv[1].x=dv[0].x=glseg.x1+vx*left;
	dv[1].y=dv[0].y=glseg.y1+vy*left;

	dv[3].x=dv[2].x=glseg.x1+vx*right;
	dv[3].y=dv[2].y=glseg.y1+vy*right;
		
	zpos+= FRACUNIT*(flipy? decalheight-decaltopo : decaltopo);

	tex->BindPatch(p.colormap, decal->Translation);

	dv[1].z=dv[2].z = FIXED2FLOAT(zpos);
	dv[0].z=dv[3].z = dv[1].z - decalheight;
	dv[1].v=dv[2].v = tex->GetVT();

	dv[1].u=dv[0].u = tex->GetU(lefttex / FIXED2FLOAT(decal->ScaleX));
	dv[3].u=dv[2].u = tex->GetU(righttex / FIXED2FLOAT(decal->ScaleX));
	dv[0].v=dv[3].v = tex->GetVB();


	// now clip to the top plane
	float vzt=(ztop[1]-ztop[0])/linelength;
	float topleft=this->ztop[0]+vzt*left;
	float topright=this->ztop[0]+vzt*right;

	// completely below the wall
	if (topleft<dv[0].z && topright<dv[3].z) 
		return;

	if (topleft<dv[1].z || topright<dv[2].z)
	{
		// decal has to be clipped at the top
		// let texture clamping handle all extreme cases
		dv[1].v=(dv[1].z-topleft)/(dv[1].z-dv[0].z)*dv[0].v;
		dv[2].v=(dv[2].z-topright)/(dv[2].z-dv[3].z)*dv[3].v;
		dv[1].z=topleft;
		dv[2].z=topright;
	}

	// now clip to the bottom plane
	float vzb=(zbottom[1]-zbottom[0])/linelength;
	float bottomleft=this->zbottom[0]+vzb*left;
	float bottomright=this->zbottom[0]+vzb*right;

	// completely above the wall
	if (bottomleft>dv[1].z && bottomright>dv[2].z) 
		return;

	if (bottomleft>dv[0].z || bottomright>dv[3].z)
	{
		// decal has to be clipped at the bottom
		// let texture clamping handle all extreme cases
		dv[0].v=(dv[1].z-bottomleft)/(dv[1].z-dv[0].z)*(dv[0].v-dv[1].v) + dv[1].v;
		dv[3].v=(dv[2].z-bottomright)/(dv[2].z-dv[3].z)*(dv[3].v-dv[2].v) + dv[2].v;
		dv[0].z=bottomleft;
		dv[3].z=bottomright;
	}


	if (flipx)
	{
		float ur = tex->GetUR();
		for(i=0;i<4;i++) dv[i].u=ur-dv[i].u;
	}
	if (flipy)
	{
		float vb = tex->GetVB();
		for(i=0;i<4;i++) dv[i].v=vb-dv[i].v;
	}
	// fog is set once per wall in the calling function and not per decal!

	if (loadAlpha)
	{
		glColor4f(red, green, blue, a);

		if (glset.lightmode == 8)
		{
			if (gl_fixedcolormap)
				glVertexAttrib1f(VATTR_LIGHTLEVEL, 1.0);
			else
				glVertexAttrib1f(VATTR_LIGHTLEVEL, gl_CalcLightLevel(light, rel, false) / 255.0);
		}
	}
	else
	{
		if (glset.lightmode == 8)
		{
			gl_SetColor(light, rel, &p, a, extralight); // Korshun.
		}
		else
		{
			gl_SetColor(light, rel, &p, a);
		}
	}

	PalEntry fc = gl_RenderState.GetFogColor();
	if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One)
	{
		gl_RenderState.SetFog(0,-1);
	}


	gl_SetRenderStyle(decal->RenderStyle, false, false);

	// If srcalpha is one it looks better with a higher alpha threshold
	if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
	else gl_RenderState.AlphaFunc(GL_GREATER, 0.f);

	gl_RenderState.Apply();
	glBegin(GL_TRIANGLE_FAN);
	for(i=0;i<4;i++)
	{
		glTexCoord2f(dv[i].u,dv[i].v);
		glVertex3f(dv[i].x,dv[i].z,dv[i].y);
	}
	glEnd();
	rendered_decals++;
	gl_RenderState.SetFog(fc,-1);
	gl_RenderState.SetDynLight(0,0,0);
}
Exemple #22
0
bool gl_GetSpriteLight(AActor *self, fixed_t x, fixed_t y, fixed_t z, subsector_t * subsec, int desaturation, float * out, line_t *line, int side)
{
	ADynamicLight *light;
	float frac, lr, lg, lb;
	float radius;
	bool changed = false;
	
	out[0]=out[1]=out[2]=0;

	for(int j=0;j<2;j++)
	{
		// Go through both light lists
		FLightNode * node = subsec->lighthead[j];
		while (node)
		{
			light=node->lightsource;
			//if (!light->owned || light->target == NULL || light->target->IsVisibleToPlayer())
			{
				if (!(light->flags2&MF2_DORMANT) &&
					(!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self))
				{
					float dist = FVector3(FIXED2FLOAT(x - light->x), FIXED2FLOAT(y - light->y), FIXED2FLOAT(z - light->z)).Length();
					radius = light->GetRadius() * gl_lights_size;

					if (dist < radius)
					{
						frac = 1.0f - (dist / radius);

						if (frac > 0)
						{
							if (line != NULL)
							{
								if (P_PointOnLineSide(light->x, light->y, line) != side)
								{
									node = node->nextLight;
									continue;
								}
							}
							lr = light->GetRed() / 255.0f * gl_lights_intensity;
							lg = light->GetGreen() / 255.0f * gl_lights_intensity;
							lb = light->GetBlue() / 255.0f * gl_lights_intensity;
							if (light->IsSubtractive())
							{
								float bright = FVector3(lr, lg, lb).Length();
								FVector3 lightColor(lr, lg, lb);
								lr = (bright - lr) * -1;
								lg = (bright - lg) * -1;
								lb = (bright - lb) * -1;
							}

							out[0] += lr * frac;
							out[1] += lg * frac;
							out[2] += lb * frac;
							changed = true;
						}
					}
				}
			}
			node = node->nextLight;
		}
	}

	// Desaturate dynamic lighting if applicable
	if (desaturation>0 && desaturation<=CM_DESAT31)
	{
		float gray=(out[0]*77 + out[1]*143 + out[2]*37)/257;

		out[0]= (out[0]*(31-desaturation)+ gray*desaturation)/31;
		out[1]= (out[1]*(31-desaturation)+ gray*desaturation)/31;
		out[2]= (out[2]*(31-desaturation)+ gray*desaturation)/31;
	}
	return changed;
}
Exemple #23
0
void GLWall::SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2)
{
	if (fs->GetTexture(sector_t::floor)==skyflatnum)
	{
		if ((bs->special&0xff) == NoSkyDraw) return;
		FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::bottom));
		
		// For lower skies the normal logic only applies to walls with no lower texture!
		if (tex->UseType==FTexture::TEX_Null)
		{
			if (bs->GetTexture(sector_t::floor)==skyflatnum)
			{
				// if the back sector is closed the sky must be drawn!
				if (bs->ceilingplane.ZatPoint(v1) > bs->floorplane.ZatPoint(v1) ||
					bs->ceilingplane.ZatPoint(v2) > bs->floorplane.ZatPoint(v2))
						return;

			}
			else
			{
				// Special hack for Vrack2b
				if (bs->floorplane.ZatPoint(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy)) > FIXED2FLOAT(viewz)) return;
			}
		}
		zbottom[0]=zbottom[1]=-32768.0f;

		if ((tex && tex->UseType!=FTexture::TEX_Null) || bs->GetTexture(sector_t::floor)!=skyflatnum)
		{
			ztop[0]=zfloor[0];
			ztop[1]=zfloor[1];
		}
		else
		{
			ztop[0]=FIXED2FLOAT(bs->floorplane.ZatPoint(v1));
			ztop[1]=FIXED2FLOAT(bs->floorplane.ZatPoint(v2));
			flags|=GLWF_SKYHACK;	// mid textures on such lines need special treatment!
		}
	}
	else 
	{
		FPortal *pfront = fs->portals[sector_t::floor];
		FPortal *pback = bs->portals[sector_t::floor];
		float frontreflect = fs->GetReflect(sector_t::floor);
		if (frontreflect > 0)
		{
			float backreflect = bs->GetReflect(sector_t::floor);
			if (backreflect > 0 && bs->floorplane.d == fs->floorplane.d)
			{
				// Don't add intra-portal line to the portal.
				return;
			}
		}
		else if (pfront == NULL || pfront == pback)
		{
			return;
		}

		// stacked sectors
		fixed_t fsc1=fs->floorplane.ZatPoint(v1);
		fixed_t fsc2=fs->floorplane.ZatPoint(v2);

		zbottom[0]=zbottom[1]=-32768.0f;
		ztop[0]=FIXED2FLOAT(fsc1);
		ztop[1]=FIXED2FLOAT(fsc2);
	}

	SkyPlane(fs, sector_t::floor, true);
}
Exemple #24
0
void GLWall::SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2)
{
	if (fs->GetTexture(sector_t::ceiling)==skyflatnum)
	{
		if ((bs->special&0xff) == NoSkyDraw) return;
		if (bs->GetTexture(sector_t::ceiling)==skyflatnum) 
		{
			// if the back sector is closed the sky must be drawn!
			if (bs->ceilingplane.ZatPoint(v1) > bs->floorplane.ZatPoint(v1) ||
				bs->ceilingplane.ZatPoint(v2) > bs->floorplane.ZatPoint(v2) || bs->transdoor)
					return;

			// one more check for some ugly transparent door hacks
			if (bs->floorplane.a==0 && bs->floorplane.b==0 && fs->floorplane.a==0 && fs->floorplane.b==0)
			{
				if (bs->GetPlaneTexZ(sector_t::floor)==fs->GetPlaneTexZ(sector_t::floor)+FRACUNIT)
				{
					FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::bottom));
					if (!tex || tex->UseType==FTexture::TEX_Null) return;

					// very, very, very ugly special case (See Icarus MAP14)
					// It is VERY important that this is only done for a floor height difference of 1
					// or it will cause glitches elsewhere.
					tex = TexMan(seg->sidedef->GetTexture(side_t::mid));
					if (tex != NULL && !(seg->linedef->flags & ML_DONTPEGTOP) &&
						seg->sidedef->GetTextureYOffset(side_t::mid) > 0)
					{
						ztop[0]=ztop[1]=32768.0f;
						zbottom[0]=zbottom[1]= 
							FIXED2FLOAT(bs->ceilingplane.ZatPoint(v2) + seg->sidedef->GetTextureYOffset(side_t::mid));
						SkyPlane(fs, sector_t::ceiling, false);
						return;
					}
				}
			}
		}

		ztop[0]=ztop[1]=32768.0f;

		FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::top));
		if (bs->GetTexture(sector_t::ceiling) != skyflatnum)

		{
			zbottom[0]=zceil[0];
			zbottom[1]=zceil[1];
		}
		else
		{
			zbottom[0]=FIXED2FLOAT(bs->ceilingplane.ZatPoint(v1));
			zbottom[1]=FIXED2FLOAT(bs->ceilingplane.ZatPoint(v2));
			flags|=GLWF_SKYHACK;	// mid textures on such lines need special treatment!
		}
	}
	else 
	{
		FPortal *pfront = fs->portals[sector_t::ceiling];
		FPortal *pback = bs->portals[sector_t::ceiling];
		float frontreflect = fs->GetReflect(sector_t::ceiling);
		if (frontreflect > 0)
		{
			float backreflect = bs->GetReflect(sector_t::ceiling);
			if (backreflect > 0 && bs->ceilingplane.d == fs->ceilingplane.d)
			{
				// Don't add intra-portal line to the portal.
				return;
			}
		}
		else if (pfront == NULL || pfront == pback)
		{
			return;
		}

		// stacked sectors
		fixed_t fsc1=fs->ceilingplane.ZatPoint(v1);
		fixed_t fsc2=fs->ceilingplane.ZatPoint(v2);

		ztop[0]=ztop[1]=32768.0f;
		zbottom[0]=FIXED2FLOAT(fsc1);
		zbottom[1]=FIXED2FLOAT(fsc2);
	}

	SkyPlane(fs, sector_t::ceiling, true);
}
Exemple #25
0
//-----------------------------------------------------------------------------
//
// R_EnterMirror
//
//-----------------------------------------------------------------------------
void GLMirrorPortal::DrawContents()
{
	if (renderdepth>r_mirror_recursions) 
	{
		ClearScreen();
		return;
	}

	GLRenderer->mCurrentPortal = this;
	angle_t startang = viewangle;
	fixed_t startx = viewx;
	fixed_t starty = viewy;

	vertex_t *v1 = linedef->v1;
	vertex_t *v2 = linedef->v2;

	// Reflect the current view behind the mirror.
	if (linedef->dx == 0)
	{ 
		// vertical mirror
		viewx = v1->x - startx + v1->x;

		// Compensation for reendering inaccuracies
		if (startx<v1->x)  viewx -= FRACUNIT/2;
		else viewx += FRACUNIT/2;
	}
	else if (linedef->dy == 0)
	{ 
		// horizontal mirror
		viewy = v1->y - starty + v1->y;

		// Compensation for reendering inaccuracies
		if (starty<v1->y)  viewy -= FRACUNIT/2;
		else viewy += FRACUNIT/2;
	}
	else
	{ 
		// any mirror--use floats to avoid integer overflow. 
		// Use doubles to avoid losing precision which is very important here.

		double dx = FIXED2FLOAT(v2->x - v1->x);
		double dy = FIXED2FLOAT(v2->y - v1->y);
		double x1 = FIXED2FLOAT(v1->x);
		double y1 = FIXED2FLOAT(v1->y);
		double x = FIXED2FLOAT(startx);
		double y = FIXED2FLOAT(starty);

		// the above two cases catch len == 0
		double r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy);

		viewx = FLOAT2FIXED((x1 + r * dx)*2 - x);
		viewy = FLOAT2FIXED((y1 + r * dy)*2 - y);

		// Compensation for reendering inaccuracies
		FVector2 v(-dx, dy);
		v.MakeUnit();

		viewx+= FLOAT2FIXED(v[1] * renderdepth / 2);
		viewy+= FLOAT2FIXED(v[0] * renderdepth / 2);
	}
	// we cannot afford any imprecisions caused by R_PointToAngle2 here. They'd be visible as seams around the mirror.
	viewangle = 2*R_PointToAnglePrecise (linedef->v1->x, linedef->v1->y,
										linedef->v2->x, linedef->v2->y) - startang;

	GLRenderer->mViewActor = NULL;

	validcount++;

	MirrorFlag++;
	GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));

	clipper.Clear();

	angle_t af = GLRenderer->FrustumAngle();
	if (af<ANGLE_180) clipper.SafeAddClipRangeRealAngles(viewangle+af, viewangle-af);

	angle_t a2 = linedef->v1->GetClipAngle();
	angle_t a1 = linedef->v2->GetClipAngle();
	clipper.SafeAddClipRange(a1,a2);

	GLRenderer->DrawScene();

	MirrorFlag--;
}
void FNodeBuilder::Extract (FLevelLocals &level)
{
	int i;

	auto &outVerts = level.vertexes; 
	int vertCount = Vertices.Size ();
	outVerts.Alloc(vertCount);

	for (i = 0; i < vertCount; ++i)
	{
		outVerts[i].set(Vertices[i].x, Vertices[i].y);
	}

	auto &outSubs = level.subsectors;
	auto subCount = Subsectors.Size();
	outSubs.Alloc(subCount);
	memset(&outSubs[0], 0, subCount * sizeof(subsector_t));

	auto &outNodes = level.nodes;
	auto nodeCount = Nodes.Size ();
	outNodes.Alloc(nodeCount);

	memcpy (&outNodes[0], &Nodes[0], nodeCount*sizeof(node_t));
	for (unsigned i = 0; i < nodeCount; ++i)
	{
		D(Printf(PRINT_LOG, "Node %d:  Splitter[%08x,%08x] [%08x,%08x]\n", i,
			outNodes[i].x, outNodes[i].y, outNodes[i].dx, outNodes[i].dy));
		// Go backwards because on 64-bit systems, both of the intchildren are
		// inside the first in-game child.
		for (int j = 1; j >= 0; --j)
		{
			if (outNodes[i].intchildren[j] & 0x80000000)
			{
				D(Printf(PRINT_LOG, "  subsector %d\n", outNodes[i].intchildren[j] & 0x7FFFFFFF));
				outNodes[i].children[j] = (uint8_t *)(&outSubs[(outNodes[i].intchildren[j] & 0x7fffffff)]) + 1;
			}
			else
			{
				D(Printf(PRINT_LOG, "  node %d\n", outNodes[i].intchildren[j]));
				outNodes[i].children[j] = &outNodes[outNodes[i].intchildren[j]];
			}
		}
		for (int j = 0; j < 2; ++j)
		{
			for (int k = 0; k < 4; ++k)
			{
				outNodes[i].bbox[j][k] = FIXED2FLOAT(outNodes[i].nb_bbox[j][k]);
			}
		}
	}

	auto &outSegs = level.segs;
	if (GLNodes)
	{
		TArray<glseg_t> segs (Segs.Size()*5/4);

		for (unsigned i = 0; i < subCount; ++i)
		{
			uint32_t numsegs = CloseSubsector (segs, i, &outVerts[0]);
			outSubs[i].numlines = numsegs;
			outSubs[i].firstline = (seg_t *)(size_t)(segs.Size() - numsegs);
		}

		auto segCount = segs.Size ();
		outSegs.Alloc(segCount);

		for (unsigned i = 0; i < segCount; ++i)
		{
			outSegs[i] = *(seg_t *)&segs[i];

			if (segs[i].Partner != DWORD_MAX)
			{
				const uint32_t storedseg = Segs[segs[i].Partner].storedseg;
				outSegs[i].PartnerSeg = DWORD_MAX == storedseg ? nullptr : &outSegs[storedseg];
			}
			else
			{
				outSegs[i].PartnerSeg = nullptr;
			}
		}
	}
	else
	{
		memcpy (&outSubs[0], &Subsectors[0], subCount*sizeof(subsector_t));
		auto segCount = Segs.Size ();
		outSegs.Alloc(segCount);
		for (unsigned i = 0; i < segCount; ++i)
		{
			const FPrivSeg *org = &Segs[SegList[i].SegNum];
			seg_t *out = &outSegs[i];

			D(Printf(PRINT_LOG, "Seg %d: v1(%d) -> v2(%d)\n", i, org->v1, org->v2));

			out->v1 = &outVerts[org->v1];
			out->v2 = &outVerts[org->v2];
			out->backsector = org->backsector;
			out->frontsector = org->frontsector;
			out->linedef = Level.Lines + org->linedef;
			out->sidedef = Level.Sides + org->sidedef;
			out->PartnerSeg = nullptr;
		}
	}
	for (unsigned i = 0; i < subCount; ++i)
	{
		outSubs[i].firstline = &outSegs[(size_t)outSubs[i].firstline];
	}

	D(Printf("%i segs, %i nodes, %i subsectors\n", segCount, nodeCount, subCount));

	for (i = 0; i < Level.NumLines; ++i)
	{
		Level.Lines[i].v1 = &outVerts[(size_t)Level.Lines[i].v1];
		Level.Lines[i].v2 = &outVerts[(size_t)Level.Lines[i].v2];
	}
}
Exemple #27
0
//==========================================================================
//
// Draw the plane segment into the gap
//
//==========================================================================
void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling)
{
	GLSectorPlane plane;
	int lightlevel;
	FColormap Colormap;
	FMaterial * gltexture;

	plane.GetFromSector(sec, ceiling);

	gltexture=FMaterial::ValidateTexture(plane.texture, true);
	if (!gltexture) return;

	if (gl_fixedcolormap) 
	{
		Colormap.GetFixedColormap();
		lightlevel=255;
	}
	else
	{
		Colormap=sec->ColorMap;
		if (gltexture->tex->isFullbright())
		{
			Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff;
			lightlevel=255;
		}
		else lightlevel=abs(ceiling? sec->GetCeilingLight() : sec->GetFloorLight());
	}

	int rel = getExtraLight();
	gl_SetColor(lightlevel, rel, &Colormap, 1.0f);
	gl_SetFog(lightlevel, rel, &Colormap, false);
	gltexture->Bind(Colormap.colormap);

	float fviewx = FIXED2FLOAT(viewx);
	float fviewy = FIXED2FLOAT(viewy);
	float fviewz = FIXED2FLOAT(viewz);

	gl_RenderState.Apply();

	bool pushed = gl_SetPlaneTextureRotation(&plane, gltexture);

	glBegin(GL_TRIANGLE_FAN);
	float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz);
	float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz);

	float px1 = fviewx + prj_fac1 * (ws->x1-fviewx);
	float py1 = fviewy + prj_fac1 * (ws->y1-fviewy);

	float px2 = fviewx + prj_fac2 * (ws->x1-fviewx);
	float py2 = fviewy + prj_fac2 * (ws->y1-fviewy);

	float px3 = fviewx + prj_fac2 * (ws->x2-fviewx);
	float py3 = fviewy + prj_fac2 * (ws->y2-fviewy);

	float px4 = fviewx + prj_fac1 * (ws->x2-fviewx);
	float py4 = fviewy + prj_fac1 * (ws->y2-fviewy);

	glTexCoord2f(px1 / 64, -py1 / 64);
	glVertex3f(px1, planez, py1);

	glTexCoord2f(px2 / 64, -py2 / 64);
	glVertex3f(px2, planez, py2);

	glTexCoord2f(px3 / 64, -py3 / 64);
	glVertex3f(px3, planez, py3);

	glTexCoord2f(px4 / 64, -py4 / 64);
	glVertex3f(px4, planez, py4);

	glEnd();

	if (pushed)
	{
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
	}
}
Exemple #28
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);
}
Exemple #29
0
bool APathFollower::Interpolate ()
{
	fixed_t dx = 0, dy = 0, dz = 0;

	if ((args[2] & 8) && Time > 0.f)
	{
		dx = x;
		dy = y;
		dz = z;
	}

	if (CurrNode->Next==NULL) return false;

	UnlinkFromWorld ();
	if (args[2] & 1)
	{	// linear
		x = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->x), FIXED2FLOAT(CurrNode->Next->x)));
		y = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->y), FIXED2FLOAT(CurrNode->Next->y)));
		z = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->z), FIXED2FLOAT(CurrNode->Next->z)));
	}
	else
	{	// spline
		if (CurrNode->Next->Next==NULL) return false;

		x = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->x), FIXED2FLOAT(CurrNode->x),
								FIXED2FLOAT(CurrNode->Next->x), FIXED2FLOAT(CurrNode->Next->Next->x)));
		y = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->y), FIXED2FLOAT(CurrNode->y),
								FIXED2FLOAT(CurrNode->Next->y), FIXED2FLOAT(CurrNode->Next->Next->y)));
		z = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->z), FIXED2FLOAT(CurrNode->z),
								FIXED2FLOAT(CurrNode->Next->z), FIXED2FLOAT(CurrNode->Next->Next->z)));
	}
	LinkToWorld ();

	if (args[2] & 6)
	{
		if (args[2] & 8)
		{
			if (args[2] & 1)
			{ // linear
				dx = CurrNode->Next->x - CurrNode->x;
				dy = CurrNode->Next->y - CurrNode->y;
				dz = CurrNode->Next->z - CurrNode->z;
			}
			else if (Time > 0.f)
			{ // spline
				dx = x - dx;
				dy = y - dy;
				dz = z - dz;
			}
			else
			{
				int realarg = args[2];
				args[2] &= ~(2|4|8);
				Time += 0.1f;
				dx = x;
				dy = y;
				dz = z;
				Interpolate ();
				Time -= 0.1f;
				args[2] = realarg;
				dx = x - dx;
				dy = y - dy;
				dz = z - dz;
				x -= dx;
				y -= dy;
				z -= dz;
			}
			if (args[2] & 2)
			{ // adjust yaw
				angle = R_PointToAngle2 (0, 0, dx, dy);
			}
			if (args[2] & 4)
			{ // adjust pitch; use floats for precision
				float fdx = FIXED2FLOAT(dx);
				float fdy = FIXED2FLOAT(dy);
				float fdz = FIXED2FLOAT(-dz);
				float dist = (float)sqrt (fdx*fdx + fdy*fdy);
				float ang = dist != 0.f ? (float)atan2 (fdz, dist) : 0;
				pitch = (angle_t)(ang * 2147483648.f / PI);
			}
		}
		else
		{
			if (args[2] & 2)
			{ // interpolate angle
				float angle1 = (float)CurrNode->angle;
				float angle2 = (float)CurrNode->Next->angle;
				if (angle2 - angle1 <= -2147483648.f)
				{
					float lerped = Lerp (angle1, angle2 + 4294967296.f);
					if (lerped >= 4294967296.f)
					{
						angle = (angle_t)(lerped - 4294967296.f);
					}
					else
					{
						angle = (angle_t)lerped;
					}
				}
				else if (angle2 - angle1 >= 2147483648.f)
				{
					float lerped = Lerp (angle1, angle2 - 4294967296.f);
					if (lerped < 0.f)
					{
						angle = (angle_t)(lerped + 4294967296.f);
					}
					else
					{
						angle = (angle_t)lerped;
					}
				}
				else
				{
					angle = (angle_t)Lerp (angle1, angle2);
				}
			}
			if (args[2] & 1)
			{ // linear
				if (args[2] & 4)
				{ // interpolate pitch
					pitch = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->pitch), FIXED2FLOAT(CurrNode->Next->pitch)));
				}
			}
			else
			{ // spline
				if (args[2] & 4)
				{ // interpolate pitch
					pitch = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->pitch), FIXED2FLOAT(CurrNode->pitch),
						FIXED2FLOAT(CurrNode->Next->pitch), FIXED2FLOAT(CurrNode->Next->Next->pitch)));
				}
			}
		}
	}

	return true;
}
Exemple #30
0
void FGLRenderer::DrawTexture(FTexture *img, DCanvas::DrawParms &parms)
{
	double xscale = parms.destwidth / parms.texwidth;
	double yscale = parms.destheight / parms.texheight;
	double x = parms.x - parms.left * xscale;
	double y = parms.y - parms.top * yscale;
	double w = parms.destwidth;
	double h = parms.destheight;
	float u1, v1, u2, v2, r, g, b;
	float light = 1.f;

	FMaterial * gltex = FMaterial::ValidateTexture(img);

	const PatchTextureInfo * pti;

	if (parms.colorOverlay)
	{
		// Right now there's only black. Should be implemented properly later
		light = 1.f - APART(parms.colorOverlay)/255.f;
	}

	if (!img->bHasCanvas)
	{
		if (!parms.alphaChannel) 
		{
			int translation = 0;
			if (parms.remap != NULL && !parms.remap->Inactive)
			{
				GLTranslationPalette * pal = static_cast<GLTranslationPalette*>(parms.remap->GetNative());
				if (pal) translation = -pal->GetIndex();
			}
			pti = gltex->BindPatch(CM_DEFAULT, translation);
		}
		else 
		{
			// This is an alpha texture
			pti = gltex->BindPatch(CM_SHADE, 0);
		}

		if (!pti) return;

		u1 = pti->GetUL();
		v1 = pti->GetVT();
		u2 = pti->GetUR();
		v2 = pti->GetVB();
	}
	else
	{
		gltex->Bind(CM_DEFAULT, 0, 0);
		u2=1.f;
		v2=-1.f;
		u1 = v1 = 0.f;
		gl_RenderState.SetTextureMode(TM_OPAQUE);
	}
	
	if (parms.flipX)
	{
		float temp = u1;
		u1 = u2;
		u2 = temp;
	}
	

	if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
	{
		x += parms.windowleft * xscale;
		w -= (parms.texwidth - parms.windowright + parms.windowleft) * xscale;

		u1 = float(u1 + parms.windowleft / parms.texwidth);
		u2 = float(u2 - (parms.texwidth - parms.windowright) / parms.texwidth);
	}

	if (parms.style.Flags & STYLEF_ColorIsFixed)
	{
		r = RPART(parms.fillcolor)/255.0f;
		g = GPART(parms.fillcolor)/255.0f;
		b = BPART(parms.fillcolor)/255.0f;
	}
	else
	{
		r = g = b = light;
	}
	
	// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
	int btm = (SCREENHEIGHT - screen->GetHeight()) / 2;
	btm = SCREENHEIGHT - btm;

	gl.Enable(GL_SCISSOR_TEST);
	int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight()-screen->GetHeight())/2;
	gl.Scissor(parms.lclip, btm - parms.dclip + space, parms.rclip - parms.lclip, parms.dclip - parms.uclip);
	
	gl_SetRenderStyle(parms.style, !parms.masked, false);
	if (img->bHasCanvas)
	{
		gl_RenderState.SetTextureMode(TM_OPAQUE);
	}

	gl.Color4f(r, g, b, FIXED2FLOAT(parms.alpha));
	
	gl_RenderState.EnableAlphaTest(false);
	gl_RenderState.Apply();
	gl.Begin(GL_TRIANGLE_STRIP);
	gl.TexCoord2f(u1, v1);
	glVertex2d(x, y);
	gl.TexCoord2f(u1, v2);
	glVertex2d(x, y + h);
	gl.TexCoord2f(u2, v1);
	glVertex2d(x + w, y);
	gl.TexCoord2f(u2, v2);
	glVertex2d(x + w, y + h);
	gl.End();
	gl_RenderState.EnableAlphaTest(true);
	
	gl.Scissor(0, 0, screen->GetWidth(), screen->GetHeight());
	gl.Disable(GL_SCISSOR_TEST);
	gl_RenderState.SetTextureMode(TM_MODULATE);
	gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	gl_RenderState.BlendEquation(GL_FUNC_ADD);
}