Skip to content

Instantly share code, notes, and snippets.

@kei-y
Created August 21, 2019 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kei-y/180999193b57a6dceef2ca1e59ad043c to your computer and use it in GitHub Desktop.
Save kei-y/180999193b57a6dceef2ca1e59ad043c to your computer and use it in GitHub Desktop.
//
//
// 解説
//
//
// $HeadURL: https://svnrepos.sandlot.jp/svn/repos/FUSHIMI/trunk/Program/SourceFiles/Game/Object/Effect/GlassClashEffect.cpp $
// $Id: GlassClashEffect.cpp 1077 2019-08-21 13:45:18Z prg_y_horiuchi $
//
//------------------------------------------------------------------------------
// include files
//------------------------------------------------------------------------------
#include "stdafx.h"
#include "GlassClashEffect.h"
#include "../Effect/EffectGenUtil.h"
#include <sgs/db/db_Output.h>
#include <sgs/mt/mt_Utility.h>
#include <xgs/game/game_System.h>
#include <xgs/xgs_Global.h>
#include <xgs/Havok/havok_Utility.h>
#include <Physics2012/Dynamics/Phantom/hkpAabbPhantom.h>
#include <Physics2012/Collide/Query/Collector/RayCollector/hkpClosestRayHitCollector.h>
#include <Physics2012/Collide/Query/Collector/PointCollector/hkpSimpleClosestContactCollector.h>
// #include <xgs/debug/debug_Utility.h>
#include "../../Collision/HitQueryUtility.h"
//------------------------------------------------------------------------------
// compile switch
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// constant
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// macro
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// type
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// class
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// global function
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// local variable
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// コンストラクタ
//------------------------------------------------------------------------------
GlassClashEffect::GlassClashEffect(const InitParamBase& _init_param) : SceneObject(_init_param)
{
if (CheckLimitter(EFFECT_LIMITTER_INDEX_CRASH_GLASS, 1, 100) == false)
return;
EnableCallback(CB_UPDATE | CB_SYNC_RENDER);
const InitParam& init_param = _init_param.cast<const InitParam>();
SGS_WARNING(init_param.m_reduction_level > 0);
m_gravity = 9.80665f / 60.0f / 60.0f;
// 大きいガラス片
{
ParticleEmitterCore::InitParam particle_param;
particle_param.m_max_count = 5;
particle_param.m_alive_time_min = uint32_t(init_param.m_size * 25.0f);
particle_param.m_alive_time_max = particle_param.m_alive_time_min * 2;
particle_param.m_blend_mode = xgl::ren::DrawUtility::BLEND_ALPHA;
// particle_param.m_air_resistance = 0.98f;
particle_param.m_air_resistance = 1.0f;
particle_param.m_gravity.Set(0.0f, -m_gravity, 0.0f);
particle_param.m_direction.m_angle_min = 0.0f;
particle_param.m_direction.m_angle_max = sgs::mt::PI * 0.125f;
particle_param.m_rotate.m_min = 0.0f;
particle_param.m_rotate.m_max = 0.0f;
particle_param.m_rotate.m_speed_min = 0.0f;
particle_param.m_rotate.m_speed_max = 0.0f;
particle_param.m_speed.m_factor = ParticleEmitterCore::InitParam::RANDOM_FACTOR_SPEED;
particle_param.m_speed.m_min = 0.0f;
particle_param.m_speed.m_max = init_param.m_size * 0.1f;
particle_param.m_size.m_factor = ParticleEmitterCore::InitParam::RANDOM_FACTOR_SPEED;
particle_param.m_size.m_min = init_param.m_size * 0.4f;
particle_param.m_size.m_max = particle_param.m_size.m_min * 2.0f;
particle_param.m_size.m_inc = 0;
particle_param.m_color.m_base.Set(1.0f, 1.0f, 1.0f, 1.0f);
particle_param.m_color.m_fade_out.Set(1.0f, 1.0f, 1.0f, 0.0f);
particle_param.m_texture.m_instance = EffectGenUtil::Instance().GetTexture(L"ガラス片小_01.dds");
particle_param.m_lighting.m_is_enable = true;
// particle_param.m_lighting.m_prim_normal_weight = 1.0f;
// particle_param.m_lighting.m_round_normal_weight = 1.0f;
particle_param.m_lighting.m_view_normal_weight = 1.0f;
m_large_particle.Initialize(particle_param);
// エミット
m_large_particle.Emit(init_param.m_position, init_param.m_normal, 5 / init_param.m_reduction_level);
}
// 小さいガラス片
{
ParticleEmitterCore::InitParam particle_param;
particle_param.m_max_count = 5;
particle_param.m_alive_time_min = uint32_t(init_param.m_size * 25.0f);
particle_param.m_alive_time_max = particle_param.m_alive_time_min * 2;
particle_param.m_blend_mode = xgl::ren::DrawUtility::BLEND_ALPHA;
// particle_param.m_air_resistance = 0.98f;
particle_param.m_air_resistance = 1.0f;
particle_param.m_gravity.Set(0.0f, -m_gravity, 0.0f);
particle_param.m_direction.m_angle_min = 0.0f;
particle_param.m_direction.m_angle_max = sgs::mt::PI * 0.25f;
particle_param.m_rotate.m_min = 0.0f;
particle_param.m_rotate.m_max = 0.0f;
particle_param.m_rotate.m_speed_min = 0.0f;
particle_param.m_rotate.m_speed_max = 0.0f;
particle_param.m_speed.m_factor = ParticleEmitterCore::InitParam::RANDOM_FACTOR_SPEED;
particle_param.m_speed.m_min = 0.0f;
particle_param.m_speed.m_max = init_param.m_size * 0.1f;
particle_param.m_size.m_factor = ParticleEmitterCore::InitParam::RANDOM_FACTOR_SPEED;
particle_param.m_size.m_min = init_param.m_size * 0.3f;
particle_param.m_size.m_max = particle_param.m_size.m_min * 2.0f;
particle_param.m_size.m_inc = 0;
particle_param.m_color.m_base.Set(1.0f, 1.0f, 1.0f, 1.0f);
particle_param.m_color.m_fade_out.Set(1.0f, 1.0f, 1.0f, 0.0f);
particle_param.m_texture.m_instance = EffectGenUtil::Instance().GetTexture(L"ガラス片小_02.dds");
particle_param.m_lighting.m_is_enable = true;
// particle_param.m_lighting.m_prim_normal_weight = 1.0f;
// particle_param.m_lighting.m_round_normal_weight = 1.0f;
particle_param.m_lighting.m_view_normal_weight = 1.0f;
m_small_particle.Initialize(particle_param);
// エミット
m_small_particle.Emit(init_param.m_position, init_param.m_normal, 5 / init_param.m_reduction_level);
}
// 砕ける破片
{
m_particle_position = init_param.m_position;
m_emit_vector = init_param.m_normal;
m_emit_vector.Normalize();
m_emit_vector = sgs::mt::MakeRandomVector(m_emit_vector, 0.0f, sgs::mt::PI * 0.25f); // ランダムベクトル
m_emit_vector.Mul(init_param.m_size * sgs::mt::Random32::global.Float(0.03f, 0.1f));
m_particle_position += m_emit_vector; // 壁にめり込まないように
m_start_alpha = sgs::mt::Random32::global.Float(0.5f, 1.0f);
m_clash_particle.pos = init_param.m_position;
m_clash_particle.color = sgs::mt::Color(1.0f, 1.0f, 1.0f, m_start_alpha);
m_clash_particle.size =
init_param.m_size * sgs::mt::Random32::global.Float(0.25f, 0.4f); // 大きいので縮小(ランダム)
m_clash_particle.rad = 0.0f;
m_clash_particle.nrm = init_param.m_normal;
m_clash_particle.pat_no = 1; //?
m_clash_texture = EffectGenUtil::Instance().GetTexture(L"ガラス片大_01.dds");
xgl::gs::SamplerState::InitParam sampler_init_param;
sampler_init_param.m_mip_lod_bias = 0;
m_clash_sampler.Initialize(xgs::g_device, sampler_init_param);
m_ground_hit = false;
m_use_clash_particle = true;
m_particle_alpha = m_start_alpha;
if (sgs::mt::Random32::global.Integer(0, 100) > 60)
{
m_ground_hit = true; // 砕ける破片を表示させない
m_use_clash_particle = false;
}
// 砕けたガラス片パーティクル
ParticleEmitterCore::InitParam particle_param;
particle_param.m_max_count = 20;
particle_param.m_alive_time_min = uint32_t(init_param.m_size * 50.0f);
particle_param.m_alive_time_max = uint32_t(init_param.m_size * 50.0f);
particle_param.m_blend_mode = xgl::ren::DrawUtility::BLEND_ALPHA;
// particle_param.m_air_resistance = 0.98f;
particle_param.m_gravity.Set(0.0f, -m_gravity, 0.0f);
particle_param.m_direction.m_angle_min = 0.0f;
particle_param.m_direction.m_angle_max = sgs::mt::PI * 0.25f;
particle_param.m_rotate.m_min = 0.0f;
particle_param.m_rotate.m_max = 0.0f;
particle_param.m_rotate.m_speed_min = 0.0f;
particle_param.m_rotate.m_speed_max = 0.0f;
particle_param.m_speed.m_factor = ParticleEmitterCore::InitParam::RANDOM_FACTOR_SPEED;
particle_param.m_speed.m_min = 0.0f;
particle_param.m_speed.m_max = init_param.m_size * 0.05f;
particle_param.m_size.m_factor = ParticleEmitterCore::InitParam::RANDOM_FACTOR_SPEED;
particle_param.m_size.m_min = m_clash_particle.size;
particle_param.m_size.m_max = m_clash_particle.size;
particle_param.m_size.m_inc = 0;
particle_param.m_color.m_base.Set(1.0f, 1.0f, 1.0f, 1.0f);
particle_param.m_color.m_fade_out.Set(1.0f, 1.0f, 1.0f, 0.0f);
particle_param.m_texture.m_instance = EffectGenUtil::Instance().GetTexture(L"ガラス片小_02.dds");
particle_param.m_lighting.m_is_enable = true;
// particle_param.m_lighting.m_prim_normal_weight = 1.0f;
// particle_param.m_lighting.m_round_normal_weight = 1.0f;
particle_param.m_lighting.m_view_normal_weight = 0.5f;
m_splash_particle.Initialize(particle_param);
}
m_time = 0;
m_timelimit = uint32_t(init_param.m_size * 50.0f);
// aabb計算(とりあえず)
sgs::mt::Vector size(2.0f, 2.0f, 2.0f);
m_local_aabb.m_pos = init_param.m_position;
m_local_aabb.m_size = size * 0.5f;
sgs::mt::Matrix mat;
xgs::umbra::Object::Initialize(xgs::game::System::Instance().GetUmbraCell(), mat, xgs::g_device);
xgs::umbra::Object::imdSetOpacity(false); // 不透明フェーズでの描画OFF
xgs::umbra::Object::imdSetTransparent(true); // 半透明フェーズでの描画ON
xgs::umbra::Object::imdSetRenderCost(Umbra::Object::CHEAP); // エフェクト処理なのでカリングが弱くても気にしない
xgs::umbra::Object::imdSetProperty(Umbra::Object::OCCLUDER, false); // 描画時に深度情報は出力しないのでfalse
}
//------------------------------------------------------------------------------
// デストラクタ
//------------------------------------------------------------------------------
GlassClashEffect::~GlassClashEffect()
{
}
//------------------------------------------------------------------------------
// 同期
//------------------------------------------------------------------------------
void GlassClashEffect::OnSyncRender()
{
m_large_particle.SyncRender();
m_small_particle.SyncRender();
m_splash_particle.SyncRender();
m_clash_particle.pos = m_particle_position;
m_clash_particle.color.a = m_particle_alpha;
sgs::mt::MatrixNC m;
CalcAabb(m);
xgs::umbra::Object::imdSetObb(m);
}
//------------------------------------------------------------------------------
// 更新
//------------------------------------------------------------------------------
void GlassClashEffect::OnUpdate(const xgs::game::UpdateContext& context)
{
// パーティクル部分
m_large_particle.Update(context);
m_small_particle.Update(context);
m_splash_particle.Update(context);
// レイキャストテスト
if (m_ground_hit == false)
{
// カラー遷移(alpha値のみ)
float time_factor = (float)m_time / (float)m_timelimit;
m_particle_alpha = m_start_alpha * (1.0f - time_factor);
sgs::mt::Vector next_position(m_particle_position);
next_position += m_emit_vector;
sgs::mt::Vector difference_vec(next_position - m_particle_position);
difference_vec.Abs();
hknpClosestHitCollector collector;
xgs::havok::CastRaySettings settings;
settings.m_from = m_particle_position;
settings.m_to = next_position;
settings.m_filter_info = CollisionFilter::Instance().CalcForMapSearchFilter();
xgs::havok::CastRayToWorld(xgs::game::System::Instance().World(), collector, settings);
if (collector.hasHit())
{
// 地面HIT
m_ground_hit = true;
// 1回かけらを撒く(パーティクル)
sgs::mt::Vector position = XGS_TO_SGSVECTOR(collector.getHit().m_position);
sgs::mt::Vector normal = XGS_TO_SGSVECTOR(collector.getHit().m_normal);
sgs::mt::Vector ref_vec(m_emit_vector);
ref_vec.Reflection(normal);
m_splash_particle.Emit(position, normal, 5);
m_timelimit *= 2; // 砕けたパーティクル消失までの時間分増加
}
// 砕ける予定のパーティクルの座標更新
m_particle_position += m_emit_vector;
m_emit_vector += sgs::mt::Vector(0.0f, -m_gravity, 0.0f);
// m_emit_vector.Mul(0.98f); // 空気抵抗値
}
// aabb作成
sgs::mt::Aabb temp_aabb;
// 砕けるパーティクル
if (m_use_clash_particle == true)
{
if (m_ground_hit == false)
{
// 砕ける前
temp_aabb.m_size.Set(m_clash_particle.size, m_clash_particle.size, m_clash_particle.size);
temp_aabb.m_pos = m_clash_particle.pos;
}
else
{
// 砕けた後
temp_aabb = m_splash_particle.AABB();
}
}
else
{
temp_aabb.m_pos = m_particle_position;
temp_aabb.m_size.Set(0.1f, 0.1f, 0.1f);
}
// aabb合成
if (m_small_particle.IsEnd() == false)
{
temp_aabb.Combine(m_small_particle.AABB());
}
if (m_large_particle.IsEnd() == false)
{
temp_aabb.Combine(m_large_particle.AABB());
}
// if( m_splash_particle.IsEnd() == false ){temp_aabb.Combine(m_splash_particle.AABB());}
m_local_aabb = temp_aabb;
if (m_time++ > m_timelimit)
{
// 削除
Delete();
}
}
//------------------------------------------------------------------------------
// レンダリング
//------------------------------------------------------------------------------
void GlassClashEffect::OnRender(xgl::gs::Context& context,
RenderPhase phase,
const xgs::umbra::RenderSetting& render_setting)
{
m_large_particle.Render(context, sgs::mt::UNIT_MATRIX);
m_small_particle.Render(context, sgs::mt::UNIT_MATRIX);
m_splash_particle.Render(context, sgs::mt::UNIT_MATRIX);
if (m_ground_hit == false)
{
xgs::g_draw_utility.imdSetState(context, false, xgl::ren::DrawUtility::BLEND_ALPHA);
xgs::g_draw_utility.imdSetSampler(context, m_clash_sampler, m_clash_texture);
xgs::g_draw_utility.imdDrawLightParticle(context, sgs::mt::UNIT_MATRIX, &m_clash_particle, 1, 1.0f, 0.1f, 1.0f);
}
}
//------------------------------------------------------------------------------
// Aabb作成
//------------------------------------------------------------------------------
void GlassClashEffect::CalcAabb(sgs::mt::Matrix& dest)
{
sgs::mt::Aabb aabb;
aabb.SetTransformAABB(m_local_aabb, m_matrix);
aabb.m_size.Max(sgs::mt::Vector(0.1f, 0.1f, 0.1f));
dest[0].Set(aabb.m_size.x, 0.0f, 0.0f, 0.0f);
dest[1].Set(0.0f, aabb.m_size.y, 0.0f, 0.0f);
dest[2].Set(0.0f, 0.0f, aabb.m_size.z, 0.0f);
dest[3] = aabb.m_pos;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment