Быстрый старт с java: от знакомства до вашей первой игры

Что было раньше: код или документация? OpenApi (OAS 3.0) и проблемы кодогенерации на Java

Задача интеграции сервисов и различных систем является чуть ли не одной из основных проблем современного IT. На сегодняшний день самым популярным архитектурным стилем для проектирования распределенных систем является REST. Но, как известно, единого стандарта для RESTful сервисов нет, а у кажущейся простоты и свободы есть обратная сторона медали

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

Эту проблему отчасти удалось решить при помощи спецификации OpenAPI (OAS 3.0), но все равно часто встает вопрос о правильном применении и подводных камнях кодогенерации, например на языке Java. И можно ли полностью предоставить аналитикам написание функциональных требований, документации и моделей в yml форме для OpenAPI, а разработчикам предоставить возможность только написание бизнес-логики?

Что было раньше: код или документация? OpenApi (OAS 3.0) и проблемы кодогенерации на Java

Задача интеграции сервисов и различных систем является чуть ли не одной из основных проблем современного IT. На сегодняшний день самым популярным архитектурным стилем для проектирования распределенных систем является REST. Но, как известно, единого стандарта для RESTful сервисов нет, а у кажущейся простоты и свободы есть обратная сторона медали

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

Эту проблему отчасти удалось решить при помощи спецификации OpenAPI (OAS 3.0), но все равно часто встает вопрос о правильном применении и подводных камнях кодогенерации, например на языке Java. И можно ли полностью предоставить аналитикам написание функциональных требований, документации и моделей в yml форме для OpenAPI, а разработчикам предоставить возможность только написание бизнес-логики?

Способы улучшение производительности Library

С JSON легко работать и он стал стандартным форматом данных практически для всего. В Stackify широко применяют JSON для API-интерфейсов REST, сериализации сообщений в очереди и многого другого.

Некоторые общие советы по производительности JSON:

  1. Использовать несколько библиотек JSON для оптимальной производительности и функций.
  2. Использовать потоки, когда это возможно.
  3. Сжимать пользовательский JSON. Поскольку это просто текст, можно рассчитывать на сжатие до 90%. Поэтому применяют «zip» везде, где это возможно.
  4. Избегать анализа, если это не нужно.
  5. Выполнять сериализацию/десериализацию больших и меньших объектов JSON. В некоторых случаях, когда нужно получить массив больших объектов, его разбивают на более мелкие части.
  6. Настроить анализатор JSON Web API.
  7. Не сериализовать все поля, нулевые значения или значения по умолчанию.
  8. Использовать более короткие имена полей.
  9. Ручная сериализация или разбор могут быть быстрее.

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

Ключевые принципы дизайна

Повторное использование кода является одним из священных Граалей компьютерного программирования. Написание кода, который можно легко повторно применять, требует обладания сложных навыков, но, безусловно, его может освоить каждый желающий. Язык Java может помочь создать хорошую многоразовую платформу. Для этого разработчику необходимо иметь базовые знания по программированию, включая умение создавать, компилировать и выполнять простые программы из командной строки.

Несколько ключевых принципов хорошего дизайна Java-библиотеки:

  1. Она четко должна передавать свою внутреннюю структуру таким образом, что пользователь знает, как ее использовать, даже если не понимает, как она работает изнутри.
  2. Инкапсуляция — ужесточение и уточнение интерфейса кода, что делает его более надежным и понятным.
  3. Расширяемость — создание Java-библиотеки, которая хорошо выполняет свою задачу и предоставляет возможность заполнить недостающие части для удовлетворения потребностей конкретного разработчика.
  4. Наследование — обеспечивает способ настройки кода без необходимости знать все детали кода, который настраивается.
  5. Предоставление способа получения отладочной информации из кода — помогает пользователям находить собственные ошибки.

Computation result

Usually, instance methods operate on the object (matrix, vector, quaternion) on which they are invoked by writing the computation result back into that object. Most of the methods however also allow to specify another destination object to write the result into. This is useful if you do not want to overwrite the original object with the computation result.
This can be useful for computing the view-projection matrix and its inverse in one go:

Matrix4f viewProj = new Matrix4f();
Matrix4f invViewProj = new Matrix4f();
viewProj.perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f)
        .lookAt(0.0f, 1.0f, 3.0f,
                0.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f)
        .invert(invViewProj);

The invViewProj matrix now contains the inverse of the viewProj matrix, but the latter is still intact.

Development

Build/running in development

  1. To install all required npm packages:
yarn
  1. To start the server in dev mode:
node server
# or
yarn start

OPTIONAL: Monitor for /server changes & auto-restart with:

yarn watch

CLI flags

--css # Enables CSS modules in dev mode (enables Sass HMR)
--sourcemap # Enables inline JS source-maps
--nohmr # Disables Webpack Hot Module Replacement

The following flags are used for testing production builds locally.
NODE_ENV environment variable must be set to «production».

--test # Enables production test mode (loads assets from disk instead of S3)
--nocache # Disables Pug view caching
--pretty # Pretty prints HTML
--s3proxy # Proxies S3 images

The following flags are used for testing production builds locally.
NODE_ENV environment variable must be set to «production».

--test # Enables production test mode (loads assets from disk instead of S3)
--nocache # Disables Pug view caching
--pretty # Pretty prints HTML
--s3proxy # Proxies S3 images

Flag usage examples:

node server --css
node server --async --nohmr
yarn watch -- --async --nohmr

Default config if file is missing:

{
  "port": 80,
  "host": "0.0.0.0"
}

Границы функциональности: вход и выход

Проблема в том, что не все дизайнеры Java-библиотек думают о своих пользователях, о том, как API будет применяться на практике и как будет выглядеть и тестироваться код.

Границы функциональности — это, пожалуй, самая важная тема. Хорошей практикой является прохождение всех зависимостей через конструкторы и их краткость с несколькими параметрами. Если нужен конструктор с более чем тремя или четырьмя параметрами, тогда ясно, что код должен быть реорганизован.

Также разработчики всегда должны предлагать пользователям более одного конструктора. Клиенты должны работать со String и Integer, чтобы они могли передавать ByteArrayInputStream при тестировании модулей.

Например, несколько способов создания точки входа API Github с помощью jcabi-github:

  • Github noauth = new RtGithub();
  • Github basicauth = new RtGithub(«username», «password»);
  • Github oauth = new RtGithub(«token»).

В качестве второго примера, как работать с charles, Java-библиотекой профессионала для веб-сканирования, можно прописать следующее.

По умолчанию шаблоны не должны игнорироваться. Переменная indexPage — это URL-адрес, с которого должен начаться обход контента, драйвер — это используемый браузер. По умолчанию он ничего не может сделать, поскольку неизвестно, какой браузер установлен на работающей машине. Выход нужен в основном для Library, которая общается с внешним миром. Здесь нужно ответить на вопрос, как он будет обрабатываться.

Для этого нужно прописать что-то вроде этого:

WebCrawl graph = new GraphCrawl(…);List pages = graph.crawl();

Java 15 глазами программиста Scala

Перевод

Время летит. Не успеваешь моргнуть глазом, а уже вышел очередной релиз Java. В соответствии с графиком (по релизу каждые полгода) комьюнити получило в свое распоряжение Java 15, судьба которой — стать фундаментом для Java 17 LTS (выйдет через год).

В Java постоянно вносятся улучшения, многие из которых были реализованы под влиянием других языков JVM и функционального программирования. Сюда можно отнести такие возможности, как лямбды, ограниченный вывод типов локальных переменных (тип var) и switch-выражения. Scala — особенно богатый источник идей, благодаря инновационному сочетанию в ней объектно-ориентированного и функционального программирования.

Предлагаю рассмотреть, как представленные в новом релизе Java 15 (пока в статусе превью финальной версии) возможности соотносятся с конструкциями в Scala. Мы сосредоточимся на особенностях языка, пропустим улучшения в JVM и доработку стандартной библиотеки. Кроме того, нужно отметить, что некоторые из описанных компонентов уже были доступны в более ранних версиях Java (в виде предварительной или бета-версии).

Matrix API

Using JOML you can build matrices out of basic transformations, such as scale, translate and rotate, using a fluent interface style. All such operations directly modify the matrix instance on which they are invoked.
The following example builds a transformation matrix which effectively first scales all axes by 0.5
and then translates x by 2.0:

Vector3f v = ...;
new Matrix4f().translate(2.0f, 0.0f, 0.0f)
              .scale(0.5f)
              .transformPosition(v);
// v is now transformed by the specified transformation

Common transformation idioms, such as rotating about a given axis using a specific rotation center, can be expressed in a simple way. The following example rotates the point (0, 4, 4) about the x-axis and uses (0, 3, 4) as the rotation center:

Vector3f center = new Vector3f(0.0f, 3.0f, 4.0f);
Vector3f pointToRotate = new Vector3f(0.0f, 4.0f, 4.0f);
new Matrix4f().translate(center)
              .rotate((float) Math.toRadians(90.0f), 1.0f, 0.0f, 0.0f)
              .translate(center.negate())
              .transformPosition(pointToRotate);

The vector pointToRotate will now represent (0, 3, 5).

Production

The website is served via Amazon CloudFront using the server’s hostname & port as origin.
SSL Termination happens on the CDN (using a certificate issued by AWS Certificate Manager).

The production process involves the following steps:

  • Compile SCSS files (node-sass -> postcss -> autoprefixer -> cssnano)
  • Compile JS files with webpack (babel) and store the manifest on disk
  • Process the manifest:
    • Read the webpack manifest and compile list of files & routes
    • Process each file with terser
    • Compute hashes of final files
    • Store each production file on disk
    • Generate production manifest that also needs to be shipped
    • Generate & print file size report
  • Deploy files to S3
  • Start or reload node app

Build for production

git pull
yarn
yarn release

To run the production build (*nix only)

NODE_ENV=production node server

you can simulate and run the production build locally:

# will use production assets on disk
yarn test-production
# will download production assets from S3, only proxies request that pass through Cloudfront
yarn run-production
yarn production-profiling
yarn post-production
yarn test-production

Debugging production output

The following debugging tips may come in handy:

  • Disable minification by uncommenting in
  • Prevent Terser from dropping or by changing in
  • Pass to load React profiling builds
  • Output module & chunk ids in
  • Analyze build output with (for full breakdown, change to when writing in )

Run in production with PM2

cd /path/to/lwjgl3-www
NODE_ENV=production pm2 start server/index.js --name lwjgl
pm2 save

or place a process.json file anywhere with the following contents:

{
  "apps": [
    {
      "name": "lwjgl-site",
      "cwd": "/path/to/lwjgl3-www",
      "script": "./server/index.js",
      "env": {
        "NODE_ENV": "production",
        "PORT": 7687
      }
    }
  ]
}

and then run:

pm2 start process.json --only lwjgl-site
pm2 save

Post-multiplication

All transformation operations in the matrix and quaternion classes act in the same way as OpenGL and GLU by post-multiplying the operation’s result to the object on which they are invoked. This allows to chain multiple transformations in the same way as with OpenGL’s legacy matrix stack operations, and allows to decompose the resulting effective matrix as a decomposition of multiple matrix multiplications.
One such common decomposition are the projection and modelview matrices, written as: . The modelview matrix of course can be further decomposed into individual matrix multiplications, as far as this seems necessary.

When invoking transformation methods in JOML’s matrix classes, a convenient way now is to think of Java’s dot operator as a matrix multiplication. If multiple matrix operations are chained after one another, as shown in the above example, each individual operation/method creates its matrix which is then post-multiplied to the matrices built before.

In addition to the post-multiplying methods, there are still ways to set a matrix or quaternion to a given transformation regardless of what that matrix or quaternion was before:

Matrix4f m = new Matrix4f();
Vector3f point = new Vector3f(1.0f, 2.0f, 3.0f);
Vector3f offset = new Vector3f(1.0f, 0.0f, 0.0f);
...
m.translation(offset).transformPosition(point);

In the above example, the matrix m is being set to a translation, instead of applying the translation to it.
These methods are useful when the same matrix is being used in a sequence of consecutive operations or repeatedly in a loop without having to set it to the identity each time.

Обучающие книги Horstmann

Многообразие библиотек заставляет программистов находить исчерпывающее, но сжатое руководство по всем новым функциям Java SE 9. В этом им помогают книги Хорстманна, особенно интересно начинающим пользователям десятое издание книги «Java-библиотека профессионала».

Кей С. Хорстманн — профессор компьютерных наук государственного университета Сан-Хосе. Он является опытным профессиональным программистом и консультантом для крупных корпораций, университетов и организаций по Java, C ++, Windows и интернет-программирования. Хорстманн является автором многих успешных профессиональных и академических книг, включая «Big C ++», «C ++ для всех», «Big Java», «Объектно-ориентированный дизайн и шаблоны».

Книга Корнелла Хорстманн «Java-библиотека профессионала» охватывает все важные аспекты языка, которые должен знать современный разработчик, включая модульность, а также мощные лямбда-выражения, представленные в 8-й версии. В них изложены основы программирования с использованием Java в более доступном и менее строгом подходе.

Книга предоставляет более удобный интенсивный графический дизайн, который передает сложные концепции просто и эффективно. Она отличается от других книг на рынке тем, что фокусируется на таких темах, как циклы и графические интерфейсы, при этом избегая ориентации на объектную ориентацию. Акцент делается на простые программы, которые используют предварительно созданные структуры данных и алгоритмы.

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

Using with Java 2D

Matrix4f m = ...; // <- any affine 2D transformation built with JOML
AffineTransform t = ...; // <- any Java 2D AffineTransform (e.g. Graphics2D.getTransform())
t.setTransform(m.m00(), m.m01(), m.m10(), m.m11(), m.m30(), m.m31());

The above will copy any affine 2D transformation, represented by the Matrix4f, to the provided AffineTransform instance.

Since Java 2D cannot represent 3D transformations, using a Matrix4f in JOML is not necessary. For 2D transformations JOML provides the Matrix3x2f and Matrix3x2d classes. If those are used, copying the 2D transformation into a Java 2D AffineTransform instance works like this:

Matrix3x2f m = ...; // <- any 2D transformation built with JOML
AffineTransform t = ...; // <- any Java 2D AffineTransform
t.setTransform(m.m00, m.m01, m.m10, m.m11, m.m20, m.m21);

(Note: The AffineTransform class uses a different order for the row and column indices of a matrix element. Here, the row index comes first, and then the column index)

How to use it?

In your existing SWT application just replace all imports of with .
The new implementation is a drop-in replacement, which means that your current SWT code should work like before.
To use the new features you can use the new fields in the class, such as using real multisampled framebuffers or creating a OpenGL 3.2 core context.

If your current OpenGL SWT setup looks like this:

Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
GLData data = new GLData();
GLCanvas canvas = new GLCanvas(shell, , data);

then adding multisampling and using a OpenGL 3.2 core context is as easy as doing:

Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
GLData data = new GLData();
data.profile = GLData.Profile.CORE;
data.majorVersion = 3;
data.minorVersion = 2;
data.samples = 4; // 4x multisampling
data.swapInterval = 1; // for enabling v-sync (swapbuffers sync'ed to monitor refresh)
GLCanvas canvas = new GLCanvas(shell, , data);

Архитектурные подходы к авторизации в серверных приложениях: Activity-Based Access Control Framework

Из песочницы

Сегодня поговорим об секьюрити в web (да, наверное, и не только) приложениях. Прежде чем описывать подходы и фреймворки расскажу небольшую предысторию.

Подходы к созданию фреймворка

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

Всем известны два стиля написания кода — императивный и декларативный. Императивный стиль описывает то, как получить результат, декларативный — что требуется получить в результате.

Обеспечение границ компонентов чистой архитектуры с помощью Spring Boot и ArchUnit

Когда мы создаем программное обеспечение, мы хотим создавать «-способности»: понятность, ремонтопригодность, расширяемость и — в тренде сейчас — декомпозицию (чтобы мы могли разложить монолит на микросервисы, если возникнет необходимость). Добавьте в этот список свою любимую «способность».

Большинство — возможно, даже все — из этих «возможностей» идут рука об руку с чистыми зависимостями между компонентами.

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

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

Это тем более важно, если мы работаем над монолитной кодовой базой, охватывающей множество различных областей бизнеса или «ограниченных контекстов», если использовать жаргон Domain-Driven Design. Как мы можем защитить нашу кодовую базу от нежелательных зависимостей? С тщательным проектированием ограниченных контекстов и постоянным соблюдением границ компонентов. В этой статье показан набор практик, которые помогают в обоих случаях при работе со Spring Boot

Как мы можем защитить нашу кодовую базу от нежелательных зависимостей? С тщательным проектированием ограниченных контекстов и постоянным соблюдением границ компонентов. В этой статье показан набор практик, которые помогают в обоих случаях при работе со Spring Boot.

Внедрение рекомендаций по структуре кода с использованием ArchUnit

  • Перевод
  • Tutorial

При создании программного обеспечения все мы, как команда, соглашаемся следовать набору рекомендаций, которые обычно считаются лучшими практиками. Но во время разработки разработчики могут нарушить эти правила по незнанию или нежеланию. Обычно мы полагаемся на ревью кода или инструменты проверки качества кода, такие как SonarQube , PMD и т.д. для проверки таких нарушений. Но некоторые из рекомендаций могут быть решениями, которые нельзя автоматизировать с помощью SonarQube, PMD и т.д.

Например, обычно я хочу следовать приведенным ниже рекомендациям для моих приложений на основе Java:

1. Следуйте трехуровневой структуре (уровни веб, сервис, репозиторий), где любой уровень может взаимодействовать только с непосредственным нижним уровнем, а нижний уровень не должен взаимодействовать с верхним уровнем. т.е. веб-уровень может взаимодействовать с уровнем сервиса, уровень сервиса может взаимодействовать с уровнем репозитория. Но уровень репозитория не может взаимодействовать с сервисным или веб-уровнем, сервисный уровень не может взаимодействовать с веб-уровнем.

2. Если приложение большое, мы могли бы захотеть следовать структуре Package-By-Feature, где только компоненты Web и Service являются public, а остальные компоненты должны быть package-private.

3. При использовании внедрения зависимостей Spring не используйте внедрение на основе поля и предпочитайте внедрение на основе конструктора.

Таким образом, может быть много правил, которым мы хотим следовать. Хорошая новость заключается в том, что мы можем проконтролировать выполнение этих рекомендаций с помощью JUnit тестов с использованием ArchUnit.

Using with JOGL

JOML can be used together with JOGL to build a transformation matrix and set it as a uniform mat4 in a shader (for example as a replacement of com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil and com.jogamp.opengl.util.PMVMatrix to emulate the fixed pipeline). For this, the Matrix4f class provides a method to transfer a matrix into a Java NIO FloatBuffer, which can then be used by JOGL when calling into OpenGL:

FloatBuffer fb = Buffers.newDirectFloatBuffer(16);
new Matrix4f().perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f)
              .lookAt(0.0f, 0.0f, 10.0f,
                      0.0f, 0.0f, 0.0f,
                      0.0f, 1.0f, 0.0f).get(fb);
gl.glUniformMatrix4fv(mat4Location, 1, false, fb);
FloatBuffer fb = Buffers.newDirectFloatBuffer(16);
Matrix4f m = new Matrix4f();
m.setPerspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f);
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadMatrixf(m.get(fb));
m.setLookAt(0.0f, 0.0f, 10.0f,
            0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadMatrixf(m.get(fb));

Staying allocation-free

JOML is designed to be completely allocation-free for all methods. That means JOML will never allocate Java objects on the heap unless you as the client specifically requests to do so via the new keyword when creating a new matrix or vector or calling the toString() method on them.

JOML also does not allocate any unexpected internal helper/temporary/working objects itself, neither in instance nor static fields, thus giving you full control over object allocations.

Since you have to create a matrix or a vector at some point in order to make any computations with JOML on them, you are advised to do so once at the initialization of your program. Those objects will then be the working memory/objects for JOML. These working objects can then be reused in the hot path of your application without incurring any additional allocations. The following example shows a typical usecase with LWJGL:

FloatBuffer fb;
Matrix4f m;

void init() {
  fb = MemoryUtil.memAllocFloat(16);
  m = new Matrix4f();
  ...
}
void destroy() {
  MemoryUtil.memFree(fb);
}

void frame() {
  ...
  // compute view-projection matrix
  m.identity()
   .perspective((float) Math.toRadians(45.0f), (float)widthheight, 0.01f, 100.0f)
   .lookAt(0.0f, 0.0f, 10.0f,
           0.0f, 0.0f, 0.0f,
           0.0f, 1.0f, 0.0f);
  // possibly apply more model transformations
  m.rotateY(angle);
  // get matrix into FloatBuffer and upload to OpenGL
  glUniformMatrix4fv(mat4Location, false, m.get(fb));
  ...
}

In the example above, a single Matrix4f is allocated during some initialization time when the init() method is called. Then each frame() we reinitialize the same matrix with the identity() and recompute the camera transformation based on some other parameters.

Мне надоело, что индустрия зависит от прихоти создателей языков программирования. Сообществу нужно больше власти

Я программирую 16 лет, и перебрал за это время много технических стеков. Изучать языки весело, в начале они всегда как новенькие игрушки, пока месяце на третьем не появляются первые проблемы.

В языках вечно не хватает чего-то простого — лямбда-функций, именованных объединений, кастомных примитивных типов. Я лезу в обсуждения на Stack Overflow, в Github и вижу, как разрабы жалуются — им не хватает того же, чего и мне. Но обсуждения почти всегда заканчиваются одинаково: нужная фича не появится, потому что главный дизайнер языка и члены его команды нужной ее не считают.

Раньше в эти моменты мне казалось, что это я неграмотный, и чего-то не понимаю. Что создатели языков за гранями приземленной разрабовской критики. Они умны, дальновидны, преисполнены мудрости, и пути их неисповедимы.

Но сейчас я понимаю — это полная чушь.

IDE Setup

  • Prettier — Code formatter
  • vscode-styled-components
  • IntelliSense for CSS class names

We also recommend enabling auto-save onWindowChange for faster HMR (simply Alt/Cmd+Tab).
In VS Code add the following in the user settings:

{
  "files.autoSave": "onWindowChange"
}

Recommended VS Code Workspace Settings:

  • enable Prettier’s format-on-save
  • exclude generated files
{
  "editor.formatOnSave": true,
  "files.exclude": {
    "**/.vscode": true,
    "**/public/js/*": true,
    "**/public/css/*": true
  },
  "typescript.tsdk": "node_modules\\typescript\\lib",
  "html-css-class-completion.includeGlobPattern": "**/*.{css}"
}

Matrix stack

JOML also features an interface that resembles the matrix stack from legacy OpenGL.
This allows you to use all of the legacy OpenGL matrix stack operations even in modern OpenGL applications,
but without the otherwise necessary JNI calls into the graphics driver.
Note that JOML does not interface in any way with the OpenGL API. It merely provides matrix and vector arithmetics.

Matrix4fStack s = new Matrix4fStack(2);
s.translate(2.0f, 0.0f, 0.0f);
s.pushMatrix();
{
  s.scale(0.5f, 0.5f, 0.5f);
  // do something with the Matrix4f of 's'
}
s.popMatrix();
s.rotate((float) Math.toRadians(45.0f), 0.0f, 0.0f, 1.0f);
// do something with the Matrix4f of 's'

Оцените статью
Рейтинг автора
5
Материал подготовил
Андрей Измаилов
Наш эксперт
Написано статей
116
Добавить комментарий