//=========================================================================== // Demo particle system (fountain). //=========================================================================== static void add_particles_fountain (WalkTest* Sys, iSector* sector, char* matname, int num, const csVector3& origin) { iEngine* engine = Sys->Engine; // First check if the material exists. iMaterialWrapper* mat = engine->GetMaterialList ()->FindByName (matname); if (!mat) { Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Can't find material '%s'!", matname); return; } csRef<iMeshFactoryWrapper> mfw = engine->CreateMeshFactory ( "crystalspace.mesh.object.particles", "fountain"); if (!mfw) return; csRef<iMeshWrapper> exp = engine->CreateMeshWrapper (mfw, "custom fountain", sector, origin); exp->SetZBufMode(CS_ZBUF_TEST); exp->GetMeshObject()->SetMixMode (CS_FX_ADD); exp->GetMeshObject()->SetMaterialWrapper (mat); csRef<iParticleBuiltinEmitterFactory> emit_factory = csLoadPluginCheck<iParticleBuiltinEmitterFactory> ( Sys->object_reg, "crystalspace.mesh.object.particles.emitter", false); csRef<iParticleBuiltinEffectorFactory> eff_factory = csLoadPluginCheck<iParticleBuiltinEffectorFactory> ( Sys->object_reg, "crystalspace.mesh.object.particles.effector", false); csRef<iParticleBuiltinEmitterCone> conemit = emit_factory->CreateCone (); float velocity = 3.0f; float seconds_to_live = 1.5f; conemit->SetExtent (csVector3 (0, 0.5f, 0)); conemit->SetConeAngle (0.3f); conemit->SetParticlePlacement (CS_PARTICLE_BUILTIN_VOLUME); conemit->SetEmissionRate (float (num) / seconds_to_live); conemit->SetInitialMass (8.0f, 10.0f); conemit->SetInitialTTL (seconds_to_live, seconds_to_live); conemit->SetInitialVelocity (csVector3 (0, velocity, 0), csVector3 (0)); csRef<iParticleBuiltinEffectorLinColor> lincol = eff_factory-> CreateLinColor (); lincol->AddColor (csColor4 (0.25f, 0.35f, 0.55f, 1), seconds_to_live); csRef<iParticleBuiltinEffectorForce> force = eff_factory-> CreateForce (); force->SetAcceleration (csVector3 (0.0f, -3.0f, 0.0f)); csRef<iParticleSystem> partstate = scfQueryInterface<iParticleSystem> (exp->GetMeshObject ()); partstate->SetParticleSize (csVector2 (0.1f, 0.1f)); partstate->AddEmitter (conemit); partstate->AddEffector (lincol); partstate->AddEffector (force); }
void SimpleStaticLighter::ShineLights (iMeshWrapper* mesh, iEngine* engine, int maxlights, ShadowType shadow_type) { iMovable* movable = mesh->GetMovable (); if (!movable->InSector ()) return; // No movable, do nothing. const csBox3& world_box = mesh->GetWorldBoundingBox (); CS_ALLOC_STACK_ARRAY (iLight*, lights, maxlights); size_t num = engine->GetNearbyLights (movable->GetSectors ()->Get (0), world_box, lights, maxlights); if (num == 0) { ConstantColor (mesh, csColor4 (0, 0, 0, 0)); return; } if (num == 1) { ShineLight (mesh, lights[0], shadow_type); return; } iMeshFactoryWrapper* meshfact = mesh->GetFactory (); if (!meshfact) return; csRef<iGeneralFactoryState> fact_state = scfQueryInterface< iGeneralFactoryState> (meshfact->GetMeshObjectFactory ()); if (!fact_state) return; // Not a mesh we recognize. size_t count = fact_state->GetVertexCount (); csRef<iRenderBuffer> rbuf = csRenderBuffer::CreateRenderBuffer ( count, CS_BUF_STATIC, CS_BUFCOMP_FLOAT, 4); CS_ALLOC_STACK_ARRAY (csColor4, colors, count); size_t l; for (l = 0 ; l < num ; l++) { iLight* light = lights[l]; CalculateLighting (mesh, fact_state, light, shadow_type, colors, l == 0); } rbuf->CopyInto (colors, count); csRef<iGeneralMeshState> state = scfQueryInterface<iGeneralMeshState> (mesh->GetMeshObject ()); state->AddRenderBuffer ("static color", rbuf); mesh->GetFlags().Set (CS_ENTITY_STATICLIT); }
void SimpleStaticLighter::CalculateLighting (iMeshWrapper* mesh, iGeneralFactoryState* fact_state, iLight* light, ShadowType shadow_type, csColor4* colors, bool init) { size_t count = fact_state->GetVertexCount (); size_t i; csVector3 center = light->GetMovable ()->GetFullTransform ().GetOrigin (); iSector* light_sector = light->GetMovable ()->GetSectors ()->Get (0); csReversibleTransform mesh_trans = mesh->GetMovable ()->GetFullTransform (); if (shadow_type == CS_SHADOW_CENTER) { csSectorHitBeamResult rc = light_sector->HitBeamPortals (center, mesh_trans.GetOrigin ()); if (rc.mesh != 0 && rc.mesh != mesh) { // Shadow. if (init) for (i = 0 ; i < count ; i++) colors[i] = csColor4 (0, 0, 0, 0); return; } } else if (shadow_type == CS_SHADOW_BOUNDINGBOX) { const csBox3& world_box = mesh->GetWorldBoundingBox (); bool shadowed = true; for (int j = 0 ; shadowed && j < 8 ; j++) { csSectorHitBeamResult rc = light_sector->HitBeamPortals (center, world_box.GetCorner (j)); if (rc.mesh == 0 || rc.mesh == mesh) shadowed = false; } if (shadowed) { // Shadow. if (init) for (i = 0 ; i < count ; i++) colors[i] = csColor4 (0, 0, 0, 0); return; } } // Shaders multiply by 2. So we need to divide by 2 here. csColor color = 0.5f * light->GetColor (); float sqcutoff = light->GetCutoffDistance (); sqcutoff *= sqcutoff; csVector3* verts = fact_state->GetVertices (); csVector3* normals = fact_state->GetNormals (); if (shadow_type != CS_SHADOW_FULL) { // Transform light to object space here since we don't have to do // full accurate shadows anyway. center = mesh_trans.Other2This (center); for (i = 0 ; i < count ; i++) { csVector3 relpos = center-verts[i]; float dist = relpos * relpos; bool dark = init; if (dist < sqcutoff) { dist = sqrt (dist); float bright = light->GetBrightnessAtDistance (dist); bright *= (normals[i] * relpos) / relpos.Norm (); if (bright > SMALL_EPSILON) { if (init) colors[i] = color * bright; else colors[i] += color * bright; colors[i].Clamp (1.0, 1.0, 1.0); dark = false; } } if (dark) colors[i].Set (0, 0, 0, 0); } } else { // With full shadows we need world space coordinates to be // able to check the shadow beams. bool mesh_trans_identity = mesh_trans.IsIdentity (); for (i = 0 ; i < count ; i++) { csVector3 vworld; if (mesh_trans_identity) vworld = verts[i]; else vworld = mesh_trans.This2Other (verts[i]); csVector3 relpos = center-vworld; float dist = relpos * relpos; bool dark = init; if (dist < sqcutoff) { dist = sqrt (dist); float bright = light->GetBrightnessAtDistance (dist); bright *= (normals[i] * relpos) / relpos.Norm (); if (bright > SMALL_EPSILON) { csSectorHitBeamResult rc = light_sector->HitBeamPortals (center, vworld); if (rc.mesh == 0 || rc.mesh == mesh) { if (init) colors[i] = color * bright; else colors[i] += color * bright; colors[i].Clamp (1.0, 1.0, 1.0); dark = false; } } } if (dark) colors[i].Set (0, 0, 0, 0); } } }
//=========================================================================== // Demo particle system (rain). //=========================================================================== static void add_particles_rain (WalkTest* Sys, iSector* sector, char* matname, int num, float speed, bool do_camera) { iEngine* engine = Sys->Engine; // First check if the material exists. iMaterialWrapper* mat = engine->GetMaterialList ()->FindByName (matname); if (!mat) { Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Can't find material '%s' in memory!", matname); return; } csBox3 bbox; if (do_camera) bbox.Set (-5, -5, -5, 5, 5, 5); else sector->CalculateSectorBBox (bbox, true); csRef<iMeshFactoryWrapper> mfw = engine->CreateMeshFactory ( "crystalspace.mesh.object.particles", "rain"); if (!mfw) return; csRef<iMeshWrapper> exp = engine->CreateMeshWrapper (mfw, "custom rain", sector, csVector3 (0, 0, 0)); if (do_camera) { iEngine* e = Sys->Engine; int c = e->GetAlphaRenderPriority (); exp->GetFlags ().Set (CS_ENTITY_CAMERA); exp->SetRenderPriority (c); } exp->SetZBufMode(CS_ZBUF_TEST); exp->GetMeshObject()->SetMixMode (CS_FX_ADD); exp->GetMeshObject()->SetMaterialWrapper (mat); csRef<iParticleBuiltinEmitterFactory> emit_factory = csLoadPluginCheck<iParticleBuiltinEmitterFactory> ( Sys->object_reg, "crystalspace.mesh.object.particles.emitter", false); csRef<iParticleBuiltinEffectorFactory> eff_factory = csLoadPluginCheck<iParticleBuiltinEffectorFactory> ( Sys->object_reg, "crystalspace.mesh.object.particles.effector", false); csRef<iParticleBuiltinEmitterBox> boxemit = emit_factory->CreateBox (); // Time to live depends on height of sector. float velocity = 2.84f * speed / 2.0f; float seconds_to_live = (bbox.MaxY () - bbox.MinY ()) / velocity; csBox3 emit_bbox = bbox; emit_bbox.SetMin (1, emit_bbox.MaxY ()); boxemit->SetBox (emit_bbox); boxemit->SetParticlePlacement (CS_PARTICLE_BUILTIN_VOLUME); boxemit->SetEmissionRate (float (num) / seconds_to_live); boxemit->SetInitialMass (5.0f, 7.5f); boxemit->SetUniformVelocity (true); boxemit->SetInitialTTL (seconds_to_live, seconds_to_live); boxemit->SetInitialVelocity (csVector3 (0, -velocity, 0), csVector3 (0)); csRef<iParticleBuiltinEffectorLinColor> lincol = eff_factory-> CreateLinColor (); lincol->AddColor (csColor4 (.25,.25,.25,1), seconds_to_live); csRef<iParticleSystem> partstate = scfQueryInterface<iParticleSystem> (exp->GetMeshObject ()); partstate->SetMinBoundingBox (bbox); partstate->SetParticleSize (csVector2 (0.3f/50.0f, 0.3f)); partstate->SetParticleRenderOrientation (CS_PARTICLE_ORIENT_COMMON); partstate->SetCommonDirection (csVector3 (0, 1, 0)); partstate->AddEmitter (boxemit); partstate->AddEffector (lincol); }
//=========================================================================== // Demo particle system (explosion). //=========================================================================== static void add_particles_explosion (WalkTest* Sys, iSector* sector, iEngine* engine, const csVector3& center, const char* matname) { // First check if the material exists. iMaterialWrapper* mat = Sys->Engine->GetMaterialList ()-> FindByName (matname); if (!mat) { Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Can't find material '%s' in memory!", matname); return; } csRef<iMeshFactoryWrapper> mfw = engine->CreateMeshFactory ( "crystalspace.mesh.object.particles", "explosion"); if (!mfw) return; csRef<iMeshWrapper> exp = engine->CreateMeshWrapper (mfw, "custom explosion", sector, center); exp->SetZBufMode(CS_ZBUF_TEST); exp->SetRenderPriority (engine->GetAlphaRenderPriority ()); exp->GetMeshObject()->SetMaterialWrapper (mat); exp->GetMeshObject()->SetMixMode (CS_FX_ALPHA); exp->GetMeshObject()->SetColor (csColor (1, 1, 0)); csRef<iParticleBuiltinEmitterFactory> emit_factory = csLoadPluginCheck<iParticleBuiltinEmitterFactory> ( Sys->object_reg, "crystalspace.mesh.object.particles.emitter", false); csRef<iParticleBuiltinEffectorFactory> eff_factory = csLoadPluginCheck<iParticleBuiltinEffectorFactory> ( Sys->object_reg, "crystalspace.mesh.object.particles.effector", false); csRef<iParticleBuiltinEmitterSphere> sphereemit = emit_factory-> CreateSphere (); sphereemit->SetRadius (0.1f); sphereemit->SetParticlePlacement (CS_PARTICLE_BUILTIN_CENTER); sphereemit->SetPosition (csVector3 (0, 0, 0)); sphereemit->SetInitialVelocity (csVector3 (1, 0, 0), csVector3 (3, 3, 3)); sphereemit->SetUniformVelocity (false); sphereemit->SetDuration (0.1f); sphereemit->SetEmissionRate (1000.0f); sphereemit->SetInitialTTL (1.0f, 1.0f); csRef<iParticleBuiltinEffectorLinColor> lincol = eff_factory-> CreateLinColor (); lincol->AddColor (csColor4 (1,1,1,1), 1.0f); lincol->AddColor (csColor4 (1,1,1,0), 0.0f); csRef<iParticleSystem> partstate = scfQueryInterface<iParticleSystem> (exp->GetMeshObject ()); partstate->SetParticleSize (csVector2 (0.15f, 0.15f)); partstate->SetRotationMode (CS_PARTICLE_ROTATE_VERTICES); partstate->SetIntegrationMode (CS_PARTICLE_INTEGRATE_BOTH); partstate->AddEmitter (sphereemit); partstate->AddEffector (lincol); Sys->Engine->DelayedRemoveObject (1100, exp); Sys->Engine->DelayedRemoveObject (1101, mfw); exp->PlaceMesh (); }
//=========================================================================== // Demo particle system (fire). //=========================================================================== static void add_particles_fire (WalkTest* Sys, iSector* sector, char* matname, int num, const csVector3& origin) { iEngine* engine = Sys->Engine; // First check if the material exists. iMaterialWrapper* mat = engine->GetMaterialList ()->FindByName (matname); if (!mat) { Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Can't find material '%s' in memory!", matname); return; } csRef<iMeshFactoryWrapper> mfw = engine->CreateMeshFactory ( "crystalspace.mesh.object.particles", "fire"); if (!mfw) return; csRef<iMeshWrapper> exp = engine->CreateMeshWrapper (mfw, "custom fire", sector, origin); exp->SetZBufMode(CS_ZBUF_TEST); exp->GetMeshObject()->SetMixMode (CS_FX_ADD); exp->GetMeshObject()->SetMaterialWrapper (mat); csRef<iParticleBuiltinEmitterFactory> emit_factory = csLoadPluginCheck<iParticleBuiltinEmitterFactory> ( Sys->object_reg, "crystalspace.mesh.object.particles.emitter", false); csRef<iParticleBuiltinEffectorFactory> eff_factory = csLoadPluginCheck<iParticleBuiltinEffectorFactory> ( Sys->object_reg, "crystalspace.mesh.object.particles.effector", false); csRef<iParticleBuiltinEmitterSphere> sphemit = emit_factory->CreateSphere (); float velocity = 0.5f; float seconds_to_live = 2.0f; sphemit->SetRadius (.2f); sphemit->SetParticlePlacement (CS_PARTICLE_BUILTIN_VOLUME); sphemit->SetEmissionRate (float (num) / seconds_to_live); sphemit->SetInitialMass (5.0f, 7.5f); sphemit->SetUniformVelocity (true); sphemit->SetInitialTTL (seconds_to_live, seconds_to_live); sphemit->SetInitialVelocity (csVector3 (0, velocity, 0), csVector3 (0)); csRef<iParticleBuiltinEffectorLinColor> lincol = eff_factory-> CreateLinColor (); lincol->AddColor (csColor4 (0.00f, 0.00f, 0.00f, 1.00f), 2.0000f); lincol->AddColor (csColor4 (1.00f, 0.35f, 0.00f, 0.00f), 1.5000f); lincol->AddColor (csColor4 (1.00f, 0.22f, 0.00f, 0.10f), 1.3125f); lincol->AddColor (csColor4 (1.00f, 0.12f, 0.00f, 0.30f), 1.1250f); lincol->AddColor (csColor4 (0.80f, 0.02f, 0.00f, 0.80f), 0.9375f); lincol->AddColor (csColor4 (0.60f, 0.00f, 0.00f, 0.90f), 0.7500f); lincol->AddColor (csColor4 (0.40f, 0.00f, 0.00f, 0.97f), 0.5625f); lincol->AddColor (csColor4 (0.20f, 0.00f, 0.00f, 1.00f), 0.3750f); lincol->AddColor (csColor4 (0.00f, 0.00f, 0.00f, 1.00f), 0.1875f); lincol->AddColor (csColor4 (0.00f, 0.00f, 0.00f, 1.00f), 0.0000f); csRef<iParticleBuiltinEffectorForce> force = eff_factory-> CreateForce (); force->SetRandomAcceleration (csVector3 (1.5f, 1.5f, 1.5f)); csRef<iParticleSystem> partstate = scfQueryInterface<iParticleSystem> (exp->GetMeshObject ()); //partstate->SetMinBoundingBox (bbox); partstate->SetParticleSize (csVector2 (0.04f, 0.08f)); partstate->AddEmitter (sphemit); partstate->AddEffector (lincol); partstate->AddEffector (force); }