カスタム プリミティブ オブジェクトは、作成する前に XSILoadPlugin コールバックで登録する必要があります。このコールバックは Softimage で自己インストール プラグインがロードされたときに呼び出されます。PluginRegistrar.RegisterPrimitive メソッドを使用してカスタム プリミティブを登録できます。
SICALLBACK XSILoadPlugin(PluginRegistrar& in_reg) { in_reg.PutAuthor(L"SoftimageUser"); in_reg.PutName(L"CustomPrimitives Plug-in"); in_reg.PutVersion(1,0); // Register primitive types in_reg.RegisterPrimitive("Box"); ... }
カスタム プリミティブ オブジェクトを登録した後、GetPrim および X3DObject::AddPrimitive のようなプリミティブの作成コマンドを使用して作成することができます。 登録されたカスタム プリミティブ タイプは、プリセット引数としてコマンドに渡すことができます。
GetPrim "Box"
SICALLBACK Box_Define(const CRef& in_ref) { Context in_ctxt(in_ref); CustomPrimitive in_prim(in_ctxt.GetSource()); if(in_prim.IsValid()) { Application().LogMessage(CString("Box_Define: ") + in_prim.GetFullName()); Factory l_fact = Application().GetFactory(); double dMin = 0.01; double dMax = 10.0; CRef l_widthDef = l_fact.CreateParamDef(“Width”, CValue::siDouble, 1.0, dMin, dMax); CRef l_lengthDef = l_fact.CreateParamDef(“Length”, CValue::siDouble, 1.0, dMin, dMax); CRef l_heightDef = l_fact.CreateParamDef(“Height”, CValue::siDouble, 1.0, dMin, dMax); Parameter l_width, l_length, l_height; in_prim.AddParameter(l_widthDef, l_width); in_prim.AddParameter(l_lengthDef, l_length); in_prim.AddParameter(l_heightDef, l_height); } return CStatus::OK; } SICALLBACK Box_DefineLayout(const CRef& in_ref) { Context in_ctxt(in_ref); PPGLayout layout = in_ctxt.GetSource(); layout.Clear(); layout.AddGroup("Box Group"); layout.AddItem(“Width”, "Half-Width"); layout.AddItem(“Length”, "Half-Length"); layout.AddItem(“Height”, "Half-Height"); layout.AddButton("ConvertGeom", "Convert to PolygonMesh"); layout.AddButton("CloseTheInspector", "Close the Inspector"); layout.EndGroup(); return CStatus::OK; }
SICALLBACK Box_PPGEvent(const CRef& in_ref) { PPGEventContext in_ctxt(in_ref); switch (in_ctxt.GetEventID()) { case siOnInit: { CustomPrimitive primitive = in_ctxt.GetSource(); Application().LogMessage(CString("Box_PPGEvent: OnInit: " + primitive.GetName())); break; } case siOnClosed: { CustomPrimitive primitive = in_ctxt.GetSource(); Application().LogMessage(CString("Box_PPGEvent: siOnClosed: " + primitive.GetName())); break; } case siParameterChange: { Parameter changed = in_ctxt.GetSource(); CustomPrimitive primitive = changed.GetParent(); CString paramName = changed.GetScriptName(); // Show that it is possible to change a value in the callback. // Note that the Draw() call might see the intermediary value before // it is changed this way. if (paramName == kWidthName) { primitive.PutParameterValue(kHeightName, changed.GetValue()); } else if (paramName == kHeightName) { primitive.PutParameterValue(kWidthName, changed.GetValue()); } Application().LogMessage(CString("Box_PPGEvent: siParameterChange: " + primitive.GetName() + CString("/") + paramName + CString(" = ") + changed.GetValue().GetAsText())); break; } ... } return CStatus::OK; }
SICALLBACK Box_Draw(const CRef& in_ref) { Context in_ctxt(in_ref); CustomPrimitive in_prim(in_ctxt.GetSource()); if(!in_prim.IsValid()) { return CStatus::Fail; } // Keep a cache of primitive data. Box_CachedData& data = g_Cache.Get(in_prim); double boxHalfWidth = data.halfWidth; double boxHalfLength = data.halfLength; double boxHalfHeight = data.halfHeight; // Draw Box ::glBegin(); ... ::glEnd(); return CStatus::OK; }
バウンディング ボックスは、カスタム プリミティブ オブジェクトの簡易版に相当し、特定の処理でのパフォーマンスを向上させるために使用されます。BoundingBox コールバックは、カスタム プリミティブのバウンディング ボックスを返します。
SICALLBACK Box_BoundingBox(const CRef& in_ref) { Context in_ctxt(in_ref); CustomPrimitive in_prim(in_ctxt.GetSource()); if(!in_prim.IsValid()) { return CStatus::Fail; } // Keep a cache of primitive data. Box_CachedData& data = g_Cache.Get(in_prim); double boxHalfWidth = data.halfWidth; double boxHalfHeight = data.halfHeight; double boxHalfLength = data.halfLength; in_ctxt.PutAttribute("LowerBoundX", -boxHalfWidth); in_ctxt.PutAttribute("LowerBoundY", -boxHalfHeight); in_ctxt.PutAttribute("LowerBoundZ", -boxHalfLength); in_ctxt.PutAttribute("UpperBoundX", boxHalfWidth); in_ctxt.PutAttribute("UpperBoundY", boxHalfHeight); in_ctxt.PutAttribute("UpperBoundZ", boxHalfLength); return CStatus::OK; }
他のインプリシット プリミティブと同じように、カスタム プリミティブ オブジェクトは、SIConvert コマンドまたは CreatePrim コマンドのいずれかを使用してジオメトリに変換することができます。Softimage 2014 では、カスタム プリミティブ オブジェクトはポリゴンメッシュにのみ変換することができます。
SICALLBACK Box_ConvertToGeom(const CRef& in_ref) // // This callback is invoked when the SIConvert or CreatePrim commands are run // for a custom primitive object. // { CustomPrimitiveContext in_ctxt(in_ref); CustomPrimitive in_prim(in_ctxt.GetSource()); if(!in_prim.IsValid()) { return CStatus::Fail; } Box_CachedData& data = g_Cache.Get(in_prim); double boxHalfWidth = data.halfWidth; double boxHalfHeight = data.halfHeight; double boxHalfLength = data.halfLength; double boxMinPt[3]; double boxMaxPt[3]; boxMinPt[0] = -boxHalfWidth; boxMinPt[1] = -boxHalfHeight; boxMinPt[2] = 0; boxMaxPt[0] = boxHalfWidth; boxMaxPt[1] = boxHalfHeight; boxMaxPt[2] = 0; Geometry out_geo = in_ctxt.GetGeometry(); // PolygonMesh support PolygonMesh out_mesh(out_geo); if(out_mesh.IsValid()) { // Convert to polygon MATH::CVector3Array out_verts; CLongArray out_faces; int index = 0; for (int i = -boxHalfLength; i <= boxHalfLength; ++i) { MATH::CVector3 vMinXMinY(-boxHalfWidth, -boxHalfHeight, 1.0 * i); MATH::CVector3 vMinXMaxY(-boxHalfWidth, boxHalfHeight, 1.0 * i); MATH::CVector3 vMaxXMinY(boxHalfWidth, -boxHalfHeight, 1.0 * i); MATH::CVector3 vMaxXMaxY(boxHalfWidth, boxHalfHeight, 1.0 * i); out_verts.Add(vMinXMinY); out_verts.Add(vMinXMaxY); out_verts.Add(vMaxXMaxY); out_verts.Add(vMaxXMinY); out_faces.Add(4); // Vertex count for tri out_faces.Add(index + 0); out_faces.Add(index + 1); out_faces.Add(index + 2); out_faces.Add(index + 3); index += 4; } return out_mesh.Set(out_verts, out_faces); } }
ConvertToGeom コールバックでは、ジオメトリはコールバックのコンテキストにアタッチされます。変換の結果を使用してジオメトリを更新することができます。
詳細については、SDK ワークグループのカスタム プリミティブのサンプル(<your_installation_folder>¥Softimage2014¥XSISDK¥examples¥workgroup¥Addons¥CustomPrimitive)を参照してください。
カスタム プリミティブ ウィザードを使用して、カスタム プリミティブ オブジェクトを含む自己インストール プラグインのコードを作成することができます。 カスタム プリミティブ ウィザードにアクセスするには、[プラグイン マネージャ] [ファイル] [新規] [プリミティブ] を選択します。