| 1 |
#include "stdafx.h" |
| 2 |
#include "CModelPlugin.h" |
| 3 |
#include "CEnvPlugin.h" |
| 4 |
#include "CScene.h" |
| 5 |
#include "CConfigMode.h" |
| 6 |
|
| 7 |
// 内部グローバル |
| 8 |
VEC3 g_WindDir = V3ZERO; // 風方向 |
| 9 |
VEC3 g_WindDirNorm = V3DIR; // 風方向 (正規化済) |
| 10 |
|
| 11 |
/* |
| 12 |
* コンストラクタ |
| 13 |
*/ |
| 14 |
CParticleInst::CParticleInst( |
| 15 |
CParticle *emitter, // エミッタ |
| 16 |
VEC3 pos, // 座標 |
| 17 |
VEC3 dir, // 速度 |
| 18 |
float initradius, // 半径 |
| 19 |
float finradius, // アルファ |
| 20 |
int lifetime, // 寿命 |
| 21 |
CScene *scene // シーン |
| 22 |
){ |
| 23 |
m_Emitter = emitter; |
| 24 |
m_Pos = pos; |
| 25 |
m_Dir = dir; |
| 26 |
m_InitRadius = initradius; |
| 27 |
m_FinRadius = finradius; |
| 28 |
m_Alpha = 0.0f; |
| 29 |
m_Angle = FRand(2.0f*D3DX_PI); |
| 30 |
m_Color = MixColor(m_Emitter->m_Color[0], m_Emitter->m_Color[1], FRand(1.0f)); |
| 31 |
m_Lifetime = lifetime; |
| 32 |
if(m_Lifetime<=0) m_Lifetime = 1; |
| 33 |
m_Timer = 0; |
| 34 |
m_Scene = scene; |
| 35 |
} |
| 36 |
|
| 37 |
/* |
| 38 |
* レンダリング |
| 39 |
*/ |
| 40 |
void CParticleInst::Render(){ |
| 41 |
if(m_Timer>m_Lifetime || m_Scene!=g_Scene) return; |
| 42 |
devTransBillboard(m_Pos); |
| 43 |
devSetTexture(0, m_Emitter->m_Texture); |
| 44 |
float radius = 1.41421356f*(m_Alpha*m_InitRadius+(1.0f-m_Alpha)*m_FinRadius); |
| 45 |
float si = sinf(m_Angle)*radius, co = cosf(m_Angle)*radius; |
| 46 |
D3DCOLOR col = ScaleColor(m_Color, m_Alpha); |
| 47 |
if(m_Emitter->m_BlendMode){ |
| 48 |
devBLEND_ADD2(); |
| 49 |
}else{ |
| 50 |
devBLEND_ALPHA(); |
| 51 |
col = MultiplyColor(g_NoLightColor, col); |
| 52 |
} |
| 53 |
SetUVMap(0.0f, 0.0f, 1.0f, 1.0f); |
| 54 |
TexMap3DRect( |
| 55 |
VEC3(co, si, 0.0f), VEC3(si, -co, 0.0f), |
| 56 |
VEC3(-co, -si, 0.0f), VEC3(-si, co, 0.0f), col); |
| 57 |
} |
| 58 |
|
| 59 |
/* |
| 60 |
* シミュレーション進行 |
| 61 |
*/ |
| 62 |
bool CParticleInst::Simulate(){ |
| 63 |
m_Timer++; |
| 64 |
if(m_Timer>m_Lifetime) return false; |
| 65 |
VEC3 wind = g_ConfigMode->GetWind() ? g_WindDir : V3ZERO; |
| 66 |
m_Alpha = (float)(m_Lifetime-m_Timer)/m_Lifetime; |
| 67 |
m_Pos += m_Dir; |
| 68 |
m_Dir.y -= m_Emitter->m_Gravity; |
| 69 |
m_Dir = (1.0f-m_Emitter->m_AirResistance)*m_Dir |
| 70 |
+m_Emitter->m_AirResistance*(wind+V3RandS(m_Emitter->m_Turbulence)); |
| 71 |
return true; |
| 72 |
} |
| 73 |
|
| 74 |
//////////////////////////////////////////////////////////////////////////////// |
| 75 |
//////////////////////////////////////////////////////////////////////////////// |
| 76 |
|
| 77 |
/* |
| 78 |
* 読込 |
| 79 |
*/ |
| 80 |
char *CParticleState::Read( |
| 81 |
char *str // 対象文字列 |
| 82 |
){ |
| 83 |
char *eee; |
| 84 |
if(!(str = Assignment(eee = str, "ParticleState"))) return NULL; |
| 85 |
if(!(str = ConstFloat(eee = str, &m_EmissionCredit))) throw CSynErr(eee); |
| 86 |
if(!(str = Character2(eee = str, ','))) throw CSynErr(eee); |
| 87 |
if(!(str = Vector3D(eee = str, &m_OldPos))) throw CSynErr(eee); |
| 88 |
if(!(str = Character2(eee = str, ';'))) throw CSynErr(eee); |
| 89 |
return str; |
| 90 |
} |
| 91 |
|
| 92 |
/* |
| 93 |
* 保存 |
| 94 |
*/ |
| 95 |
void CParticleState::Save( |
| 96 |
FILE *df, // ファイル |
| 97 |
char *ind // インデント |
| 98 |
){ |
| 99 |
fprintf(df, "%sParticleState = %f, ", ind, m_EmissionCredit); |
| 100 |
V3Save(df, m_OldPos, ";\n"); |
| 101 |
} |
| 102 |
|
| 103 |
//////////////////////////////////////////////////////////////////////////////// |
| 104 |
//////////////////////////////////////////////////////////////////////////////// |
| 105 |
|
| 106 |
// 内部グローバル |
| 107 |
list<CParticleInst> CParticle::ms_RenderList; |
| 108 |
|
| 109 |
/* |
| 110 |
* [static] |
| 111 |
* リスト初期化 |
| 112 |
*/ |
| 113 |
void CParticle::InitRenderList(){ |
| 114 |
ms_RenderList.clear(); |
| 115 |
} |
| 116 |
|
| 117 |
/* |
| 118 |
* [static] |
| 119 |
* 全てレンダリング |
| 120 |
*/ |
| 121 |
void CParticle::RenderAll(){ |
| 122 |
if(!g_ConfigMode->GetMiscParticle()) return; |
| 123 |
devResetMaterial(); |
| 124 |
//devSetZRead(FALSE); |
| 125 |
devSetZWrite(FALSE); |
| 126 |
devSetLighting(FALSE); |
| 127 |
IParticleInst ipi; |
| 128 |
for(ipi = ms_RenderList.begin(); ipi!=ms_RenderList.end(); ipi++) ipi->CalcDist(); |
| 129 |
ms_RenderList.sort(); |
| 130 |
for(ipi = ms_RenderList.begin(); ipi!=ms_RenderList.end(); ipi++) ipi->Render(); |
| 131 |
//devSetZRead(TRUE); |
| 132 |
devSetZWrite(TRUE); |
| 133 |
devSetLighting(TRUE); |
| 134 |
devBLEND_ALPHA(); |
| 135 |
} |
| 136 |
|
| 137 |
/* |
| 138 |
* [static] |
| 139 |
* 全てシミュレート |
| 140 |
*/ |
| 141 |
void CParticle::SimulateAll(){ |
| 142 |
IParticleInst ipi = ms_RenderList.begin(); |
| 143 |
// Dialog("particles %d", ms_RenderList.size()); |
| 144 |
while(ipi!=ms_RenderList.end()){ |
| 145 |
if(ipi->Simulate()) ipi++; |
| 146 |
else ipi = ms_RenderList.erase(ipi); |
| 147 |
} |
| 148 |
} |
| 149 |
|
| 150 |
/* |
| 151 |
* 読込 |
| 152 |
*/ |
| 153 |
char *CParticle::Read( |
| 154 |
char *str, // 対象文字列 |
| 155 |
CModelPlugin *mpi // 車輌プラグイン |
| 156 |
){ |
| 157 |
char *tmp, *eee; |
| 158 |
int i; |
| 159 |
string obj, blend; |
| 160 |
m_Texture = NULL; |
| 161 |
if(!(str = BeginBlock(str, "Particle"))) return NULL; |
| 162 |
if(!(str = AsgnString(eee = str, "TextureFileName", &m_TextureFileName))) throw CSynErr(eee); |
| 163 |
if(!(str = AsgnString(eee = str, "AttachObject", &obj))) throw CSynErr(eee); |
| 164 |
if(!(m_Link = mpi->FindObject(obj))) |
| 165 |
throw CSynErr(eee, "%s: \"%s\"", lang(UndefinedObject), obj.c_str()); |
| 166 |
if(!(str = AsgnVector3D(eee = str, "SourceCoord", &m_SourceCoord))) throw CSynErr(eee); |
| 167 |
if(!(str = AsgnFloat(eee = str, "MinQty", &m_MinQty))) throw CSynErr(eee); |
| 168 |
if(tmp = AsgnFloat(eee = str, "MaxQty", &m_MaxQty)) str = tmp; |
| 169 |
else m_MaxQty = m_MinQty; |
| 170 |
if(tmp = AsgnFloat(eee = str, "VelocityRel", &m_VelocityRel)) str = tmp; |
| 171 |
else m_VelocityRel = 0.0f; |
| 172 |
if(tmp = AsgnFloat(eee = str, "AccelerationRel", &m_AccelerationRel)) str = tmp; |
| 173 |
else m_AccelerationRel = 0.0f; |
| 174 |
if(tmp = AsgnFloat(eee = str, "DecelerationRel", &m_DecelerationRel)) str = tmp; |
| 175 |
else m_DecelerationRel = 0.0f; |
| 176 |
m_MinQty /= MAXFPS; |
| 177 |
m_MaxQty /= MAXFPS; |
| 178 |
m_VelocityRel *= 3.6f; |
| 179 |
m_AccelerationRel *= 3.6f*MAXFPS; |
| 180 |
m_DecelerationRel *= 3.6f*MAXFPS; |
| 181 |
if(!(str = AsgnFloat(eee = str, "Lifetime", m_Lifetime, 2, true))) throw CSynErr(eee); |
| 182 |
if(!(str = AsgnVector3D(eee = str, "Direction", m_Direction, 2, true))) throw CSynErr(eee); |
| 183 |
for(i = 0; i<2; i++) m_Direction[i] /= MAXFPS; |
| 184 |
if(!(str = AsgnFloat(eee = str, "InitialRadius", m_InitialRadius, 2, true))) throw CSynErr(eee); |
| 185 |
if(!(str = AsgnFloat(eee = str, "FinalRadius", m_FinalRadius, 2, true))) throw CSynErr(eee); |
| 186 |
if(!(str = AsgnColor(eee = str, "Color", m_Color, 2, true))) throw CSynErr(eee); |
| 187 |
if(!(str = AsgnIdentifier(eee = str, "BlendMode", &blend))) throw CSynErr(eee); |
| 188 |
if(blend=="Alpha") m_BlendMode = 0; |
| 189 |
else if(blend=="Add") m_BlendMode = 1; |
| 190 |
else throw CSynErr(eee, "%s: \"%s\"", lang(InvalidBlendMode), blend.c_str()); |
| 191 |
if(tmp = AsgnFloat(eee = str, "AirResistance", &m_AirResistance)) str = tmp; |
| 192 |
else m_AirResistance = 0.0f; |
| 193 |
ValueArea(&m_AirResistance, 0.0f, 1.0f); |
| 194 |
m_AirResistance = 1.0f-powf(1.0f-m_AirResistance, 1.0f/MAXFPS); |
| 195 |
if(tmp = AsgnFloat(eee = str, "Gravity", &m_Gravity)) str = tmp; |
| 196 |
else m_Gravity = 0.0f; |
| 197 |
m_Gravity /= MAXFPS; |
| 198 |
if(tmp = AsgnFloat(eee = str, "Turbulence", &m_Turbulence)) str = tmp; |
| 199 |
else m_Turbulence = 0.0f; |
| 200 |
m_Turbulence /= MAXFPS; |
| 201 |
if(!(str = EndBlock(eee = str))) throw CSynErr(eee, ERR_ENDBLOCK); |
| 202 |
m_LinkState = NULL; |
| 203 |
return str; |
| 204 |
} |
| 205 |
|
| 206 |
/* |
| 207 |
* データ読込 |
| 208 |
*/ |
| 209 |
void CParticle::LoadData(){ |
| 210 |
m_Texture = g_TexList.Get(FALSE, m_TextureFileName.c_str(), 0, !g_NamedObjectMipMap); |
| 211 |
} |
| 212 |
|
| 213 |
/* |
| 214 |
* 状態変数をアタッチ |
| 215 |
*/ |
| 216 |
void CParticle::Link( |
| 217 |
CParticleState *stt // 状態変数 |
| 218 |
){ |
| 219 |
m_LinkState = stt; |
| 220 |
m_LinkState->m_ApplyFlag = false; |
| 221 |
} |
| 222 |
|
| 223 |
/* |
| 224 |
* レンダリングリストに登録 |
| 225 |
*/ |
| 226 |
void CParticle::Register( |
| 227 |
CScene *scene // シーン |
| 228 |
){ |
| 229 |
if(!m_LinkState || !scene) return; |
| 230 |
m_LinkState->m_ApplyFlag = true; |
| 231 |
CObject *obj = m_Link->GetObject(); |
| 232 |
VEC3 oright = obj->GetRight(), oup = obj->GetUp(), odir = obj->GetDir(); |
| 233 |
V3Norm(&oright, &oright); |
| 234 |
V3Norm(&oup, &oup); |
| 235 |
V3Norm(&odir, &odir); |
| 236 |
VEC3 pos = obj->GetPos()+V3LocalToWorld(&m_SourceCoord, &oright, &oup, &odir); |
| 237 |
if(m_LinkState->m_EmissionCredit<0.0f){ |
| 238 |
m_LinkState->m_EmissionCredit = 0.0f; |
| 239 |
m_LinkState->m_EmissionCredit = 0.0f; |
| 240 |
m_LinkState->m_OldPos = pos; |
| 241 |
return; |
| 242 |
} |
| 243 |
VEC3 wind = g_ConfigMode->GetWind() ? g_WindDir : V3ZERO; |
| 244 |
VEC3 delta = pos-m_LinkState->m_OldPos; |
| 245 |
float speed = V3Len(&delta); |
| 246 |
if(m_LinkState->m_OldSpeed<0.0f) m_LinkState->m_OldSpeed = speed; |
| 247 |
float acc = speed-m_LinkState->m_OldSpeed; |
| 248 |
float qty = m_MinQty+m_VelocityRel*speed |
| 249 |
+(acc<0.0f ? -m_DecelerationRel : m_AccelerationRel)*acc; |
| 250 |
ValueArea(&qty, m_MinQty, m_MaxQty); |
| 251 |
m_LinkState->m_EmissionCredit += qty; |
| 252 |
int i = 0, credit = (int)m_LinkState->m_EmissionCredit; |
| 253 |
while(m_LinkState->m_EmissionCredit>=1.0f){ |
| 254 |
m_LinkState->m_EmissionCredit -= 1.0f; |
| 255 |
VEC3 rad = V3Rand2(m_Direction[0], m_Direction[1]); |
| 256 |
VEC3 dir = V3LocalToWorld(&rad, &oright, &oup, &odir)+delta; |
| 257 |
float fix = (float)(i++)/credit, vfix = powf(1.0f-m_AirResistance, fix); |
| 258 |
ms_RenderList.push_back(CParticleInst( |
| 259 |
this, pos+fix*rad, vfix*dir+(1.0f-vfix)*wind, |
| 260 |
FRand2(m_InitialRadius[0], m_InitialRadius[1]), |
| 261 |
FRand2(m_FinalRadius[0], m_FinalRadius[1]), |
| 262 |
Round(FRand2(m_Lifetime[0], m_Lifetime[1])*MAXFPS), scene)); |
| 263 |
} |
| 264 |
m_LinkState->m_OldPos = pos; |
| 265 |
m_LinkState->m_OldSpeed = speed; |
| 266 |
} |