mafulechka
mafulechka2 сентября 2019 г. 5:04

Представляем Qt Quick 3D: высокоуровневый 3D API для Qt Quick

Разработчики изучали, как можно глубже интегрировать 3D и Qt Quick, в результате чего создали новый проект под названием Qt Quick 3D , который предоставляет собой высокоуровневый API для создания 3D-контента для пользовательских интерфейсов из Qt Quick. Вместо того, чтобы использовать внешний движок, который может привести к проблемам синхронизации анимации и нескольким уровням абстракции, Qt Company предоставляет расширения для Qt Quick Scenegraph для 3D-контента и средство визуализации для этих расширенных узлов графа сцены.

Значит ли это, что они написали еще одно 3D Solution для Qt? Не совсем так, потому что ядро пространственного рендеринга получено из рендерера Qt 3D Studio. Этот рендерер был портирован для использования Qt для абстракции платформы и подвергся рефакторингу для соответствия стилю кодирования проекта Qt.



”Сан-Мигель” тестовая сцена, запущенная в Qt Quick 3D.

Каковы цели Qt Company? Почему другое 3D Solution?

Унифицированная графическая история

Самая важная цель - унифицировать графическую историю. В настоящее время Qt Company предлагает два комплексных решения для создания гибких пользовательских интерфейсов, каждое из которых имеет свой собственный инструментарий. Одно из этих решений - Qt Quick для 2D, другое - Qt 3D Studio для 3D. Если вы ограничиваете себя использованием одного или другого обычно все работает довольно хорошо. Однако, разработчики обнаружили, что пользователям, в конечном итоге, приходится их смешивать и сопоставлять, что выявляет много «подводных камней», как в производительности во время выполнения, так и в опыте разработчиков/дизайнеров.

Поэтому для простоты Qt Company стремится сделать одну среду выполнения (Qt Quick), один общий граф сцены (Qt Quick Scenegraph) и один инструмент проектирования (Qt Design Studio). Не должно быть никаких компромиссов в функциях, производительности или опыте разработчика/дизайнера. Таким образом, нет нужды в дальнейшем разделять разработки на большее количество продуктов, и, тем самым, они смогут быстрее предоставлять больше функций и исправлений.

Интуитивно понятный и простой в использовании API

Следующая цель для Qt Quick 3D - предоставить API для определения 3D-контента. API, который доступен и удобен для разработчиков без необходимости понимать тонкие детали современного графического конвейера. В конце концов, большинству пользователей не нужно создавать специализированные средства визуализации 3D-графики для каждого из своих приложений, а просто нужно показывать некоторый 3D-контент, часто наряду с 2D. Поэтому разрабатывается Qt Quick 3D с этой точки зрения.

При этом со временем будет все больше и больше раскрываться API рендеринг, что сделает возможными более сложные варианты использования, необходимые опытным пользователям.

На момент написания этой статьи Qt Company предоставляла только API QML, но в будущем также они хотят предоставить открытый API C ++.

Унифицированный инструментарий для Qt Quick

Qt Quick 3D призван стать преемником Qt 3D Studio . В настоящее время Qt 3D Studio все еще будет развиваться, но в долгосрочной перспективе его заменят Qt Quick и Qt Design Studio .

Разработчики намереваются взять лучшие части Qt 3D Studio и перенести их в Qt Quick и Qt Design Studio. Поэтому вместо того, чтобы нуждаться в отдельном инструменте для Qt Quick или 3D, можно будет взять и то, и другое из Qt Design Studio. Сейчас идет работа над деталями и Qt Company надеется получить предварительный просмотр в ближайшее время.

Для существующих пользователей Qt 3D Studio они работают над инструментом портирования для преобразования проектов в Qt Quick 3D. Подробнее об этом позже.

Первый класс Asset’ов обрабатывающего конвейера

При работе с 3D-сценами состояние системы asset’ов становится более важным, потому как теперь используется больше типов asset’ов, и в целом они, как правило, значительно больше. Поэтому при разработке Qt Quick 3D разработчики старались понять, как можно максимально упростить импорт вашего контента и преобразовать его в эффективные форматы времени выполнения для Qt Quick.

Например, во время разработки вы захотите указать используемые asset’ы на основе того, что генерируют ваши инструменты создания asset’ов (например, файлы FBX из Maya для 3D-моделей или PSD-файлы из Photoshop для текстур), но во время выполнения вы не захотите использовать движок для этих форматов. Вместо этого вы захотите преобразовать asset’ы в некоторый эффективный формат времени выполнения и обновлять их каждый раз при изменении исходных asset’ов. В Qt Company хотят, чтобы это был максимально автоматизированный процесс, и поэтому хотят встроить его в систему сборки и инструментарий Qt.

Межплатформенная производительность и совместимость

Другой целью является поддержка нескольких собственных графических API-интерфейсов с использованием нового Rendering Hardware Interface, добавляемого в Qt. В настоящее время Qt Quick 3D поддерживает рендеринг только с использованием OpenGL, как и многие другие компоненты в Qt. Однако, в Qt 6 будет использоваться QtRHI в качестве графической абстракции, и там можно будет поддерживать рендеринг через Vulkan, Metal и Direct3D, в дополнение к OpenGL.

Что такое Qt Quick 3D?

Qt Quick 3D - это не замена Qt 3D, а скорее расширение функциональности Qt Quick для рендеринга 3D-контента с использованием высокоуровневого API.

Вот как выглядит очень простой проект с полезными примечаниями:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick3D 1.0

Window {
  id: window
  visible: true
  width: 1280
  height: 720

  // Viewport for 3D content
  View3D {
    id: view

    anchors.fill: parent
    // Scene to view
    Node {
      id: scene

      Light {

        id: directionalLight

      }

      Camera {
        id: camera
        // It's important that your camera is not inside 
        // your model so move it back along the z axis
        // The Camera is implicitly facing up the z axis,
        // so we should be looking towards (0, 0, 0)
        z: -600
      }

      Model {
        id: cubeModel
        // #Cube is one of the "built-in" primitive meshes
        // Other Options are:
        // #Cone, #Sphere, #Cylinder, #Rectangle
        source: "#Cube"

        // When using a Model, it is not enough to have a 
        // mesh source (ie "#Cube")
        // You also need to define what material to shade
        // the mesh with. A Model can be built up of 
        // multiple sub-meshes, so each mesh needs its own
        // material. Materials are defined in an array, 
        // and order reflects which mesh to shade

        // All of the default primitive meshes contain one
        // sub-mesh, so you only need 1 material.

        materials: [

          DefaultMaterial {

            // We are using the DefaultMaterial which 
            // dynamically generates a shader based on what
            // properties are set. This means you don't 
            // need to write any shader code yourself.  
            // In this case we just want the cube to have
            // a red diffuse color.
            id: cubeMaterial
            diffuseColor: "red"
          }
        ]
      }
    }
  }
}

Идея состоит в том, что определение 3D-контента должно быть таким же простым, как 2D. Есть несколько дополнительных вещей, которые вам понадобятся, например, концепции Lights, Cameras и Materials (Свет, Камеры и Материалы), но все они являются концепциями сцены высокого уровня, а не деталями реализации графического конвейера.

Этот простой API, конечно же, обходится дешевле. Хотя есть возможность настроить материалы и содержимое сцены, невозможно полностью настроить способ визуализации сцены, в отличие от Qt 3D с помощью настраиваемой диаграммы кадров. Вместо этого на данный момент есть фиксированный передний рендерер (визуализатор), где вы можете определить свойства сцены и как они будут отображаться. Это похоже на другие существующие движки, которые обычно имеют несколько возможных конвейеров рендеринга, которые затем визуализируют логическую сцену.


Камера, вращающаяся вокруг модели автомобиля в скайбоксе с осями и линиями сетки (примечание: stutter от GIF 12 FPS).

Что вы можете сделать с Qt Quick 3D?

Он может делать много вещей, но они создаются с использованием следующих примитивов сцены:

Node (Узел)

Node является базовым компонентом для любого узла в 3D-сцене. Он представляет собой преобразование (трансформацию) в трехмерном пространстве, но не является визуальным. Он работает аналогично тому, как работает Item type в Qt Quick.

Camera (Камера)

Camera представляет, как сцена проецируется на 2D поверхность. Камера имеет положение в трехмерном пространстве (так как это подкласс Node) и проекцию. Для рендеринга сцены вам нужно иметь хотя бы одну камеру.

Light (Свет)

Компонент Light определяет источник освещения в сцене, по крайней мере, для материалов, которые используют освещение. На данный момент существует 3 типа источников света: Directional (направленный (по умолчанию)), Point (точечный) и Area (охватывающий область).

Model (Модель)

Компонент Model является единственным визуальным компонентом в сцене. Он представляет собой комбинацию геометрии (из сетки) и одного или нескольких материалов.

Свойство source (источник) компонента Mesh ожидает файл .mesh , который является форматом времени выполнения, используемым Qt Quick 3D. Чтобы получить файлы mesh (сетки), вам необходимо конвертировать 3D-модели с помощью asset import tool (инструмента импорта asset’ов). Есть также несколько встроенных примитивов. Они могут быть использованы путем установки следующих значений для свойства source (источника): #Cube, #Cylinder, #Sphere, #Cone или #Rectangle.

Также добавлен программный способ определения вашей собственной геометрии во время выполнения, но он пока недоступен в предварительном просмотре.

Прежде чем Model (Модель) может быть визуализирована, она также должна иметь Material (Материал). Это определяет, как сетка (mesh) затенена.

Материалы по умолчанию (Default Material) и нестандартные материалы (Custom Materials)

Компонент DefaultMaterial представляет собой простой в использовании встроенный материал. Все, что вам нужно сделать, это создать этот материал, установить свойства, которые вы хотите определить, и под капотом автоматически будет создан весь необходимый код шейдера. Все остальные свойства, которые вы устанавливаете на сцене, также учитываются. Нет необходимости самостоятельно писать код графического шейдера (например, вершинный или фрагментный шейдер).

Также можно определить так называемые CustomMaterials, где вы предоставляете свой собственный код шейдера. Qt Company также предоставляет библиотеку определенных заранее CustomMaterials, которые вы можете попробовать, просто добавив в свой импорт QML следующее:
import QtQuick3D.MaterialLibrary 1.0

Texture (Текстура)

Компонент Texture представляет текстуру в 3D-сцене, а также то, как она отображается в сетке (mesh). Источником текстуры может быть файл изображения или компонент QML (QML Component).

Образец доступных функций

3D виды в Qt Quick

Чтобы просмотреть 3D-контент в Qt Quick, необходимо выровнять его на 2D-поверхности. Для этого используется компонент View3D. View3D - единственный основанный на QQuickItem компонент во всем API. Вы можете определить сцену, как дочернюю для View3D или сослаться на существующую сцену, установив свойство сцены в корневой узел (Node) сцены, которую вы хотите визуализировать.

Если у вас несколько камер, вы также можете указать, какую камеру вы хотите использовать для рендеринга сцены. По умолчанию он будет использовать только первую активную камеру, определенную в сцене.

Также стоит отметить, что элементы View3D не обязательно должны отображаться за пределами экранных текстур перед визуализацией. Можно установить один из 4 следующих режимов рендеринга, чтобы определить, когда отображается 3D-контент:

1. Texture (Текстура): View3D является провайдером текстур Qt Quick и отображает содержимое в текстуру через FBO.

2. Underlay (Подложка): View3D визуализируется до отображения 2D-контента Qt Quick непосредственно в окне (3D всегда находится под 2D).

3. Overlay (Наложение): View3D отображается после рендеринга 2D-контента Qt Quick непосредственно в окно (3D всегда больше 2D).

4. RenderNode: View3D визуализируется в соответствии с содержимым Qt Quick 2D. Однако это может привести к некоторым странностям из-за того, как Qt Quick 2D использует буфер глубины в Qt 5.

2D виды внутри 3D

Возможно, вы также захотите визуализировать содержимое Qt Quick внутри 3D-сцены. Для этого везде, где Текстура берется в качестве значения свойства (например, в свойстве diffuseMap Material по умолчанию), вы можете использовать Текстуру с установленным свойством sourceItem вместо простого указания файла в свойстве source . Таким образом, ссылка на элемент Qt Quick будет автоматически отображена и использована в качестве текстуры.


Текстуры диффузного цвета, отображаемые на кубы, являются анимированными элементами Qt Quick 2D.

Компоненты 3D QML

Благодаря тому, что Qt Quick 3D построен на QML, можно также создавать повторно используемые компоненты для 3D. Например, если вы создаете модель Автомобиля, состоящую из нескольких Моделей, просто сохраните ее в Car.qml. Затем вы можете создать несколько экземпляров Автомобиля, просто используя его повторно, как и любой другой тип QML. Это очень важно, потому что таким образом 2D и 3D сцены могут быть созданы с использованием одной и той же компонентной модели, вместо того, чтобы иметь дело с разными подходами для 2D и 3D сцен.

Несколько просмотров одной и той же сцены

Поскольку определения сцен могут существовать в любом месте проекта Qt Quick, можно ссылаться на них из нескольких View3D. Если у вас было несколько камер в сцене, вы могли бы даже сделать рендеринг с каждой камеры на другой View3D.


4 вида одной и той же сцены с чайником. Также меняется между 3 камерами в перспективе.

Тени

Любой компонент Light может указать, что он отбрасывает тени. Когда он включен, тени автоматически отображаются на сцене. В зависимости от того, что вы делаете, рендеринг теней может быть довольно дорогим, поэтому вы можете регулировать, какие компоненты Модели отбрасывают тени, устанавливая дополнительные свойства в Модели.

Основанное на изображении освещение

В дополнение к стандартным компонентам Light, можно осветить вашу сцену, определяя карту HDRI. Эту Текстуру можно установить либо для всего View3D в свойстве SceneEnvironment , либо для отдельных Материалов.

Анимации

Анимации в Qt Quick 3D используют ту же систему анимации, что и Qt Quick. Вы можете привязать любое свойство к аниматору, и оно будет анимировано и обновлено, как ожидалось. Используя модуль QtQuickTimeline , также можно использовать анимации на основе ключевых кадров.

Как и компонентная модель, это еще один важный шаг в сокращении разрыва между 2D и 3D-сценами, поскольку здесь не используются отдельные, потенциально конфликтующие системы анимации.

В настоящее время нет поддержки фальсифицированных анимаций, но это планируется в будущем.

Как попробовать Qt Quick 3D?

Намерение состоит в том, чтобы выпустить Qt Quick 3D в качестве технического предварительного просмотра вместе с выпуском Qt 5.14. Между тем, его можно будет использовать уже сейчас, против Qt 5.12 и выше.

Чтобы получить код, вам просто нужно собрать модуль QtQuick3D, который находится здесь:
https://git.qt.io/annichol/qtquick3d

Что насчет инструментов?

Цель состоит в том, чтобы через Qt Design Studio можно было сделать все необходимое для настройки 3D-сцены. Это означает, что вы можете визуально разметить сцену, импортировать 3D asset’ы, такие как сетки, материалы и текстуры, и преобразовать эти asset’ы в эффективные форматы времени выполнения, используемые движком.


Демонстрация ранней интеграции Qt Design Studio для Qt Quick 3D.

Импорт 3D-сцен в компоненты QML

Qt Quick 3D также можно использовать, написав код QML вручную. Поэтому также есть несколько автономных утилит для конвертации asset’ов. Когда-то такой инструмент являлся инструментом подготовки balsam asset. Сейчас же можно передать этой утилите asset из инструмента создания 3D-активов, такого как Blender, Maya или 3DS Max, и он сгенерирует компонент QML, представляющий сцену, а также любые текстуры, сетки и материалы, которые он использует. В настоящее время этот инструмент поддерживает создание сцен из следующих форматов:
• FBX
• Collada (dae)
• OBJ
• Blender (blend)
• GLTF2

Чтобы преобразовать файл myTestScene.fbx, вы должны выполнить:

./balsam -o ~/exportDirectory myTestScene.fbx

Это создаст файл с именем MyTestScene.qml вместе с любыми необходимыми asset’ами. Тогда вы можете просто использовать его, как любой другой компонент в вашей сцене:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick3D 1.0

Window {
 width: 1920
 height: 1080
 visible: true
 color: "black"

 Node {
   id: sceneRoot
   Light { 
   }
   Camera {
   z: -100
   }
   MyTestScene {
   }
 }

 View3D {
   anchors.fill: parent
   scene: sceneRoot
 }
}

Qt Company работает над улучшением asset’ов, создаваемых этим инструментом, поэтому ожидаются улучшения в ближайшие месяцы.

Конвертация проектов Qt 3D Studio

В дополнение к возможности генерировать компоненты 3D QML из инструментов создания 3D-asset’ов, также был создан плагин для инструмента импорта asset’ов для преобразования существующих проектов Qt 3D Studio. Если вы ранее использовали Qt 3D Studio, вы будете знать, что он генерирует проекты в формате XML для определения сцены. Если вы передадите инструменту balsam проект UIP или UIA, сгенерированный Qt 3D Studio, он также сгенерирует проект Qt Quick 3D на основе этого. Однако обратите внимание, что, поскольку среда выполнения, используемая Qt 3D Studio, отличается от Qt Quick 3D, не все будет преобразовано. Тем не менее, он должен дать хорошее приближенное значение или отправную точку для преобразования существующего проекта. Qt Company надеется продолжить улучшение поддержки этого пути, чтобы сгладить переход для существующих пользователей Qt 3D Studio.


Пример приложения Qt 3D Studio, портированного с помощью инструмента импорта Qt Quick 3D (это еще не идеально).

Как насчет Qt 3D?

Первый вопрос, который Qt Company ожидает получить, это почему бы просто не использовать Qt 3D? Этот вопрос, который они изучали последние пару лет.

Одно предположение состоит в том, что можно просто собрать весь Qt Quick поверх Qt 3D, если смешать 2D и 3D. Qt Company собирались и начали делать это с выпуском 2.3 Qt 3D Studio. Мощный API Qt 3D предоставил хорошую абстракцию для реализации движка рендеринга, чтобы воссоздать поведение, ожидаемое Qt Quick и Qt 3D Studio. Однако, архитектура Qt 3D затрудняет получение необходимой производительности на встроенном оборудовании начального уровня. Qt 3D также имеет определенные издержки из-за собственной ограниченной среды выполнения, а также из-за того, что является еще одним уровнем абстракции между Qt Quick и графическим оборудованием. В своей нынешней форме Qt 3D не идеален для дальнейшего развития, если они хотят достичь полностью унифицированной графической истории, обеспечивая при этом постоянную хорошую поддержку для широкого спектра платформ и устройств, начиная от низкого до высокого класса.

В то же время уже был движок рендеринга в Qt 3D Studio, который делал именно то, что нужно, и являлся хорошей основой для создания дополнительных функциональных возможностей. Это связано с недостатком, заключающимся в том, что у них больше нет мощных API, которые идут с Qt 3D, но на практике, когда вы начинаете создавать среду выполнения поверх Qt 3D, вы уже в конечном итоге принимаете решения о том, как все должно работать, что в любом случае приводит к ограниченной возможности настроить framegraph (граф кадра). В конце концов, наиболее практичным решением было использовать существующий движок рендеринга Qt 3D Studio в качестве базы и опираться на него.

Каков план продвижения вперед?

Этот релиз - только предварительный просмотр того, что должно быть. Планируется предоставить Qt Quick 3D, как полностью поддерживаемый модуль вместе с Qt 5.15 LTS. Тем временем Qt Company работает над дальнейшей разработкой Qt Quick 3D в качестве релиза Tech Preview с Qt 5.14.

Для серии Qt 5 они ограничены в том, насколько глубоко они могут комбинировать 2D и 3D из-за обещаний двоичной совместимости. С выпуском Qt 6 Qt Company планирует еще более глубокую интеграцию Qt Quick 3D в Qt Quick, чтобы обеспечить еще более плавную работу.

Цель в том, что они хотят быть максимально эффективными при смешивании 2D и 3D контента, без дополнительных затрат для пользователей, которые вообще не используют 3D контент. Они не будут делать ничего радикального, например, заставлять все приложения Qt Quick проходить через новый рендер, только те, которые смешивают 2D и 3D.

В Qt 6 также будет использоваться аппаратный интерфейс рендеринга Qt для рендеринга сцен Qt Quick (включая 3D), что должно устранить многие из текущих проблем, с которыми Qt Company сталкивается сегодня при развертывании приложений OpenGL (с использованием DirectX в Windows, Metal в macOS и т. д.).

Qt Company также желает, чтобы конечные пользователи могли использовать C ++ Rendering API, который создали более обобщённо, без Qt Quick. Код теперь, как у частного API, но они ждут времени Qt 6 (и портирования RHI), прежде чем делать обещания совместимости, которые идут с общедоступными API.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

qml_puthon_user
  • 2 декабря 2019 г. 11:39

Доброго времени суток. Подскажите пожалуйста, я вызываю файл qml через python-скрипт. QtQuick работает нормально, но, когда дописываю import QtQuick3D 1.0, мне выдаётся ошибка, что модуль не установлен. У меня стоит ещё QtDesignStudio, так же прописываю в ней импорт и всё работает нормально, и при запуске GUI из самой студии, всё работает. Почему же тогда из питона не работает? Работаю под Windows пока что. Со сборкой модуля не справился, не знаю, как правильно делать. Спасибо!

Evgenii Legotckoi
  • 3 декабря 2019 г. 4:10

QtDesignStudio работает с C++, поэтому там работает, но вот относительно python думаю, что не все требуемые зависимости установлены для python пакетов.
К тому же, что именно вы используете для python? PyQt5 или Pyside?

qml_puthon_user
  • 3 декабря 2019 г. 4:11
  • (ред.)

PyQt5.

Evgenii Legotckoi
  • 3 декабря 2019 г. 4:20

Ясно. Я видел, что вы вопрос на форум задали. Я вечером после работы гляну у себя на домашнем ПК, запустится ли ваш код. У меня там Ubuntu и вроде бы все пакеты установлены для PyQt5. Но вполне может быть так, что это может и не работать для PyQt5

qml_puthon_user
  • 3 декабря 2019 г. 4:21

Хорошо, спасибо большое! :)

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50баллов,
  • Очки рейтинга-4
m
  • molni99
  • 26 октября 2024 г. 8:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80баллов,
  • Очки рейтинга4
m
  • molni99
  • 26 октября 2024 г. 8:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20баллов,
  • Очки рейтинга-10
Последние комментарии
ИМ
Игорь Максимов22 ноября 2024 г. 19:51
Django - Урок 017. Кастомизированная страница авторизации на Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 октября 2024 г. 21:37
Django - Урок 064. Как написать расширение для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 октября 2024 г. 15:19
Читалка fb3-файлов на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов5 октября 2024 г. 14:51
Django - Урок 064. Как написать расширение для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55 июля 2024 г. 18:02
QML - Урок 016. База данных SQLite и работа с ней в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Сейчас обсуждают на форуме
Evgenii Legotckoi
Evgenii Legotckoi24 июня 2024 г. 22:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 ноября 2024 г. 14:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject4 июня 2022 г. 10:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 октября 2024 г. 16:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Следите за нами в социальных сетях