Программное создание детали в сборке

Автор Sprinter500, 26.09.19, 12:22:38

« предыдущая - следующая »

0 Пользователей и 1 гость просматривают эту тему.

Sprinter500

Добрый день, уважаемые знатоки API от Компаса! Подскажите пожалуйста, как создать в контексте сборки деталь, обычную или локальную. То так программная реализация так называемого проектирования "сверху-вниз", когда деталь создается в сборке, а не "снизу-вверх", когда сначала создаются  детали, а затем вставляются в сборку. Примеров в SDK не нашел (хотя может криво искал). Еще пробовал записать Макрос, но после записи, макрос просто создает тело внутри сборки, но не деталь.

Sprinter500

Добрый день!
Частично разобрался как создать из под сборки деталь и сохранить ее в файл. Однако пока есть некоторые загвоздки:
1. Не знаю как вместо внешней детали в сборке (файл m3d лежит отдельно) создать локальную (файла m3d нет, деталь лежит внутри файла a3d).
2. Не получается задать цвет детали внутри файла m3d, могу пока лишь внешней окрасить вставленную деталь, однако если ее потом "разрезать", то внутри будет виден стандартный серый цвет, а не заданный.
3. Также не получается задать материал и плотность детали - остается то что по-умолчанию при создании детали.

Итак, посмотрите пожалуйста где закрались ошибки. Вот код:

        public void CreateNewPart()
        {
            ksPart prt = (ksPart)doc3D.GetPart((short)Part_Type.pTop_Part);  // новый компонент
            ksEntity bPlane = (ksEntity)prt.GetDefaultEntity((short)Obj3dType.o3d_planeXOY);
            ksPart part = (ksPart)doc3D.CreatePartInAssembly("111.m3d", bPlane);
            if (part != null)
            {
                part.BeginEdit();

                ksEntity entitySketch = (ksEntity)part.NewEntity((short)Obj3dType.o3d_sketch);
                if (entitySketch != null)
                {
                    // интерфейс свойств эскиза
                    ksSketchDefinition sketchDef = (ksSketchDefinition)entitySketch.GetDefinition();
                    if (sketchDef != null)
                    {
                        // получим интерфейс базовой плоскости XOY
                        ksEntity basePlane = (ksEntity)part.GetDefaultEntity((short)Obj3dType.o3d_planeXOY);
                        switch (comboBox1.SelectedIndex)
                        {
                            case 0:
                                basePlane = (ksEntity)part.GetDefaultEntity((short)Obj3dType.o3d_planeXOY);
                                break;
                            case 1:
                                basePlane = (ksEntity)part.GetDefaultEntity((short)Obj3dType.o3d_planeXOZ);
                                break;
                            case 2:
                                basePlane = (ksEntity)part.GetDefaultEntity((short)Obj3dType.o3d_planeYOZ);
                                break;
                            default:
                                basePlane = (ksEntity)part.GetDefaultEntity((short)Obj3dType.o3d_planeXOY);
                                break;
                        }

                        sketchDef.SetPlane(basePlane);  // установим плоскость базовой для эскиза
                        sketchDef.angle = 0;           // угол поворота эскиза
                        entitySketch.Create();          // создадим эскиз

                        // интерфейс редактора эскиза
                        ksDocument2D sketchEdit = (ksDocument2D)sketchDef.BeginEdit();

                        ksRectangleParam par1 = (ksRectangleParam)kompas.GetParamStruct((short)StructType2DEnum.ko_RectangleParam);
                        if (par1 != null)
                        {
                            par1.ang = 5;
                            par1.x = 10;
                            par1.y = 10;
                            par1.width = 100;
                            par1.height = 50;
                            par1.style = 1;
                            sketchEdit.ksRectangle(par1);
                        }
                        par1 = null;

                        sketchDef.EndEdit();    // завершение редактирования эскиза

                        ksEntity entityExtr = (ksEntity)part.NewEntity((short)Obj3dType.o3d_bossExtrusion);
                        if (entityExtr != null)
                        {
                            // интерфейс свойств базовой операции выдавливания
                            ksBossExtrusionDefinition extrusionDef = (ksBossExtrusionDefinition)entityExtr.GetDefinition(); // интерфейс базовой операции выдавливания
                            IExtrusion extrusion = (IExtrusion)kompas.TransferInterface(entityExtr, (int)ksAPITypeEnum.ksAPI7Dual, 0);
                            IChooseBodies7 chooseBodies = (IChooseBodies7)extrusion; // Для создания нового тела в КОМПАС-3D V15
                            chooseBodies.ChooseBodiesType = ksChooseBodiesType.ksNewBody; // Для создания нового тела в КОМПАС-3D V15
                            //IExtrusion1 extrusion1 = (IExtrusion1)extrusion; //Для 18-го Компаса
                            //extrusion1.OperationResult = ksOperationResultEnum.ksOperationNewBody; // Для 18-го Компаса
                            if (extrusionDef != null)
                            {
                                extrusionDef.directionType = (short)Direction_Type.dtNormal;         // направление выдавливания
                                extrusionDef.SetSideParam(true, // прямое направление
                                    (short)End_Type.etBlind,    // строго на глубину
                                    Val(tbDepth.Lines[0]), 0, false);
                                //extrusionDef.SetThinParam(true, (short)Direction_Type.dtBoth, 10, 10); // тонкая стенка в два направления
                                extrusionDef.SetSketch(entitySketch);   // эскиз операции выдавливания
                                entityExtr.Create();                    // создать операцию
                            }
                        }
                    }
                }
                part.SetAdvancedColor(ColorTranslator.ToWin32(Color.FromArgb(0x7FFFD4)), 0.5, 0.6, 0.8, 0.8, 1.0, 0.5);
                part.name = "Name";
                part.marking = "Marking";
                part.fixedComponent = true;
                part.SetMaterial("Материал", 3.00);
                //part.useColor = 3;

                part.EndEdit(false);
                //part.RebuildModel();
            }
            part.Update();
        }

Sabahs

21.11.19, 14:28:58 #2 Последнее редактирование: 21.11.19, 14:48:08 от Sabahs
1. IPart7.IsLocal - локальная деталь, разве не работает?
2. IPart.SetAdvancedColor.
3. IPart7.SetMaterial.

Зачем part.BeginEdit, проще открыть в невидимом режиме отредактировать, сохранить и закрыть.
part.EndEdit(false); поставить перед строкой  part.SetAdvancedColor(ColorTranslator.ToWin32(Color.FromArgb(0x7FFFD4)), 0.5, 0.6, 0.8, 0.8, 1.0, 0.5);.
Если у Вас, есть вопросы, то их можно задать тут:
- "Оборудование: Развёртки";
- "Библиотека пакетного сохранения файлов".

Sprinter500

Цитата: Sabahs от 21.11.19, 14:28:581. IPart7.IsLocal - локальная деталь, разве не работает?
2. IPart.SetAdvancedColor.
3. IPart7.SetMaterial.

Зачем part.BeginEdit, проще открыть в невидимом режиме отредактировать, сохранить и закрыть.
part.EndEdit(false); поставить перед строкой  part.SetAdvancedColor(ColorTranslator.ToWin32(Color.FromArgb(0x7FFFD4)), 0.5, 0.6, 0.8, 0.8, 1.0, 0.5);.

Спасибо, за прояснение в каком направлении двигаться дальше.
Остаются вопросы:
1. .... part.EndEdit(false); поставить перед строкой  part.SetAdvancedColor( ...    Не помогло. Цвет не поменялся. Или я что-то не так сделал или понял?
2. Вы предлагаете - "открыть, редактировать, сохранить и закрыть в невидимом режиме" вместо использования BeginEdit ... EndEdit. Как это сделать?
3. Как мне получить IPart7 от простого ksPart?.  Я попробовал так: IPart7 part7 = (IPart7)part;  но так вылазит ошибка.
4. Или надо изначально создавать компонент сборки через IPart7? В таком случае придется уже получать ksPart от IPart7 чтобы задать цвет. И это тоже не ясно пока как сделать.

Sabahs

Document:=Documents.Add(ksDocumentPart,True)
Doc3D:=Document as IKompasDocument3D;
if Doc3D<>nil then
begin
  Document3D:=IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3D),ksAPI3DCom,0)) as IDocument3D;
  pDocument3D5:=IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3D),ksAPI5Auto,0)) as ksDocument3D;
  Part7:=Doc3D.TopPart;
  if(Part7<>nil)and(Document3D<>nil)and(pDocument3D5<>nil)then
    begin
      pPart5:=ksPart(pDocument3D5.GetPart(pTop_Part));
      Part:=IPart(Document3D.GetPart(pTop_Part));
      if Part<>nil then
      begin
        Part.SetAdvancedColor(Color,Ambient,Diffuse,Specularity,Shininess,Transparency,Emission);
        Part.Update;
        Part.SetName(PWideChar(FileName_Detal));
      end;
      Part7.SetMaterial(Mat,Density);
      Part7.Marking:=Oboznacenie;
      Part7.Update;
...
Это 100% работает.
Если у Вас, есть вопросы, то их можно задать тут:
- "Оборудование: Развёртки";
- "Библиотека пакетного сохранения файлов".

Sprinter500

Цитата: Sabahs от 22.11.19, 08:25:50Document:=Documents.Add(ksDocumentPart,True)
Doc3D:=Document as IKompasDocument3D;
if Doc3D<>nil then
begin
  Document3D:=IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3D),ksAPI3DCom,0)) as IDocument3D;
  pDocument3D5:=IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3D),ksAPI5Auto,0)) as ksDocument3D;
  Part7:=Doc3D.TopPart;
  if(Part7<>nil)and(Document3D<>nil)and(pDocument3D5<>nil)then
    begin
      pPart5:=ksPart(pDocument3D5.GetPart(pTop_Part));
      Part:=IPart(Document3D.GetPart(pTop_Part));
      if Part<>nil then
      begin
        Part.SetAdvancedColor(Color,Ambient,Diffuse,Specularity,Shininess,Transparency,Emission);
        Part.Update;
        Part.SetName(PWideChar(FileName_Detal));
      end;
      Part7.SetMaterial(Mat,Density);
      Part7.Marking:=Oboznacenie;
      Part7.Update;
...
Это 100% работает.

Я так понимаю у Вас Part, pPart5 и Part7 - все берут компонент TopPart, а TopPart - в контексте сборки - это сама сборка, самый верхний узел сборки - то есть задастся цвет и материал не детали в сборке, а самой сборки. А требуется в сборке, создать деталь (желательно локальную), выставить необходимый цвет и материал, задать имя с обозначением и далее в этой же сборке добавить следующую деталь таким же способом, и так далее пока цикл работает. В итоге получаем сборку в ней несколько деталей (желательно локальных) и каждая со своим цветом и материалом.

Можете видоизменить свой код для сборки с созданием локальной детали, например детали в виде параллелепипеда любых размеров?

И еще у меня докменты3D задаются так:
        void SetActiveDoc3D()
        {
            doc3D = (ksDocument3D)kompas.ActiveDocument3D();
            doc_3D = (IKompasDocument3D)appl.ActiveDocument; // Получаем интерфейс активного документа 3D в API7
            if (doc_3D == null) MessageBox.Show("Не удалось подключиться к интерфейсу активного документа 3D в API7");
        }
У Вас несколько иначе. Это играет роль или не важно? Еще такой момент имена переменных у нас разные и это несколько сбивает с толку, когда я пытаюсь перевести код с Delphi на C# :)

Sprinter500

В ожидание ответа на вопросы в предыдущем посте сделал так:
...
            ksPart prt = (ksPart)doc3D.GetPart((short)Part_Type.pTop_Part);  // новый компонент
            ksEntity bPlane = (ksEntity)prt.GetDefaultEntity((short)Obj3dType.o3d_planeXOY);
            ksPart part = (ksPart)doc3D.CreatePartInAssembly("111.m3d", bPlane);
            IPart7 part7 = (IPart7)kompas.TransferInterface(part, (int)ksAPITypeEnum.ksAPI7Dual, 0);
            if (part != null)
            {
      //тут создание детали
            }
            part.Update();
            if (part7 != null)
            {
                IOpenDocumentParam openDocumentParam = part7.GetOpenDocumentParam();
                part7.BeginEdit((OpenDocumentParam)openDocumentParam);
                part7.Name = "Имя7";
                part7.SetMaterial("Материал", 3.00);
                part7.IsLocal = true;
                part7.EndEdit(false);
                part7.Update();

            }
            else MessageBox.Show("part7 = null");
...

Вот "Имя7" появляется в дереве сборки у создаваемой детали (правда в самом файле "111.m3d" так и остается им "Деталь"), а материал не меняется почему-то и локальной деталь не становится.

Sprinter500

Ох, уже столько всего перепробовал - максимум что получается поменять для детали в сборке - это ее имя (и то только внутри сборки, а в файле детали - имя не меняется). Ну и цвет с материалом для самой сборки (TopPart) получается поменять, но не для каждой отдельно взятой детали в сборке. Только какой смысл в цвете и материале сборки, если детали могут быть разных материалов и цветов.

Sprinter500

Пошаговое воспроизведение процесса навело на мысль, что после ...part.BeginEdit() и после внесения изменений надо произвести сохранение part в файл m3d и уже потом part.EndEdit. Но как сохранить редактируемый part я не знаю - метода такого у него нет. Это в плане редактирования материала. part7 в режиме редактирования не открывается - видать надо какие то настройки в параметры задавать предварительно. Как сделать деталь локальной по прежнему не знаю - ничего не получается.

Sabahs

part.BeginEdit - возвращает указатель на документ.
Если у Вас, есть вопросы, то их можно задать тут:
- "Оборудование: Развёртки";
- "Библиотека пакетного сохранения файлов".

Sprinter500

Цитата: Sabahs от 26.11.19, 14:29:01part.BeginEdit - возвращает указатель на документ.

Ясно. А как тогда получить указатель именно на деталь, чтобы внести изменения не в шапке сборки, а непосредственно в компоненте сборке - детали?

Sabahs

Цитата: Sprinter500 от 25.11.19, 09:47:39Ох, уже столько всего перепробовал - максимум что получается поменять для детали в сборке - это ее имя (и то только внутри сборки, а в файле детали - имя не меняется). Ну и цвет с материалом для самой сборки (TopPart) получается поменять, но не для каждой отдельно взятой детали в сборке. Только какой смысл в цвете и материале сборки, если детали могут быть разных материалов и цветов.
Значит не всё перепробовали.
Loc.png
Если у Вас, есть вопросы, то их можно задать тут:
- "Оборудование: Развёртки";
- "Библиотека пакетного сохранения файлов".

Sprinter500

Цитата: Sabahs от 28.11.19, 10:23:18Значит не всё перепробовали.
Loc.png

Ну понятно, что где-то закралась ошибка в коде. Как у Вас получилось?

Sabahs

Если у Вас, есть вопросы, то их можно задать тут:
- "Оборудование: Развёртки";
- "Библиотека пакетного сохранения файлов".

Sprinter500

Цитата: Sabahs от 28.11.19, 11:44:03Как то, так.
Loc_1.png


Спасибо большое !!! Сначала сделаю также в Delphi, потом руками проконвертирую в C#. А имеет значение, что у Вас интерфейсы документов через Unknown берутся? У меня просто подключается к заранее созданной открытой сборке (как активный документ).

Sprinter500

Заметил что ближе к концу кода есть пропущенное место:

                      PartLoc:=IPart(Document3DSB.GetPart(pNew_Part));
                      if PartLoc<>nil then
                      begin
                        if Document3DSB.SetPartFromFile(PWideChar(FileNameLoc+IntToStr(J)),PartLoc,0)=1 then
                        begin
                          Part7Loc:=Parts7SB.Part[J-1];
                          if Part7Loc<>nil then
                          begin
                            // ЧТО ТУТ ДОЛЖНО БЫТЬ ???
                          end;
                        end;
                      end;


Там где закомментировано - что там по задумке должно содержаться?

Sabahs

Всё, что угодно, как минимум правильная ориентация и привязки.
Если у Вас, есть вопросы, то их можно задать тут:
- "Оборудование: Развёртки";
- "Библиотека пакетного сохранения файлов".

Sprinter500

Набрал кода сначала под Delphi, но пока на нем проверить нет возможности, сконвертировал в C#. Кроме открытия пустой ссборк ничего не происходит почему-то. Буду искать ошибку. Вот код в C#:

        void CreateAssembly()
        {
            IDocuments pDocuments = appl.Documents;
            if (pDocuments != null)
            {
                string FileNameSB = label3.Text;
                string FileNameLoc = FileNameSB;
                IKompasDocument DocumentSB = pDocuments.Add(DocumentTypeEnum.ksDocumentAssembly, true);
                if (DocumentSB != null)
                {
                    IKompasDocument3D Doc3DSB = DocumentSB as IKompasDocument3D;
                    if (Doc3DSB != null)
                    {
                        //IDocument3D Document3DSB = IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3DSB), ksAPI3DCom, 0)) as IDocument3D;
                        //ksDocument3D pDocument3D5SB = IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3DSB), ksAPI5Auto, 0)) as ksDocument3D;

                        IDocument3D Document3DSB = kompas.TransferInterface(Doc3DSB, (int)ksAPITypeEnum.ksAPI3DCom, 0) as IDocument3D;
                        ksDocument3D pDocument3D5SB = kompas.TransferInterface(Doc3DSB, (int)ksAPITypeEnum.ksAPI5Auto, 0) as ksDocument3D;

                        IPart7 Part7SB = Doc3DSB.TopPart;
                        if ((Part7SB != null) && (Document3DSB != null) && (pDocument3D5SB != null))
                        {
                            IParts7 Parts7SB = Part7SB.Parts;
                            if (Parts7SB != null)
                            {
                                IPart PartSB = Document3DSB.GetPart((short)Part_Type.pTop_Part);
                                ksPart pPart5SB = (ksPart)pDocument3D5SB.GetPart((short)Part_Type.pTop_Part);
                                if (PartSB != null)
                                {
                                    for (int J = 1; J <= 3; J++)
                                    {
                                        IKompasDocument DocumentLoc = pDocuments.Add(DocumentTypeEnum.ksDocumentPart, true);
                                        IKompasDocument3D Doc3DLoc = DocumentLoc as IKompasDocument3D;
                                        if (Doc3DLoc != null)
                                        {
                                            IDocument3D Document3DLoc = kompas.TransferInterface(Doc3DLoc, (int)ksAPITypeEnum.ksAPI3DCom, 0) as IDocument3D;
                                            ksDocument3D pDocument3D5Loc = kompas.TransferInterface(Doc3DLoc, (int)ksAPITypeEnum.ksAPI5Auto, 0) as ksDocument3D;
                                            IPart7 Part7Loc = Doc3DLoc.TopPart;
                                            if ((Part7Loc != null) && (Document3DLoc != null) && (pDocument3D5Loc != null))
                                            {
                                                ksPart pPart5Loc = (ksPart)pDocument3D5Loc.GetPart((short)Part_Type.pTop_Part);
                                                IPart PartLoc = Document3DLoc.GetPart((short)Part_Type.pTop_Part);
                                                if ((PartLoc != null) && (pPart5Loc != null))
                                                {
                                                    pPart5Loc.useColor = (int)UseColor.useColorOur;
                                                    PartLoc.SetAdvancedColor((uint)J*4000, 0.5, 0.6, 0.5, 0.8, 0.8, 1);

                                                    PartLoc.SetName("Пластилиновая деталь" + J.ToString());
                                                    Part7Loc.SetMaterial("Пластилин цветной", 0.0033);
                                                    Part7Loc.Marking = "Обозначение " + J.ToString();
                                                    Part7Loc.Update();
                                                    IModelObject PlaneLocXY = Part7Loc.DefaultObject[ksObj3dTypeEnum.o3d_planeXOY];
                                                    IModelContainer ModelContainerLoc = Part7Loc as IModelContainer;
                                                    if (ModelContainerLoc != null)
                                                    {
                                                        ISketchs SketchsLoc = ModelContainerLoc.Sketchs;
                                                        if (SketchsLoc != null)
                                                        {
                                                            ISketch SketchLoc = SketchsLoc.Add();
                                                            if (SketchLoc != null)
                                                            {
                                                                if (PlaneLocXY != null) SketchLoc.Plane = PlaneLocXY;
                                                                SketchLoc.BeginEdit();

                                                                ksRectangleParam par1 = (ksRectangleParam)kompas.GetParamStruct((short)StructType2DEnum.ko_RectangleParam);
                                                                if (par1 != null)
                                                                {
                                                                    par1.ang = 5*J;
                                                                    par1.x = 10*J;
                                                                    par1.y = 10*J;
                                                                    par1.width = 100;
                                                                    par1.height = 50;
                                                                    par1.style = 1;

                                                                    ksDocument2D sketchEdit = kompas.TransferInterface(SketchLoc, (int)ksAPITypeEnum.ksAPI5Auto, 0) as ksDocument2D;

                                                                    sketchEdit.ksRectangle(par1);
                                                                }
                                                                par1 = null;

                                                                SketchLoc.EndEdit();
                                                                IExtrusions ExtrusionsLoc = ModelContainerLoc.Extrusions;
                                                                if (ExtrusionsLoc != null)
                                                                {
                                                                    IExtrusion ExtrusionLoc = ExtrusionsLoc.Add(ksObj3dTypeEnum.o3d_bossExtrusion);
                                                                    if (ExtrusionLoc != null)
                                                                    {
                                                                        ExtrusionLoc.Sketch = (Sketch)SketchLoc;
                                                                        ExtrusionLoc.Direction = (ksDirectionTypeEnum)Direction_Type.dtBoth;
                                                                        ExtrusionLoc.ExtrusionType[false] = (ksEndTypeEnum)End_Type.etBlind;
                                                                        ExtrusionLoc.Depth[false] = 50;
                                                                        ExtrusionLoc.ExtrusionType[true] = (ksEndTypeEnum)End_Type.etBlind;
                                                                        ExtrusionLoc.Depth[true] = 50;
                                                                        ExtrusionLoc.Update();
                                                                    }
                                                                }
                                                            }
                                                            Part7Loc.Update();
                                                            Document3DLoc.RebuildDocument();
                                                            Document3DLoc.SetFileName(FileNameLoc + J.ToString());
                                                            Document3DLoc.Save();
                                                            Document3DLoc.Close();
                                                            PartLoc = Document3DSB.GetPart((short)Part_Type.pNew_Part);
                                                            if (PartLoc != null)
                                                            {
                                                                if (Document3DSB.SetPartFromFile(FileNameLoc + J.ToString(), PartLoc, 0) == 1)
                                                                {
                                                                    Part7Loc = Parts7SB.Part[I - 1];
                                                                    if (Part7Loc != null)
                                                                    {

                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }

                                                }
                                                Document3DSB.RebuildDocument();
                                                Document3DSB.SetFileName(FileNameSB);
                                                Document3DSB.Save();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

Sprinter500

Выяснил, что после
IDocument3D Document3DSB = kompas.TransferInterface(Doc3DSB, (int)ksAPITypeEnum.ksAPI3DCom, 0) as IDocument3D;

Document3DSB остается равным null.
А предыдущая строка кода вроде как нормально прорабатывается - по крайней мере pDocument3D5SB не равен null:
ksDocument3D pDocument3D5SB = kompas.TransferInterface(Doc3DSB, (int)ksAPITypeEnum.ksAPI5Auto, 0) as ksDocument3D;

Таким образом код не исполняется после проверки на null:
if ((Part7SB != null) && (Document3DSB != null) && (pDocument3D5SB != null))

где Document3DSB равен null.


Может как-то можно проще обойтись, без трансформации интерфейсов?

Sprinter500

В Delphi при компиляции проекта тоже происходит ошибка, когда в коде присутствуют строки:
        Document3DSB:=IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3DSB),ksAPI3DCom,0)) as IDocument3D;
        pDocument3D5SB:=IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3DSB),ksAPI5Auto,0)) as ksDocument3D;

Вылазит сообщение, что не найдена kAPI2D5.DLL, хотя она есть в каталоге Bin системы Компас. Возможно причина в том что Delphi подключалась еще на предыдущей версии КОМПАСа, а после установки новой надо было по новой с TLB возиться но не стали, так как и без этого все работало.

В общем можно ли как-то получить Document3DSB и pDocument3D5SB как-то иначе?