通常、データベースのグラフィックベクトル化中、ベクトライザーは、レンダリングデバイスに設定されたカラーパレットを使用して、インデックス付きカラー(.dwgデータベースのACIカラーインデックス、.dgnデータベースのDgnIndexカラーなど)を解決します。場合によっては(特定のオブジェクトの場合)、このパレットを完全にまたは部分的にオーバーライドする必要があるかもしれません。たとえば、この機能は、異なる色を持つブロックコンテンツの再作成を回避し、代わりに異なるパレット色でブロックを描画するために、ブロック挿入のベクトル化に役立つ場合があります。
パレットオーバーライドには、OdGiSubEntityTraitsクラスに2つの新しいメソッドがあります。
virtual bool pushPaletteOverride(const OdGiPalette* pOverride);
および
virtual void popPaletteOverride();
これら2つのメソッドは常にペアで呼び出す必要があります。描画可能なオブジェクトがパレットオーバーライドをプッシュする場合、その後でpopPaletteOverrideメソッドを呼び出す必要があります。これは、安定したベクトル化結果を維持するために重要です。
エンティティベクトル化中のパレットオーバーライドの使用
この例では、描画可能なグラフィック出力でパレットオーバーライドを使用する方法を示します。
bool subWorldDraw(OdGiWorldDraw* pWd) const
{ // Create palette override
OdGiPalettePtr pPalette = OdGiPalette::createDynamic();
// Set first palette color (typically red for ACI) as blue.
pPalette->setColor(1, ODRGB(0, 0, 255));
// Inform palette that we will use this color for overriding.
pPalette->setEntryActivity(1, true);
// Set fifth palette color (typically blue for ACI) as red.
pPalette->setColor(5, ODRGB(255, 0, 0));
// Inform palette that we will use this color for overriding.
pPalette->setEntryActivity(5, true);
// Set up palette override
pWd->subEntityTraits().pushPaletteOverride(pPalette);
// Draw some geometry
pWd->subEntityTraits().setColor(1);
pWd->geometry().circle(OdGePoint3d::kOrigin, 10.0, OdGeVector3d::kZAxis);
pWd->subEntityTraits().setColor(5);
pWd->geometry().circle(OdGePoint3d::kOrigin, 15.0, OdGeVector3d::kZAxis);
// Disable palette override
pWd->subEntityTraits().popPaletteOverride(pPalette);
return true;
}
この例では、パレット内の2つの色のみがオーバーライドされます。最初の色(以前は赤でした)は青にオーバーライドされ、5番目の色(以前は青でした)は赤にオーバーライドされます。その後、パレットオーバーライドをパレットオーバーライドスタックにプッシュし、2つの円を描画します。小さい円は青で描画され、もう1つの円は赤で描画されます。パレットオーバーライドを無効にすると、色が交換されます。
このコードは、デストラクタでpopPaletteOverrideメソッドを自動的に呼び出す特別なヘルパーを使用して簡素化できます。このヘルパーは、ジオメトリ描画のソースコードに多くの分岐が含まれている場合に非常に役立ちます。
// Set up palette override
OdGiPaletteOverrideHelper poh(pWd->subEntityTraits(), *pPalette);
// Draw some geometry
pWd->subEntityTraits().setColor(1);
pWd->geometry().circle(OdGePoint3d::kOrigin, 10.0, OdGeVector3d::kZAxis);
pWd->subEntityTraits().setColor(5);
pWd->geometry().circle(OdGePoint3d::kOrigin, 15.0, OdGeVector3d::kZAxis);
return true;
}
このユースケースは可能ですが、このコンテキストではジオメトリ描画に他のカラーインデックスを単純に使用できるため、あまり役立ちません。パレットオーバーライドが役立つ最適なユースケースは、オブジェクト自体を変更せずに、他の(すでに利用可能な)オブジェクトをオーバーライドされた色で描画する場合です。
たとえば、カスタムエンティティからオーバーライドされたパレット色でブロックを描画できます。
// Set up palette override
OdGiPaletteOverrideHelper poh(pWd->subEntityTraits(), *pPalette);
// Draw some geometry
OdDbDatabasePtr pDb(pWd->context()->database());
pWd->geometry().draw(OdDbBlockTable::cast(pDb->getBlockTableId().openObject())->getAt(OD_T("TestBlock"), OdDb::kForRead));
オーバーライドを伴うパレットオーバーライドの使用
パレットオーバーライドをオーバーライド機能と組み合わせて使用し、ベクトル化されるデータベース内のオブジェクトのすべてまたは一部のパレットをオーバーライドします。
class BlockRefDrawableOverrule : public OdGiDrawableOverrule
{
public:
BlockRefDrawableOverrule()
{
OdRxOverrule::setIsOverruling(true);
// Attach overrule to OdDbBlockReference entity
OdRxOverrule::addOverrule(OdDbBlockReference::desc(), this);
}
~BlockRefDrawableOverrule()
{
OdRxOverrule::removeOverrule(OdDbBlockReference::desc(), this);
OdRxOverrule::setIsOverruling(false);
}
virtual bool isApplicable(const OdRxObject* /*pOverruledSubject*/) const { return true; }
virtual bool worldDraw(const OdGiDrawable* pSubject, OdGiWorldDraw *wd)
{
OdGiPalettePtr pPalette;
// Since subSetAttributes for drawable already called we can get current drawable layer from subEntityTraits
OdDbStub *layerId = wd->subEntityTraits().layer();
OdDbBlockTableRecordPtr pLayer = OdDbObjectId(layerId).openObject();
if (pLayer->getName() == OD_T("Layer1"))
{ // Set inverted palette for block references onto Layer1.
pPalette = OdGiPalette::createDynamic();
for (OdUInt32 nClr = 0; nClr < 256; nClr++)
{
ODCOLORREF clr = OdCmEntityColor::lookUpRGB((OdUInt8)nClr);
clr = ODRGB(ODGETBLUE(clr), ODGETGREEN(clr), ODGETRED(clr));
clr = (clr & 0xFF000000) | (~clr & 0x00FFFFFF); // Invert color avoiding alpha channel
pPalette->setColor((OdInt32)nClr, clr);
pPalette->setEntryActivity((OdInt32)nClr, true);
}
}
else if (pLayer->getName() == OD_T("Layer2"))
{ // Set palette which exchanges blue and red color channels for block references onto Layer2.
pPalette = OdGiPalette::createDynamic();
for (OdUInt32 nClr = 0; nClr < 256; nClr++)
{
ODCOLORREF clr = OdCmEntityColor::lookUpRGB((OdUInt8)nClr);
clr = ODRGB(ODGETBLUE(clr), ODGETGREEN(clr), ODGETRED(clr));
// Exchange red and blue color channels.
clr = (clr & 0xFF00FF00) | ((clr & 0x00FF0000) >> 16) | ((clr & 0x000000FF) << 16);
pPalette->setColor((OdInt32)nClr, clr);
pPalette->setEntryActivity((OdInt32)nClr, true);
}
}
else if (pLayer->getName() == OD_T("Layer3"))
{ // Set grayscale palette override for block references onto Layer3
pPalette = OdGiPalette::createDynamic();
// Override first 8 palette colors using grayscale colors gradient.
pPalette->install(OdGiGrayRamp::createDynamic(8));
}
// Set up palette override
if (!pPalette.isNull())
wd->subEntityTraits().pushPaletteOverride(pPalette);
// Call subWorldDraw of original entity
const bool bResult = OdGiDrawableOverrule::worldDraw(pSubject, wd);
// Pop palette override
if (!pPalette.isNull())
wd->subEntityTraits().popPaletteOverride();
return bResult;
}
};
このクラスは、コンストラクタでオーバーライドを有効にし、デストラクタで無効にします。ベクトル化される各ブロック参照について、worldDrawメソッドが呼び出され、パレットオーバーライドをパレットオーバーライドスタックに配置し、元のエンティティ描画メソッドを呼び出し、スタックからパレットオーバーライドを削除します。
この例では、元のエンティティのレイヤー名を使用して、どのパレットオーバーライドをスタックに配置する必要があるかを理解しています。これは可能なユースケースの1つです。
パレットオーバーライドを使用したレンダリングの例:
この例では、異なるネストされたエンティティに最初の6つのパレットインデックスカラーを使用するブロック参照があります(元の色は画像の左上隅に表示されています)。
「Layer1」に配置されたブロック参照の場合、パレット内の256色すべてを反転させます(結果は画像の右上隅に表示されています)。
「Layer2」に配置されたブロック参照の場合、パレットカラーの赤と青のカラーチャネルを交換します(結果は画像の左下隅に表示されます)。
「Layer3」に配置されたブロック参照の場合、グレースケールグラデーションジェネレーターを使用して、パレットオーバーライドの最初の8色を塗りつぶします(結果は画像の右下隅に表示されます)。
結論
この機能は、すべてのODAベクトル化モジュールでサポートされています。ODA 19.4中間リリース以降利用可能であり、すべてのODA製品で使用できます。