tsForestCellBatch.cpp
Engine/source/forest/ts/tsForestCellBatch.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "forest/ts/tsForestCellBatch.h" 26 27#include "forest/ts/tsForestItemData.h" 28#include "scene/sceneManager.h" 29#include "ts/tsLastDetail.h" 30 31 32TSForestCellBatch::TSForestCellBatch( TSLastDetail *detail ) 33 : mDetail( detail ) 34{ 35} 36 37TSForestCellBatch::~TSForestCellBatch() 38{ 39} 40 41bool TSForestCellBatch::_prepBatch( const ForestItem &item ) 42{ 43 // Make sure it's our item type! 44 TSForestItemData* data = dynamic_cast<TSForestItemData*>( item.getData() ); 45 if ( !data ) 46 return false; 47 48 // TODO: Eventually we should atlas multiple details into 49 // a single combined texture map. Till then we have to 50 // do one batch per-detail type. 51 52 // If the detail type doesn't match then 53 // we need to start a new batch. 54 if ( data->getLastDetail() != mDetail ) 55 return false; 56 57 return true; 58} 59 60void TSForestCellBatch::_rebuildBatch() 61{ 62 // Clean up first. 63 mVB = NULL; 64 if ( mItems.empty() ) 65 return; 66 67 // How big do we need to make this? 68 U32 verts = mItems.size() * 6; 69 mVB.set( GFX, verts, GFXBufferTypeStatic ); 70 if ( !mVB.isValid() ) 71 { 72 // If we failed it is probably because we requested 73 // a size bigger than a VB can be. Warn the user. 74 AssertWarn( false, "TSForestCellBatch::_rebuildBatch: Batch too big... try reducing the forest cell size!" ); 75 return; 76 } 77 78 // Fill this puppy! 79 ImposterState *vertPtr = mVB.lock(); 80 if(!vertPtr) return; 81 82 Vector<ForestItem>::const_iterator item = mItems.begin(); 83 84 const F32 radius = mDetail->getRadius(); 85 ImposterState state; 86 87 for ( ; item != mItems.end(); item++ ) 88 { 89 item->getWorldBox().getCenter( &state.center ); 90 state.halfSize = radius * item->getScale(); 91 state.alpha = 1.0f; 92 item->getTransform().getColumn( 2, &state.upVec ); 93 item->getTransform().getColumn( 0, &state.rightVec ); 94 95 *vertPtr = state; 96 vertPtr->corner = 0; 97 ++vertPtr; 98 99 *vertPtr = state; 100 vertPtr->corner = 1; 101 ++vertPtr; 102 103 *vertPtr = state; 104 vertPtr->corner = 2; 105 ++vertPtr; 106 107 *vertPtr = state; 108 vertPtr->corner = 2; 109 ++vertPtr; 110 111 *vertPtr = state; 112 vertPtr->corner = 3; 113 ++vertPtr; 114 115 *vertPtr = state; 116 vertPtr->corner = 0; 117 ++vertPtr; 118 } 119 120 mVB.unlock(); 121} 122 123void TSForestCellBatch::_render( const SceneRenderState *state ) 124{ 125 if ( !mVB.isValid() || 126 ( state->isShadowPass() && !TSLastDetail::smCanShadow ) ) 127 return; 128 129 // Make sure we have a material to render with. 130 BaseMatInstance *mat = state->getOverrideMaterial( mDetail->getMatInstance() ); 131 if ( mat == NULL ) 132 return; 133 134 // We don't really render here... we submit it to 135 // the render manager which collects all the batches 136 // in the scene, sorts them by texture, sets up the 137 // shader, and then renders them all at once. 138 139 ImposterBatchRenderInst *inst = state->getRenderPass()->allocInst<ImposterBatchRenderInst>(); 140 inst->mat = mat; 141 inst->vertBuff = &mVB; 142 143 // We sort by the imposter type first so that RIT_Imposter and 144 // RIT_ImposterBatches do not get mixed together. 145 // 146 // We then sort by material. 147 // 148 inst->defaultKey = 0; 149 inst->defaultKey2 = mat->getStateHint(); 150 151 state->getRenderPass()->addInst( inst ); 152} 153