OpenSubdiv/opensubdiv/osdutil/drawController.h

182 lines
7.3 KiB
C
Raw Normal View History

2013-05-10 02:18:05 +00:00
//
// Copyright 2013 Pixar
2013-05-10 02:18:05 +00:00
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
2013-05-10 02:18:05 +00:00
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
2013-05-10 02:18:05 +00:00
//
// You may obtain a copy of the Apache License at
2013-05-10 02:18:05 +00:00
//
// http://www.apache.org/licenses/LICENSE-2.0
2013-07-18 21:19:50 +00:00
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
2013-05-10 02:18:05 +00:00
//
#ifndef OSDUTIL_DRAW_CONTROLLER_H
#define OSDUTIL_DRAW_CONTROLLER_H
2013-05-10 02:18:05 +00:00
#include "../version.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/*
concept DrawDelegate
{
void Begin();
void End();
void Bind(OsdUtilMeshBatchBase<DRAW_CONTEXT> *batch, EffectHandle effect);
void DrawElements(OsdDrawContext::PatchArray const &patchArray);
bool IsCombinable(EffectHandle &a, EffectHandle &b)
2013-05-10 02:18:05 +00:00
}
*/
namespace OsdUtil {
// ------------------------------------------------------------------------
// DrawCollection
// ------------------------------------------------------------------------
template <typename DRAW_ITEM_COLLECTION, typename DRAW_DELEGATE>
void DrawCollection(DRAW_ITEM_COLLECTION const &items, DRAW_DELEGATE *delegate) {
typedef typename DRAW_ITEM_COLLECTION::value_type DrawItem;
delegate->Begin();
2013-05-10 02:18:05 +00:00
// iterate over DrawItemCollection
for (typename DRAW_ITEM_COLLECTION::const_iterator it = items.begin(); it != items.end(); ++it) {
delegate->Bind(it->GetBatch(), it->GetEffect());
2013-05-10 02:18:05 +00:00
// iterate over sub items within a draw item
OsdDrawContext::PatchArrayVector const &patchArrays = it->GetPatchArrays();
for (OsdDrawContext::PatchArrayVector::const_iterator pit = patchArrays.begin(); pit != patchArrays.end(); ++pit) {
delegate->DrawElements(*pit);
2013-05-10 02:18:05 +00:00
}
delegate->Unbind(it->GetBatch(), it->GetEffect());
2013-05-10 02:18:05 +00:00
}
delegate->End();
2013-05-10 02:18:05 +00:00
}
// ------------------------------------------------------------------------
struct PatchArrayCombiner {
typedef std::map<OsdDrawContext::PatchDescriptor, OsdDrawContext::PatchArrayVector> Dictionary;
2013-05-10 02:18:05 +00:00
struct PatchArrayComparator {
bool operator() (OsdDrawContext::PatchArray const &a, OsdDrawContext::PatchArray const &b) {
return a.GetDescriptor() < b.GetDescriptor() or ((a.GetDescriptor() == b.GetDescriptor()) and
(a.GetVertIndex() < b.GetVertIndex()));
}
};
// XXX: reconsider this function
template <typename DRAW_ITEM_COLLECTION, typename BATCH, typename EFFECT_HANDLE>
void emit(DRAW_ITEM_COLLECTION &result, BATCH *batch, EFFECT_HANDLE &effect) {
2013-05-10 02:18:05 +00:00
if (dictionary.empty()) return;
typename DRAW_ITEM_COLLECTION::value_type item(batch, effect);
for (Dictionary::iterator it = dictionary.begin(); it != dictionary.end(); ++it) {
if (it->second.empty()) continue;
// expecting patchArrays is already sorted mostly.
std::sort(it->second.begin(), it->second.end(), PatchArrayComparator());
for (OsdDrawContext::PatchArrayVector::iterator pit = it->second.begin(); pit != it->second.end(); ++pit) {
if (not item.GetPatchArrays().empty()) {
OsdDrawContext::PatchArray &back = item.GetPatchArrays().back();
if (back.GetDescriptor() == pit->GetDescriptor() &&
back.GetVertIndex() + back.GetNumIndices() == pit->GetVertIndex()) {
// combine together
back.SetNumPatches(back.GetNumPatches() + pit->GetNumPatches());
continue;
}
}
// append to item
item.GetPatchArrays().push_back(*pit);
}
}
result.push_back(item);
for (Dictionary::iterator it = dictionary.begin(); it != dictionary.end(); ++it) {
it->second.clear();
2013-05-10 02:18:05 +00:00
}
}
void append(OsdDrawContext::PatchArray const &patchArray) {
dictionary[patchArray.GetDescriptor()].push_back(patchArray);
2013-05-10 02:18:05 +00:00
}
Dictionary dictionary;
};
// ------------------------------------------------------------------------
// OptimizeDrawItem
// ------------------------------------------------------------------------
template <typename DRAW_ITEM_COLLECTION, typename DRAW_DELEGATE>
2013-05-10 02:18:05 +00:00
void OptimizeDrawItem(DRAW_ITEM_COLLECTION const &items,
DRAW_ITEM_COLLECTION &result,
DRAW_DELEGATE *delegate) {
2013-05-10 02:18:05 +00:00
typedef typename DRAW_ITEM_COLLECTION::value_type DrawItem;
if (items.empty()) return;
2013-05-10 02:18:05 +00:00
result.reserve(items.size());
typename DrawItem::BatchBase *currentBatch = items[0].GetBatch();
typename DrawItem::EffectHandle const *currentEffect = &(items[0].GetEffect());
2013-05-10 02:18:05 +00:00
PatchArrayCombiner combiner;
for (typename DRAW_ITEM_COLLECTION::const_iterator it = items.begin(); it != items.end(); ++it) {
typename DrawItem::BatchBase *batch = it->GetBatch();
typename DrawItem::EffectHandle const &effect = it->GetEffect();
if (currentBatch != batch or
(not delegate->IsCombinable(*currentEffect, effect))) {
2013-05-10 02:18:05 +00:00
// emit cached draw item
combiner.emit(result, currentBatch, *currentEffect);
2013-05-10 02:18:05 +00:00
currentBatch = batch;
currentEffect = &effect;
2013-05-10 02:18:05 +00:00
}
// merge consecutive items if possible. This operation changes drawing order.
// i.e.
// PrimA-Regular, PrimA-Transition, PrimB-Regular, PrimB-Transition
// becomes
// PrimA-Regular, PrimB-Regular, PrimA-Transition, PrimB-Transition
OsdDrawContext::PatchArrayVector const &patchArrays = it->GetPatchArrays();
for (OsdDrawContext::PatchArrayVector::const_iterator itp = patchArrays.begin(); itp != patchArrays.end(); ++itp) {
if (itp->GetNumPatches() == 0) continue;
// insert patchArrays into dictionary
combiner.append(*itp);
}
}
// pick up after
combiner.emit(result, currentBatch, *currentEffect);
2013-05-10 02:18:05 +00:00
}
};
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif /* OSDUTIL_DRAW_CONTROLLER_H */