- Author
- Владимир Маковецкий
Создание базового класса, добавляем пункт в меню
В этом примере мы рассмотрим как создать эффект для обработки слоев рисования. Итак созданим папку нашего модуля также как и в предидущем уроке, только сменим название на PaintEffectTutorial. Помним о создании также всех необходимых файлов проекта, в нашем случае это файл хидера и основного кода (PaintEffectTutorial.cpp и PaintEffectTutorial.h).
Рассмотрим пример кода для создания минимального набора, который создаст только пункт меню, но еще не будет выполнять никаких действий.
Код из файла хидера:
#pragma once
class PaintEffectTutorial :public BasicTool{
public:
static PaintEffectTutorial* m_PaintEffectTutorial;
virtual void Activate();
virtual const char* GetHint(){
return "PAINTEFFECT_TOOL_HINT";
}
virtual const char* GetMessage(){
return "PAINTEFFECT_TOOL";
}
virtual bool CheckIfInToolPanel(){ return false; }
virtual int GetNumCommands(){ return 1; }
virtual void PerformCommand(int idx){ Activate(); };
virtual const char* GetCommandMessage(int idx){ return GetMessage(); }
virtual const char* GetCommandHint(int idx){ return GetHint(); }
virtual int GetMenuItemCategoty(int idx){ return 2; }
};
Код из файла CPP:
#include "../stdafx.h"
#include "PaintEffectTutorial.h"
PaintEffectTutorial* PaintEffectTutorial::m_PaintEffectTutorial;
void PaintEffectTutorial::Activate(){
}
void InitPaintEffectTutorial(){
PaintEffectTutorial::m_PaintEffectTutorial = new PaintEffectTutorial();
BasicTool::InstallTool(PaintEffectTutorial::m_PaintEffectTutorial, "PaintEffectTutorial");
}
CallItLater _PaintEffectTutorial(&InitPaintEffectTutorial, BASIC_TOOL);
После сборки и запуска 3DCoat видим:
Обработка слоя в режиме попиксельного рисования
В качестве примера сделаем все каналы слоя наполовину красными, шероховатыми диэлектриками. В файл cpp добавим в функцию Activate
след. код:
MapQuadRef mapQuadRef;
mapQuadRef.NeedSpecificLayer = PMS.CurrentLayerID;
OneLayerInfo* layerInfo = PMS.GetLayer(PMS.CurrentLayerID);
int FacesCount = PMS.FacesInfo.GetAmount();
if (PMS.VertsUV.GetAmount() > 5)
for (int faceID = 0; faceID < FacesCount; faceID++){
FaceInfo* faceInfo = &PMS.FacesInfo[faceID];
int UVIdx = faceInfo->uvIdx;
if (faceInfo->Visible && faceInfo->Editable){
if (faceInfo->isPPP){
ModelPointsScope* modelPointsScope = PMS.GetMPS(faceInfo->RTIdx);
if (modelPointsScope){
if (modelPointsScope->GetQuadRef(mapQuadRef, iUVPX.x, iUVPX.y, true, true, true)){
if (!mapQuadRef.LR){
mapQuadRef.LR = mapQuadRef.mq->AddLayerRef(&PMS, layerInfo);
}
unsigned char* pixelColor = (unsigned char*)&mapQuadRef.LR->Points[mapQuadRef.ofs].Color;
mapQuadRef.LR->Points[mapQuadRef.ofs].Dv *= 0.5;
mapQuadRef.LR->Points[mapQuadRef.ofs].Metalness *= 0.5;
mapQuadRef.LR->Points[mapQuadRef.ofs].SpecMask *= 0.5;
mapQuadRef.LR->Points[mapQuadRef.ofs].Specular *= 0.5;
pixelColor[0] = pixelColor[0] / 2;
pixelColor[1] = pixelColor[1] / 2;
pixelColor[2] = (pixelColor[2] + 255) / 2;
pixelColor[3] = (pixelColor[3] + 255) / 2;
}
} EndUVTriPxForeach
}
}
}
}
PMS.InvalidateLayer(PMS.CurrentLayerID);
PMS.SetAllDirty();
PMS.UpdateDirtyFaces(false);
Результат работы эффекта:
Создание того же эффекта в режиме pTex
Добавим код программы к существующему, но вданом случае для создания того же эффекта что и выше, но уже в режиме pTex. Добавим код функции Activate
перед строкой PMS.InvalidateLayer(PMS.CurrentLayerID)
:
for (int faceID = 0; faceID < FacesCount; faceID++){
FaceInfo* faceInfo = &PMS.FacesInfo[faceID];
if (!faceInfo->isPPP && faceInfo->Visible && faceInfo->Editable && faceInfo->Points){
OneLayerPoint* lp = PMS.GetCurrentLayer(faceID)->Points;
for (int y = 0; y<faceInfo->SubSizeY; y++){
for (int x = 0; x<faceInfo->SubSizeX; x++){
byte* pixelColor = (byte*)&lp->Color;
pixelColor[0] = pixelColor[0] / 2;
pixelColor[1] = pixelColor[1] / 2;
pixelColor[2] = (pixelColor[2] + 255) / 2;
pixelColor[3] = (pixelColor[3] + 255) / 2;
lp->Transparency = (lp->Transparency + 1.0f) / 2.0f;
lp->EffectDisplacement /= 2.0f;
lp->Dv /= 2.0f;
lp->Metallness /= 2.0f;
lp->SpecOpacity /= 2.0f;
lp++;
}
}
PMS.CalcFaceAttributesWithLayers(faceID);
}
}
Результат работы:
Создание того же эффекта в сюрфейсном режиме
Расмотрим код программы, необходимый для нашего эффекта в сюрфейсном режиме:
for (int objectId = 0; objectId < VORenderQueue::LastVisTree.GetAmount(); objectId++){
vo->MarkDirtyCell(T->V1, T->V2, T->V3, true, true);
VoxLayer* vl = vc->
Attr->Insertlayer(layerInfo->LayerID);
for (int k = 0; k < nv; k++){
byte* pixelColor = (byte*)&vl->Color[k];
pixelColor[0] = pixelColor[0] / 2;
pixelColor[1] = pixelColor[1] / 2;
pixelColor[2] = (pixelColor[2] + 255) / 2;
pixelColor[3] = (pixelColor[3] + 255) / 2;
if (vl->Specular.GetAmount() > k){
byte* specParams = (byte*)&vl->Specular[k];
specParams[0] /= 2;
specParams[1] /= 2;
specParams[2] /= 2;
specParams[3] /= 2;
}
if (vl->resMetall.GetAmount() > k) vl->resMetall[k] /= 2;
}
}
}scan_end;
}
Результат в сюрфейсном режиме:
Поздравляем! Ты научился создавать свои эффекты в 3DCoat)
Исходники
Исходники этого проекта можешь запросто скачать по ссылке.
- See Also
- Работа с VoxelExtension или Создание своего инструмента в 3DCoat
-
Настройка IDE для сборки проекта
-
Работа с UI 3DCoat