Exemple #1
0
//
// R_SortPolyObjects
//
// haleyjd 03/03/06: Here's the REAL meat of Eternity's polyobject system.
// Hexen just figured this was impossible, but as mentioned in polyobj.c,
// it is perfectly doable within the confines of the BSP tree. Polyobjects
// must be sorted to draw in DOOM's front-to-back order within individual
// subsectors. This is a modified version of R_SortVisSprites.
//
void R_SortPolyObjects(subsector_t *sub)
{
	if (numpolys)
	{
		polyobj_t *po;
		INT32 i = 0;

		// allocate twice the number needed to minimize allocations
		if (num_po_ptrs < numpolys*2)
		{
			// use free instead realloc since faster (thanks Lee ^_^)
			free(po_ptrs);
			po_ptrs = malloc((num_po_ptrs = numpolys*2)
				* sizeof(*po_ptrs));
		}

		po = sub->polyList;

		while (po)
		{
			po->zdist = R_PointToDist2(viewx, viewy,
				po->centerPt.x, po->centerPt.y);
			po_ptrs[i++] = po;
			po = (polyobj_t *)(po->link.next);
		}

		// the polyobjects are NOT in any particular order, so use qsort
		// 03/10/06: only bother if there are actually polys to sort
		if (numpolys >= 2)
		{
			qsort(po_ptrs, numpolys, sizeof(polyobj_t *),
				R_PolyobjCompare);
		}
	}
}
Exemple #2
0
//
// R_PolysegCompare
//
// Callback for qsort to sort the segs of a polyobject. Returns such that the
// closer one is sorted first. I sure hope this doesn't break anything. -Red
//
static int R_PolysegCompare(const void *p1, const void *p2)
{
	const seg_t *seg1 = *(const seg_t * const *)p1;
	const seg_t *seg2 = *(const seg_t * const *)p2;
	fixed_t dist1v1, dist1v2, dist2v1, dist2v2;

	// TODO might be a better way to get distance?
#define pdist(x, y) (FixedMul(R_PointToDist(x, y), FINECOSINE((R_PointToAngle(x, y)-viewangle)>>ANGLETOFINESHIFT))+0xFFFFFFF)
#define vxdist(v) pdist(v->x, v->y)

	dist1v1 = vxdist(seg1->v1);
	dist1v2 = vxdist(seg1->v2);
	dist2v1 = vxdist(seg2->v1);
	dist2v2 = vxdist(seg2->v2);

	if (min(dist1v1, dist1v2) != min(dist2v1, dist2v2))
		return min(dist1v1, dist1v2) - min(dist2v1, dist2v2);

	{ // That didn't work, so now let's try this.......
		fixed_t delta1, delta2, x1, y1, x2, y2;
		vertex_t *near1, *near2, *far1, *far2; // wherever you are~

		delta1 = R_PointToDist2(seg1->v1->x, seg1->v1->y, seg1->v2->x, seg1->v2->y);
		delta2 = R_PointToDist2(seg2->v1->x, seg2->v1->y, seg2->v2->x, seg2->v2->y);

		delta1 = FixedDiv(128<<FRACBITS, delta1);
		delta2 = FixedDiv(128<<FRACBITS, delta2);

		if (dist1v1 < dist1v2)
		{
			near1 = seg1->v1;
			far1 = seg1->v2;
		}
		else
		{
			near1 = seg1->v2;
			far1 = seg1->v1;
		}

		if (dist2v1 < dist2v2)
		{
			near2 = seg2->v1;
			far2 = seg2->v2;
		}
		else
		{
			near2 = seg2->v2;
			far2 = seg2->v1;
		}

		x1 = near1->x + FixedMul(far1->x-near1->x, delta1);
		y1 = near1->y + FixedMul(far1->y-near1->y, delta1);

		x2 = near2->x + FixedMul(far2->x-near2->x, delta2);
		y2 = near2->y + FixedMul(far2->y-near2->y, delta2);

		return pdist(x1, y1)-pdist(x2, y2);
	}
#undef vxdist
#undef pdist
}
void GL_RenderPoly(gl_poly_t *poly)
{
   FAnimDef *anim = NULL;
//   float alpha;
  // unsigned short tex1, tex2, curFrame;

   if (!poly->initialized) return;

   GL_BindArrays(poly);

   if (MaskSkybox)
   {
      glColor4f(1.f, 1.f, 1.f, 1.f);
      textureList.BindGLTexture(0);
      glDrawArrays(GL_TRIANGLE_FAN, 0, poly->numPts);
   }
   else
   {
      GL_SetupFog(poly->lightLevel, poly->fogR, poly->fogG, poly->fogB);

      // non-masked, so disable transparency
      if (!DrawingDeferredLines && poly->a == 1.f)
      {
         glDisable(GL_BLEND);
      }

      if (poly->doomTex > 0)
      {
         if (gl_blend_animations && gl_texture && !gl_wireframe && !textureList.IsTransparent())
         {
            anim = GL_GetAnimForLump(poly->doomTex);
         }
      }
      else
      {
         return;
      }

		glMatrixMode(GL_TEXTURE);
		glLoadIdentity();
		glScalef(poly->scaleX, poly->scaleY, 1.f);
		glTranslatef(poly->offX, poly->offY, 0.f);
		glRotatef(poly->rot, 0.f, 0.f, 1.f);
		glMatrixMode(GL_MODELVIEW);
		glColor4f(poly->r, poly->g, poly->b, poly->a);
		glDrawArrays(GL_TRIANGLE_FAN, 0, poly->numPts);

		glEnable(GL_BLEND);

      glMatrixMode(GL_TEXTURE);
      glLoadIdentity();
      glMatrixMode(GL_MODELVIEW);
   }

   numTris += poly->numPts - 2;

   if (r_fogboundary && poly->isFogBoundary)
   {
#if 0
      // draw poly again with depth-dependent alpha edges
      // note that fog boundaries are always walls, so they're always quads
      float a1, a2;
      fixed_t x, y, dist;
      int i;

      glDisable(GL_TEXTURE_2D);
      glAlphaFunc(GL_GREATER, 0.f);

      x = (fixed_t)(-poly->vertices[3] * MAP_SCALE);
      y = (fixed_t)(poly->vertices[5] * MAP_SCALE);
      dist = R_PointToDist2(x, y);
      a1 = dist / 384.f * INV_FRACUNIT;

      x = (fixed_t)(-poly->vertices[6] * MAP_SCALE);
      y = (fixed_t)(poly->vertices[8] * MAP_SCALE);
      dist = R_PointToDist2(x, y);
      a2 = dist / 384.f * INV_FRACUNIT;

      a1 *= 0.75f * byte2float[poly->fbLightLevel];
      a2 *= 0.75f * byte2float[poly->fbLightLevel];

      //a1 = 0.f;
      //a2 = 1.f;

      glColor4f(byte2float[poly->fbR] * byte2float[poly->fbLightLevel], byte2float[poly->fbG] * byte2float[poly->fbLightLevel], byte2float[poly->fbB] * byte2float[poly->fbLightLevel], a1 * a1);
      glBegin(GL_TRIANGLE_FAN);
      for (i = 0; i < poly->numPts; i++)
      {
         if (i == poly->numPts / 2)
         {
            glColor4f(byte2float[poly->fbR] * byte2float[poly->fbLightLevel], byte2float[poly->fbG] * byte2float[poly->fbLightLevel], byte2float[poly->fbB] * byte2float[poly->fbLightLevel], a2 * a2);
         }
         glVertex3fv(&poly->vertices[i * 3]);
      }
      glEnd();

      glEnable(GL_TEXTURE_2D);
#endif
   }

   // all this really does is potentially unlocks the vertex arrays
   GL_UnbindArrays(poly);
}
Exemple #4
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);
}