Какой смысл подразделять геометрию в вашем примере с кубом? Куб - это просто экземпляр Geometry, который имеет определенный набор треугольников и индексов. Не будет никакой разницы между классом Cube и классом Sphere, за исключением того, что они заполняют свои буферы треугольника / индекса разными данными. Таким образом, здесь важны сами данные. Вам нужен способ, позволяющий пользователю предоставлять вашему движку различные данные формы, а затем каким-то образом ссылаться на эти данные после его создания.
Для предоставления данных формы у вас есть два варианта. Вы можете решить, сохранять ли детали Geometry частными, и предоставить некоторый интерфейс, который принимает необработанные данные, такие как строки из файла, или массив с плавающей точкой, заполненный некоторой пользовательской функцией, создает экземпляр Geometry для этих данных и затем дает Пользователь использует некоторый дескриптор этого экземпляра (или позволяет пользователю указать дескриптор). Или вы можете создать некоторый класс, такой как GeometryInfo, который имеет методы addTriangle, addVertex и т. Д., Которые пользователь сам заполняет, а затем иметь некоторую функцию, которая принимает GeometryInfo, создает экземпляр Geometry для этих данных и затем снова дает пользователю некоторый дескриптор.
В обеих ситуациях вам необходимо предоставить некоторый интерфейс, который позволит пользователю сказать «вот некоторые данные, сделать из них что-то и дать им некоторую обработку. Как минимум, это будет иметь функцию, как я описал. Вам нужно будет поддерживать сопоставить где-нибудь созданные экземпляры Geometry в вашем движке, чтобы вы применяли один экземпляр к правилу формы и могли связать то, что хочет пользователь ("Ball", "Cube") с тем, что нужно вашему движку (Geometry с заполненными буферами ).
Теперь о ручке. Я бы либо позволил пользователю связать данные с именем, например «Ball», либо вернул некоторое целое число, которое пользователь затем связал бы с определенным экземпляром «Ball». Таким образом, когда вы создаете свой класс Rocket, пользователь может затем запросить экземпляр «Ball» из вашего движка, различные другие объекты могут использовать «Ball», и все в порядке, потому что они просто хранят ручки, а не сам мяч. Я бы не советовал хранить указатель на фактический экземпляр Geometry. Сетка не владеет геометрией, потому что она может делиться ею с другими сетками. Ему не нужен доступ к элементам геометрии, потому что средство визуализации обрабатывает грубую работу. Так что это ненужная зависимость. Единственная причина - скорость, но использование хеширования для ваших ручек будет работать так же хорошо.
Теперь несколько примеров:
Предоставление данных формы:
//option one
engine->CreateGeometryFromFile("ball.txt", "Ball");
//option two
GeometryInfo ball;
ball.addTriangle(0, 1, 0, 1);
ball.addTriangle(...);
...
engine->CreateGeometryFromInfo(ball, "Ball");
Ссылаясь на эти данные с помощью дескриптора:
class Drawable
{
std::string shape;
Matrix transform;
};
class Rocket : public Drawable
{
Rocket() { shape = "Ball";}
//other stuff here for physics maybe
};
class BallShapedEnemy : public Drawable
{
BallShapedEnemy() { shape = "Ball";}
...
}
...
...in user's render loop...
for each (drawable in myDrawables)
{
engine->Render(drawable.GetShape(), drawable.GetTransform());
}
Теперь наличие отдельного класса для каждого отдельного игрового объекта, такого как Rocket, является дискуссионным и является предметом другого вопроса, я просто сделал его похожим на ваш пример из комментария.