Beispiel #1
0
void R_DeriveFacePlanes( srfTriangles_t *tri ) {
	Plane *	planes;

	if ( !tri->facePlanes ) {
		R_AllocStaticTriSurfPlanes( tri, tri->numIndices );
	}
	planes = tri->facePlanes;

	for ( int i = 0; i < tri->numIndices; i+= 3, planes++ ) {
		int		i1, i2, i3;
		Vec3	d1, d2, normal;
		Vec3	*v1, *v2, *v3;

		i1 = tri->indices[i + 0];
		i2 = tri->indices[i + 1];
		i3 = tri->indices[i + 2];

		v1 = &tri->verts[i1].xyz;
		v2 = &tri->verts[i2].xyz;
		v3 = &tri->verts[i3].xyz;

		d1[0] = v2->x - v1->x;
		d1[1] = v2->y - v1->y;
		d1[2] = v2->z - v1->z;

		d2[0] = v3->x - v1->x;
		d2[1] = v3->y - v1->y;
		d2[2] = v3->z - v1->z;

		normal[0] = d2.y * d1.z - d2.z * d1.y;
		normal[1] = d2.z * d1.x - d2.x * d1.z;
		normal[2] = d2.x * d1.y - d2.y * d1.x;

		float sqrLength, invLength;

		sqrLength = normal.x * normal.x + normal.y * normal.y + normal.z * normal.z;
		invLength = idMath::RSqrt( sqrLength );

		(*planes)[0] = normal[0] * invLength;
		(*planes)[1] = normal[1] * invLength;
		(*planes)[2] = normal[2] * invLength;

		planes->FitThroughPoint( *v1 );
	}

	tri->facePlanesCalculated = true;
}
Beispiel #2
0
/*
====================
idRenderModelPrt::InstantiateDynamicModel
====================
*/
idRenderModel *idRenderModelPrt::InstantiateDynamicModel( const struct renderEntity_s *renderEntity, const struct viewDef_s *viewDef, idRenderModel *cachedModel ) {
	idRenderModelStatic	*staticModel;

	if ( cachedModel && !r_useCachedDynamicModels.GetBool() ) {
		delete cachedModel;
		cachedModel = NULL;
	}

	// this may be triggered by a model trace or other non-view related source, to which we should look like an empty model
	if ( !renderEntity || !viewDef ) {
		delete cachedModel;
		return NULL;
	}
	else if ( r_skipParticles.GetBool() ) {
		delete cachedModel;
		return NULL;
	}

	/*
	// if the entire system has faded out
	if ( renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] && viewDef->renderView.time * 0.001f >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] ) {
		delete cachedModel;
		return NULL;
	}
	*/

	else if ( cachedModel ) {
		assert( dynamic_cast<idRenderModelStatic *>(cachedModel) != NULL );
		assert( idStr::Icmp( cachedModel->Name(), parametricParticle_SnapshotName ) == 0 );

		staticModel = static_cast<idRenderModelStatic *>(cachedModel);
	}
	else {
		staticModel = new idRenderModelStatic;
		staticModel->InitEmpty( parametricParticle_SnapshotName );
	}

	particleGen_t g;

	g.renderEnt = renderEntity;
	g.renderView = &viewDef->renderView;
	g.origin.Zero();
	g.axis.Identity();

	for ( int stageNum = 0; stageNum < particleSystem->stages.Num(); stageNum++ ) {
		idParticleStage *stage = particleSystem->stages[stageNum];

		if ( !stage->material || !stage->cycleMsec ) {
			continue;
		}
		else if ( stage->hidden ) {		// just for gui particle editor use
			staticModel->DeleteSurfaceWithId( stageNum );
			continue;
		}

		idRandom steppingRandom, steppingRandom2;

		const int stageAge = g.renderView->time + (renderEntity->shaderParms[SHADERPARM_TIMEOFFSET] - stage->timeOffset) * 1000;
		const int stageCycle = stageAge / stage->cycleMsec;

		// some particles will be in this cycle, some will be in the previous cycle
		steppingRandom.SetSeed ( (( stageCycle << 10 )     & idRandom::MAX_RAND) ^ (int)( renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND ) );
		steppingRandom2.SetSeed( (( (stageCycle-1) << 10 ) & idRandom::MAX_RAND) ^ (int)( renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND ) );

		const int	count = stage->totalParticles * stage->NumQuadsPerParticle();

		int surfaceNum = 0;
		modelSurface_t *surf;

		if ( staticModel->FindSurfaceWithId( stageNum, surfaceNum ) ) {
			surf = &staticModel->surfaces[surfaceNum];
			R_FreeStaticTriSurfVertexCaches( surf->geometry );
		} else {
			surf = &staticModel->surfaces.Alloc();
			surf->id = stageNum;
			surf->shader = stage->material;
			surf->geometry = R_AllocStaticTriSurf();
			R_AllocStaticTriSurfVerts( surf->geometry, 4 * count );
			R_AllocStaticTriSurfIndexes( surf->geometry, 6 * count );
			R_AllocStaticTriSurfPlanes( surf->geometry, 6 * count );
		}

		int numVerts = 0;
		idDrawVert *verts = surf->geometry->verts;

		for ( int index = 0; index < stage->totalParticles; index++ ) {
			g.index = index;

			// calculate local age for this index 
			//const int bunchOffset = (index * 1000 * stage->particleLife * stage->spawnBunching) / stage->totalParticles;
			//const int particleAge = stageAge - bunchOffset
			const int particleAge = stageAge - ((index * 1000 * stage->particleLife * stage->spawnBunching) / stage->totalParticles);
			const int particleCycle = particleAge / stage->cycleMsec;
			
			// before the particleSystem has spawned or
			// cycled systems will only run cycle times
			if ( particleCycle < 0 || ( stage->cycles && particleCycle >= stage->cycles ) ) {
				continue;
			}
			
			const int inCycleTime = particleAge - particleCycle * stage->cycleMsec;
			
			if ( renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] && 
				g.renderView->time - inCycleTime >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] * 1000 ) {
				// don't fire any more particles
				continue;
			}

			// supress particles before or after the age clamp
			g.frac = (float)inCycleTime / ( stage->particleLife * 1000 );
			if ( g.frac < 0.0f || g.frac > 1.0f) {
				// < 0.0f ; yet to be spawned
				// > 1.0f ; particle is in the deadTime band
				continue;
			} else {
				g.age = g.frac * stage->particleLife;
			}

			// bump the random
			steppingRandom.RandomInt();
			steppingRandom2.RandomInt();

			if ( particleCycle == stageCycle ) {
				g.random = steppingRandom;
			} else {
				g.random = steppingRandom2;
			}

			// this is needed so aimed particles can calculate origins at different times
			g.originalRandom = g.random;

			// if the particle doesn't get drawn because it is faded out or beyond a kill region, don't increment the verts
			numVerts += stage->CreateParticle( &g, verts + numVerts );
		}

		// numVerts must be a multiple of 4
		assert( ( numVerts & 3 ) == 0 && numVerts <= 4 * count );

		// build the indexes
		int	numIndexes = 0;
		glIndex_t *indexes = surf->geometry->indexes;
		for ( int i = 0; i < numVerts; i += 4 ) {
			indexes[numIndexes+0] = i;
			indexes[numIndexes+1] = i+2;
			indexes[numIndexes+2] = i+3;
			indexes[numIndexes+3] = i;
			indexes[numIndexes+4] = i+3;
			indexes[numIndexes+5] = i+1;
			numIndexes += 6;
		}

		surf->geometry->tangentsCalculated = false;
		surf->geometry->facePlanesCalculated = false;
		surf->geometry->numVerts = numVerts;
		surf->geometry->numIndexes = numIndexes;
		surf->geometry->bounds = stage->bounds;		// just always draw the particles
	}

	return staticModel;
}