1.) Я думаю, что проблема, с которой вы сталкиваетесь, связана с попыткой поместить слишком много в базовый класс.Поскольку Модель должна знать, с каким конкретным типом материала она работает при вызове функции SetPerFrameInfo, почему бы просто не дать каждому производному от материала классу свою собственную функцию Set .. (), которая принимает правильный тип вместо void *?Поскольку базовый класс Material не имеет возможности взаимодействовать с информацией за кадр (это void *), то зачем обобщать его в базовый класс?
2.) Просто укажите материал, специфичный для материала.камеры данных в производные классы материалов.Я предполагаю, что каждый экземпляр Material соответствует уникальной модели, поэтому информация о материале для этой модели должна быть в классе, производном от материала.
В ответ на ваше разъяснение:
Хорошо, я неправильно понял отношения между двумя классами.По сути, в идеальном сценарии вам нужен набор классов Материалов, которые не знают деталей Модели, и набор Моделей, которые могут работать с любым Материалом, не зная деталей Материала.Поэтому вы можете захотеть применить экземпляр материала Rough к шести различным моделям.
Я не думаю, что возникает вопрос, если каждый экземпляр материала используется несколькими моделями, а каждый экземпляр модели ничего не знает о различных материалах.третий объект для каждой модели необходим для хранения таймеров или любых других данных экземпляра, необходимых для рисования.Таким образом, каждая Модель получает свой собственный объект AppliedMaterial, который указывает на совместно используемый экземпляр Material, а также на элементы данных, необходимые для применения материала к этой модели.Для каждого типа материала должен быть свой подкласс AppliedMaterial, в котором хранятся значения данных, относящиеся к каждому материалу.Пример использования третьего объекта контекста:
struct GlossMaterialContext
{
Timer t;
int someContextValue;
};
class GlossMaterial : Material
{
void * NewApplicator() { return new GlossMaterialContext; }
void FreeApplicator(void *applicator) { delete (GlossMaterialContext*)applicator; }
void ApplyMaterial(void *applicator)
{
// Set up shader...
// Apply texture...
}
};
class 3DModel
{
Material *material;
void *materialContext;
void SetMaterial(Material *m)
{
material = m;
materialContext = m->NewApplicator();
}
void Draw()
{
material->ApplyMaterial(materialContext);
}
};
Это не невероятно чистая техника.Я всегда чувствую, что иметь дело с указателями void * - это клудж.Вы также можете иметь третий объект контекста на основе класса, например:
class AppliedGlossMaterial : AppliedMaterial
и:
class GlossMaterial : Material
{
AppliedMaterial * NewApplicator() { return new AppliedGlossMaterial; }
...
Если камеры данных зависят от и Модельтип и тип материала, то ваши модели и материалы слишком тесно связаны, чтобы разделить их на отдельные классы, которые, как предполагается, ничего не знают друг о друге.Вам нужно будет создать подклассы вашей модели: Glossy3DModel, Rough3DModel и т. Д.