#include "stdafx.h" #include "Trail.h" #include "DynamicSimpleMesh.h" #include "SceneManager.h" #include "Console.h" TrailEffect::TrailEffect() : m_fWidth(0) { //m_kTopRibbon.m_vPoints.reserve( 1000 ); //m_kBtmRibbon.m_vPoints.reserve( 1000 ); //Create the arrays we'll need for the NiTriShapeDynamicData object NiPoint3* pkVerts = NiNew NiPoint3[NUM_DOUBLE_SCANLINE]; NiPoint3* pkNormals = NiNew NiPoint3[NUM_DOUBLE_SCANLINE]; NiPoint2* pkTexCoords = NiNew NiPoint2[NUM_DOUBLE_SCANLINE]; NiColorA* pkColors = NiNew NiColorA[NUM_DOUBLE_SCANLINE]; unsigned short* pkConnect = NiAlloc(unsigned short, NUM_DOUBLE_SCANLINE * 3); //Initialize everything. We set the UVs to their actual values as they //will remain constant over time. This gives the swoosh the sense of //hanging in the air. We set the velocity scale on everything to 0.0f //though so the swoosh starts out invisible. float fUStep = 1.0f / NUM_SCANLINE; int i = 0; for (; i < NUM_DOUBLE_SCANLINE; i++) { float fU = fUStep * (i / 2); float fV = 1.0f - 1.0f * (i % 2); pkNormals[i].x = 1; pkTexCoords[i].x = fU; pkTexCoords[i].y = fV; pkColors[i].r = 1.f; pkColors[i].g = 1.f; pkColors[i].b = 1.f; pkColors[i].a = 1.f; } //Esatblish the connectivity array. This will not change. for (i = 0; i < NUM_SCANLINE; i++) { int n = 2 * i; pkConnect[6 * i] = n; pkConnect[6 * i + 1] = n + 1; pkConnect[6 * i + 2] = n + 2; pkConnect[6 * i + 3] = n + 1; pkConnect[6 * i + 4] = n + 3; pkConnect[6 * i + 5] = n + 2; } //Seed the system with one quad. NiTriShapeDynamicData* pkData = NiNew NiTriShapeDynamicData( NUM_DOUBLE_SCANLINE, pkVerts, pkNormals, pkColors, pkTexCoords, 1, NiGeometryData::NBT_METHOD_NONE, NUM_DOUBLE_SCANLINE - 2, pkConnect, 0, 0); pkData->SetConsistency(NiGeometryData::VOLATILE); //Set a fake bound that insures rendering to begin with. //NiBound kBound; //kBound.SetCenter(0.0f, 0.0f, 0.0f); //kBound.SetRadius(10000.0f); //pkData->SetBound(kBound); m_kAxis.z = -1; m_pkTriShape = NiNew NiTriShape(pkData); // 建立静态数据,避免重复创建 NiZBufferProperty* pkZ = NiNew NiZBufferProperty; pkZ->SetZBufferTest(true); pkZ->SetZBufferWrite(false); NiStencilProperty* pkStencilProperty = NiNew NiStencilProperty; pkStencilProperty->SetDrawMode(NiStencilProperty::DRAW_BOTH); NiTexturingProperty* pkTexturingProp = NiNew NiTexturingProperty; pkTexturingProp->SetBaseClampMode(NiTexturingProperty::CLAMP_S_CLAMP_T); pkTexturingProp->SetBaseFilterMode(NiTexturingProperty::FILTER_NEAREST); m_pkTriShape->AttachProperty(pkTexturingProp); NiVertexColorProperty* pkColorProperty = NiNew NiVertexColorProperty; pkColorProperty->SetSourceMode(NiVertexColorProperty::SOURCE_IGNORE); pkColorProperty->SetLightingMode(NiVertexColorProperty::LIGHTING_E); NiAlphaProperty* pkAlpha = NiNew NiAlphaProperty; pkAlpha->SetAlphaBlending(true); pkAlpha->SetSrcBlendMode(NiAlphaProperty::ALPHA_SRCALPHA); pkAlpha->SetDestBlendMode(NiAlphaProperty::ALPHA_ONE); NiMaterialProperty* pkMaterail = NiNew NiMaterialProperty; pkMaterail->SetAlpha(0.5f); pkMaterail->SetDiffuseColor(NiColor::BLACK); pkMaterail->SetEmittance(NiColor::WHITE); m_pkTriShape->AttachProperty(pkZ); m_pkTriShape->AttachProperty(pkStencilProperty); m_pkTriShape->AttachProperty(pkColorProperty); m_pkTriShape->AttachProperty(pkAlpha); m_pkTriShape->AttachProperty(pkMaterail); m_spEffectNode = NiNew NiNode; m_spEffectNode->AttachChild(m_pkTriShape); m_spEffectNode->UpdateProperties(); m_spEffectNode->UpdateEffects(); m_spEffectNode->UpdateNodeBound(); m_spEffectNode->Update(0); m_spSoundNode = NiNew NiNode; } TrailEffect::~TrailEffect() { m_spSoundNode->DetachParent(); m_spSoundNode = 0; } void TrailEffect::BindObject(NiAVObject* pkObject, float fWidth, float fDelay, float fTotal/*=2.0f*/) { m_spBindObject = pkObject; // NIASSERT(m_spBindObject); m_spSoundNode->AttachParent((NiNode*)pkObject); m_fWidth = fWidth; m_fDelay = fDelay; m_fTotal = fTotal; if( m_fTotal >= 6.f ) m_fTotal = 6.f; else if( m_fTotal <= 0.f ) m_fTotal = 2.f; } void TrailEffect::SetTexture(const char* szTexFile) { if (!m_pkTriShape) return; NiTexture* pkTexture = NiSourceTexture::Create(szTexFile); if (!pkTexture) return; SetTexture(pkTexture); } void TrailEffect::SetTexture(NiTexture* pkTexture) { NiTexturingProperty* pkTexturingProp = (NiTexturingProperty*)m_pkTriShape->GetProperty(NiProperty::TEXTURING); if (!pkTexturingProp) pkTexturingProp = NiNew NiTexturingProperty; if (!pkTexturingProp) { NIASSERT(0); return; } pkTexturingProp->SetBaseTexture(pkTexture); } void TrailEffect::UpdateEffect(float fTimeLine, float fDeltaTime) { if (GetElapsed() >= m_fTotal) { Deactivate(); return; } Sample(fTimeLine); } void TrailEffect::RenderEffect(const NiCamera* pkCamera) { if (!m_spEffectNode) return; SceneMgr->RenderObject(m_spEffectNode); } void TrailEffect::Sample(float fTime) { if (!m_spBindObject) return; float fElapsed = GetElapsed(); const NiPoint3& samplePointTop = m_spBindObject->GetWorldTranslate(); NiPoint3 samplePointBottom = (m_spBindObject->GetWorldRotate() * m_kAxis * m_fWidth) + m_spBindObject->GetWorldTranslate(); //NiPoint3 samplePointBottom( m_spBindObject->GetWorldRotate() * m_kAxis * m_fWidth ); //samplePointBottom += m_spBindObject->GetWorldTranslate(); if ( m_fWidth < 0.0f || m_fWidth > 2.0f) m_fWidth = 0.0f; m_kTopRibbon.Add3DPoint(fElapsed, samplePointTop.x, samplePointTop.y, samplePointTop.z); m_kBtmRibbon.Add3DPoint(fElapsed, samplePointBottom.x, samplePointBottom.y, samplePointBottom.z); if( m_kTopRibbon.GetPointCount() > 1000 || m_kBtmRibbon.GetPointCount() > 1000 ) { Deactivate(); return; } if (m_kTopRibbon.GetPointCount() >= 2) { NiPoint3* pkVerts = m_pkTriShape->GetVertices(); NiPoint2* pkTextures = m_pkTriShape->GetTextures(); NiColorA* pkColors = m_pkTriShape->GetColors(); float afTopPoints[NUM_SCANLINE * 3], afBtmPoints[NUM_SCANLINE * 3]; if (!m_kTopRibbon.Get3DPoints(fElapsed, m_fDelay, NUM_SCANLINE, afTopPoints)) return; if (!m_kBtmRibbon.Get3DPoints(fElapsed, m_fDelay, NUM_SCANLINE, afBtmPoints)) return; int iWriteIndex = 0; for (unsigned ui = 0; ui < NUM_SCANLINE; ui++) { uint32 n = ui * 3; NiPoint3 kTop(afTopPoints[n], afTopPoints[n+1], afTopPoints[n+2]); NiPoint3 kBottom(afBtmPoints[n], afBtmPoints[n+1], afBtmPoints[n+2]); float fLenth = (kBottom - kTop).Length(); if ( fLenth >= 1.0f ) return; pkVerts[iWriteIndex].x = afTopPoints[n]; pkVerts[iWriteIndex].y = afTopPoints[n+1]; pkVerts[iWriteIndex].z = afTopPoints[n+2]; ++iWriteIndex; pkVerts[iWriteIndex].x = afBtmPoints[n]; pkVerts[iWriteIndex].y = afBtmPoints[n + 1]; pkVerts[iWriteIndex].z = afBtmPoints[n + 2]; ++iWriteIndex; } //Call MarkAsChanged to inform the renderer to repack. NiTriShapeDynamicData* pkData = (NiTriShapeDynamicData*)(m_pkTriShape-> GetModelData()); pkData->SetActiveTriangleCount(NUM_DOUBLE_SCANLINE - 2); pkData->SetActiveVertexCount(NUM_DOUBLE_SCANLINE); pkData->MarkAsChanged(NiGeometryData::VERTEX_MASK | NiGeometryData::TEXTURE_MASK | NiGeometryData::COLOR_MASK); //Update the bound for proper sorting and culling. NiBound kBound; kBound.ComputeFromData(NUM_DOUBLE_SCANLINE, pkVerts); m_pkTriShape->SetModelBound(kBound); m_pkTriShape->Update(0.0f, false); } }