--- /dev/null
+/.idea/
+/target/
+/.classpath
+/.project
+/.settings/
+/doc/graphs/
+/doc/apidocs/
+/*.iml
+*.html
--- /dev/null
+# Project Overview
+
+Sixth 3D Demos is a collection of demo applications showcasing the Sixth 3D rendering engine. It features interactive 3D
+visualizations including Conway's Game of Life, galaxy simulations, and various geometric demos.
+
+## Build and Test Commands
+
+### Build the project
+
+```bash
+mvn clean package
+```
+
+### Compile only (without packaging)
+
+```bash
+mvn clean compile
+```
+
+### Run the application
+
+```bash
+java -jar target/sixth-3d-demos.jar
+```
+
+### Generate API documentation
+
+```bash
+mvn javadoc:javadoc
+```
+
+### Run a specific demo directly
+
+```bash
+# Run the launcher
+java -cp target/sixth-3d-demos.jar eu.svjatoslav.sixth.e3d.examples.launcher.Main
+
+# Run Game of Life demo
+java -cp target/sixth-3d-demos.jar eu.svjatoslav.sixth.e3d.examples.life_demo.Main
+
+# Run Point Cloud Galaxy demo
+java -cp target/sixth-3d-demos.jar eu.svjatoslav.sixth.e3d.examples.galaxy_demo.PointCloudDemo
+```
+
+### Testing
+
+This project currently has no automated tests. Testing is done manually by running the demo applications.
+
+## Code Organization
+
+```
+src/main/java/eu/svjatoslav/sixth/e3d/examples/
+├── launcher/ - Application launcher and GUI
+│ ├── Main.java - Main entry point
+│ └── ApplicationListPanel.java
+├── life_demo/ - Conway's Game of Life 3D demo
+│ ├── Main.java
+│ ├── Cell.java
+│ ├── Matrix.java
+│ └── Star.java
+├── galaxy_demo/ - Galaxy simulation demo
+│ ├── Galaxy.java
+│ └── PointCloudDemo.java
+├── RandomPolygonsDemo.java
+├── OctreeDemo.java
+├── GraphDemo.java
+├── TextEditorDemo.java
+├── TextEditorDemo2.java
+├── RainingNumbersDemo.java
+└── package-info.java
+```
+
+## Code Style Guidelines
+
+### Java Version
+
+- Java 21 (source and target compatibility)
+
+### Indentation and Formatting
+
+- Use 4 spaces for indentation (no tabs)
+
+## External Dependencies
+
+| Dependency | Version | Description |
+|-------------------|--------------|---------------------|
+| sixth-3d | 1.3-SNAPSHOT | 3D rendering engine |
+| svjatoslavcommons | 1.8 | Utility library |
+
+Both are available from the svjatoslav.eu Maven repository.
+
+## Common Patterns in This Codebase
+
+### Creating a Demo Application
+
+1. Create a class with a `main` method
+2. Create a `ViewFrame` to display the 3D scene
+3. Get the `ShapeCollection` from the view panel
+4. Add shapes to the collection
+5. Optionally set up user input handling
+
+### Extending AbstractCompositeShape
+
+Use this pattern for creating composite 3D objects:
+
+```java
+public class MyShape extends AbstractCompositeShape {
+ public MyShape(Transform transform) {
+ super(transform);
+ // Add child shapes using addShape()
+ }
+}
+```
+
+### Handling User Input
+
+Implement `MouseInteractionController` for mouse events, or extend input tracker classes for keyboard input.
+
+## Documentation
+
+Always make sure that documentation in`doc/index.org` stays up to date.
--- /dev/null
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
--- /dev/null
+#!/bin/bash
+
+# This script launches IntelliJ IDEA with the current project
+# directory. The script is designed to be run by double-clicking it in
+# the GNOME Nautilus file manager.
+
+# First, we change the current working directory to the directory of
+# the script.
+
+# "${0%/*}" gives us the path of the script itself, without the
+# script's filename.
+
+# This command basically tells the system "change the current
+# directory to the directory containing this script".
+
+cd "${0%/*}"
+
+# Then, we move up one directory level.
+# The ".." tells the system to go to the parent directory of the current directory.
+# This is done because we assume that the project directory is one level up from the script.
+cd ..
+
+# Now, we use the 'setsid' command to start a new session and run
+# IntelliJ IDEA in the background. 'setsid' is a UNIX command that
+# runs a program in a new session.
+
+# The command 'idea .' opens IntelliJ IDEA with the current directory
+# as the project directory. The '&' at the end is a UNIX command that
+# runs the process in the background. The '> /dev/null' part tells
+# the system to redirect all output (both stdout and stderr, denoted
+# by '&') that would normally go to the terminal to go to /dev/null
+# instead, which is a special file that discards all data written to
+# it.
+
+setsid idea . &>/dev/null &
+
+# The 'disown' command is a shell built-in that removes a shell job
+# from the shell's active list. Therefore, the shell will not send a
+# SIGHUP to this particular job when the shell session is terminated.
+
+# '-h' option specifies that if the shell receives a SIGHUP, it also
+# doesn't send a SIGHUP to the job.
+
+# '$!' is a shell special parameter that expands to the process ID of
+# the most recent background job.
+disown -h $!
+
+
+sleep 2
+
+# Finally, we use the 'exit' command to terminate the shell script.
+# This command tells the system to close the terminal window after
+# IntelliJ IDEA has been opened.
+exit
--- /dev/null
+#!/bin/bash
+
+cd ..
+
+# Function to export org to html using emacs in batch mode
+export_org_to_html() {
+ local org_file=$1
+ local dir=$(dirname "$org_file")
+ local base=$(basename "$org_file" .org)
+ (
+ cd "$dir" || return 1
+ local html_file="${base}.html"
+ if [ -f "$html_file" ]; then
+ rm -f "$html_file"
+ fi
+ echo "Exporting: $org_file → $dir/$html_file"
+ emacs --batch -l ~/.emacs --visit="${base}.org" --funcall=org-html-export-to-html --kill
+ if [ $? -eq 0 ]; then
+ echo "✓ Successfully exported $org_file"
+ else
+ echo "✗ Failed to export $org_file"
+ return 1
+ fi
+ )
+}
+
+export_org_files_to_html() {
+ echo "🔍 Searching for .org files in doc/ ..."
+ echo "======================================="
+
+ mapfile -t ORG_FILES < <(find doc -type f -name "*.org" | sort)
+
+ if [ ${#ORG_FILES[@]} -eq 0 ]; then
+ echo "❌ No .org files found!"
+ return 1
+ fi
+
+ echo "Found ${#ORG_FILES[@]} .org file(s):"
+ printf '%s\n' "${ORG_FILES[@]}"
+ echo "======================================="
+
+ SUCCESS_COUNT=0
+ FAILED_COUNT=0
+
+ for org_file in "${ORG_FILES[@]}"; do
+ export_org_to_html "$org_file"
+ if [ $? -eq 0 ]; then
+ ((SUCCESS_COUNT++))
+ else
+ ((FAILED_COUNT++))
+ fi
+ done
+
+ echo "======================================="
+ echo "📊 SUMMARY:"
+ echo " ✓ Successful: $SUCCESS_COUNT"
+ echo " ✗ Failed: $FAILED_COUNT"
+ echo " Total: $((SUCCESS_COUNT + FAILED_COUNT))"
+ echo ""
+}
+
+build_visualization_graphs() {
+ rm -rf doc/graphs/
+ mkdir -p doc/graphs/
+
+ # javainspect -j target/sixth-3d-demos.jar -d doc/graphs/ -n "All classes" -t png -w "eu.svjatoslav.sixth.e3d.examples.*"
+ javainspect -j target/sixth-3d-demos.jar -d doc/graphs/ -n "Game of Life" -t png -w "eu.svjatoslav.sixth.e3d.examples.life_demo.*"
+
+ meviz index -w doc/graphs/ -t "Sixth 3D Demos classes"
+}
+
+# Build project jar file and JavaDocs
+mvn clean package
+
+# Put generated JavaDoc HTML files to documentation directory
+rm -rf doc/apidocs/
+cp -r target/apidocs/ doc/
+
+# Copy runnable jar file for publishing on website.
+cp target/sixth-3d-demos.jar doc/
+
+
+# Publish Emacs org-mode files into HTML format
+export_org_files_to_html
+
+# Generate nice looking code visualization diagrams
+build_visualization_graphs
+
+
+## Upload assembled documentation to server
+echo "📤 Uploading to server..."
+rsync -avz --delete -e 'ssh -p 10006' doc/ \
+ n0@www3.svjatoslav.eu:/mnt/big/projects/sixth-3d-demos/
+
+if [ $? -eq 0 ]; then
+ echo "✓ Upload completed successfully!"
+else
+ echo "✗ Upload failed!"
+fi
+
+echo ""
+echo "Press ENTER to close this window."
+read
--- /dev/null
+apidocs/
+sixth-3d-demos.jar
--- /dev/null
+#+SETUPFILE: ~/.emacs.d/org-styles/html/darksun.theme
+#+TITLE: Sixth 3D engine demos
+#+LANGUAGE: en
+#+LATEX_HEADER: \usepackage[margin=1.0in]{geometry}
+#+LATEX_HEADER: \usepackage{parskip}
+#+LATEX_HEADER: \usepackage[none]{hyphenat}
+
+#+OPTIONS: H:20 num:20
+#+OPTIONS: author:nil
+
+#+begin_export html
+<style>
+ .flex-center {
+ display: flex; /* activate flexbox */
+ justify-content: center; /* horizontally center anything inside */
+ }
+
+ .flex-center video {
+ width: min(90%, 1000px); /* whichever is smaller wins */
+ height: auto; /* preserve aspect ratio */
+ }
+
+ .responsive-img {
+ width: min(100%, 1000px);
+ height: auto;
+ }
+</style>
+#+end_export
+
+
+* Overview
+:PROPERTIES:
+:CUSTOM_ID: overview
+:ID: 4430626f-21f4-42d7-89b1-7097a0b99916
+:END:
+
+
+#+attr_html: :class responsive-img
+#+attr_latex: :width 1000px
+[[file:overview.png]]
+
+Goal of this project is to show off capabilities and API usage of
+[[https://www3.svjatoslav.eu/projects/sixth-3d/][Sixth 3D]] engine.
+
+All [[id:5f88b493-6ab3-4659-8280-803f75dbd5e0][example scenes in this repository]] render at interactive
+framerates.
+
+You can download pre-compiled runnable JAR file with embedded demos
+from here: [[file:sixth-3d-demos.jar]]
+
+It requires Java 21 or newer to run.
+
+To start demo application, use command:
+: java -jar sixth-3d-demos.jar
+
+* Navigating in space
+:PROPERTIES:
+:CUSTOM_ID: navigating-in-space
+:ID: 0aca7419-48df-48ac-b18b-a8bf7b9db0ac
+:END:
+
+| key | result |
+|---------------------+--------------------------------------|
+| Keyboard arrow keys | Move: left, right, forward, backward |
+| Mouse scroll wheel | Move: up <-> down |
+| Mouse drag | Turn head around in 3D space |
+
+* Example scenes
+:PROPERTIES:
+:CUSTOM_ID: example-scenes
+:ID: 5f88b493-6ab3-4659-8280-803f75dbd5e0
+:END:
+
+** Conway's Game of Life
+:PROPERTIES:
+:CUSTOM_ID: conways-game-of-life
+:ID: 08914390-742b-4c78-88bf-602ab9640082
+:END:
+
+The Game of Life, also known simply as Life, is a cellular automaton
+devised by the British mathematician John Horton Conway in 1970.
+
++ https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
+ + Game rules:
+ + 2 cell states: alive / dead
+ + Each cell sees 8 neighboring cells.
+ + If alive cell neighbors count is 2 or 3, then cell survives,
+ otherwise it dies.
+ + Dead cell becomes alive if neighbors count is exactly 3.
+
+[[file:screenshots/life.png]]
+
+Current application projects 2D game grid/matrix onto three
+dimensional space. Extra dimension (height) is used to visualize
+history (previous iterations) using glowing dots suspended in space.
+
+Usage:
+| key | result |
+|--------------------------------+--------------------------------------|
+| mouse click on the cell (cell) | toggles cell state |
+| <space> | next iteration |
+| ENTER | next iteeration with the history |
+| "c" | clear the matrix |
+
+** Text editors
+:PROPERTIES:
+:CUSTOM_ID: text-editors
+:ID: 39250157-db8e-4861-a21b-8568912bd160
+:END:
+
+[[file:screenshots/text editors.png]]
+
+Initial test for creating user interfaces in 3D and:
++ window focus handling
++ picking objecs using mouse
++ redirecting keyboard input to focused window
+
+
+Window focus acts like a stack.
+
+When window is clicked with the mouse, previously focused window (if
+any) is pushed to the focus stack and new window receives focus. Red
+frame appears around the window to indicate this.
+
+When ESC key is pressed, window focus is returned to previous window
+(if any).
+
+When any window is focused, all keyboard input is redirected to that
+window, including cursor keys. To be able to navigate around the world
+again, window must be unfocused first using ESC key.
+
+
++ TODO:
+ + Improve focus handling:
+ + Perhaps add shortcut to navigate world without exiting entire
+ stack of focus.
+ + Possibility to retain and reuse recently focused elements.
+ + Store user location in the world and view direction with the
+ focused window. So that when returning focus to far away object,
+ user is redirected also to proper location in the world.
+ + Possibility to store recently visited locations in the world and
+ return to them.
+
+** Text editors demo gallery
+:PROPERTIES:
+:CUSTOM_ID: text-editors-demo-gallery
+:ID: a7b8c9d0-e1f2-3456-0123-567890123456
+:END:
+
+*Quite a lot of text editors can be rendered:*
+
+[[file:screenshots/text editors 2.png]]
+
+See also [[https://hackers-1995.vercel.app/][similar looking web based demo]] ! :)
+
+** Mathematical formulas
+:PROPERTIES:
+:CUSTOM_ID: mathematical-formulas
+:ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890
+:END:
+
+[[file:screenshots/mathematical formulas.png]]
+
++ TODO: instead of projecting 2D visualizations onto 3D space,
+ visualize some formula using all 3 dimensions avaliable.
+
+** Sine heightmaps and sphere
+:PROPERTIES:
+:CUSTOM_ID: sine-heightmaps-and-sphere
+:ID: b2c3d4e5-f6a7-8901-bcde-f12345678901
+:END:
+
+[[file:screenshots/sinus heightmaps and sphere.png]]
+
+Simple test scene. Easy to implement and looks nice.
+
+** Raytracing through voxels
+:PROPERTIES:
+:CUSTOM_ID: raytracing-through-voxels
+:ID: c3d4e5f6-a7b8-9012-cdef-123456789012
+:END:
+
+[[file:screenshots/raytracing fractal in voxel polygon hybrid scene.png]]
+
+Test scene that is generated simultaneously using:
++ conventional polygons
+ + for realtime navigation, and
++ voxels
+ + for on-demand raytracing
+
+Instead of storing voxels in dumb [X * Y * Z] array, dynamically
+partitioned [[https://en.wikipedia.org/wiki/Octree][octree]] is used to compress data. Press "r" key anywhere in
+the scene to raytrace current view through compressed voxel
+datastructure.
+
+** Fill-rate test
+:PROPERTIES:
+:CUSTOM_ID: fill-rate-test
+:ID: e5f6a7b8-c9d0-1234-ef01-345678901234
+:END:
+
+A benchmark for polygon rasterization performance testing. This demo
+tests pixel fill throughput by rendering 40 large screen-filling quads
+(600x600) layered at different Z depths.
+
+The low vertex count (4 vertices per quad) combined with high overdraw
+isolates the pixel fill cost from vertex processing overhead, allowing
+you to measure pure rasterization performance.
+
+Controls:
+| key | result |
+|-----+---------------------|
+| 1 | Solid colored quads |
+| 2 | Textured quads |
+
+Compare FPS between solid and textured modes to see exactly what
+texture sampling costs on your hardware.
+
+* Source code
+:PROPERTIES:
+:CUSTOM_ID: source-code
+:ID: d4e5f6a7-b8c9-0123-def0-234567890123
+:END:
+
+*This program is free software: released under Creative Commons Zero
+(CC0) license*
+
+*Program author:*
+- Svjatoslav Agejenko
+- Homepage: https://svjatoslav.eu
+- Email: mailto://svjatoslav@svjatoslav.eu
+- See also: [[https://www.svjatoslav.eu/projects/][Other software projects hosted at svjatoslav.eu]]
+
+*Getting the source code:*
+- [[https://www2.svjatoslav.eu/gitweb/?p=sixth-3d-demos.git;a=snapshot;h=HEAD;sf=tgz][Download latest snapshot in TAR GZ format]]
+- [[https://www2.svjatoslav.eu/gitweb/?p=sixth-3d-demos.git;a=summary][Browse Git repository online]]
+- Clone Git repository using command:
+ : git clone https://www2.svjatoslav.eu/git/sixth-3d-demos.git
+
+*Understanding the Sixth 3D demos source code:*
+- Read online [[https://www3.svjatoslav.eu/projects/sixth-3d-demos/apidocs/][JavaDoc]].
+- Study underlying [[https://www3.svjatoslav.eu/projects/sixth-3d/][Sixth 3D]] engine.
--- /dev/null
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>eu.svjatoslav</groupId>
+ <artifactId>sixth-3d-demos</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Sixth 3D demos</name>
+ <description>3D engine demos</description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <maven.compiler.source>21</maven.compiler.source>
+ <maven.compiler.target>21</maven.compiler.target>
+ </properties>
+
+ <organization>
+ <name>svjatoslav.eu</name>
+ <url>https://svjatoslav.eu</url>
+ </organization>
+
+ <dependencies>
+ <dependency>
+ <groupId>eu.svjatoslav</groupId>
+ <artifactId>sixth-3d</artifactId>
+ <version>1.4-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>eu.svjatoslav</groupId>
+ <artifactId>svjatoslavcommons</artifactId>
+ <version>1.8</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.11.0</version>
+ <configuration>
+ <source>21</source>
+ <target>21</target>
+ <optimize>true</optimize>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>3.6.0</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <!-- workaround for https://bugs.openjdk.java.net/browse/JDK-8212233 -->
+ <javaApiLinks>
+ <property>
+ <name>foo</name>
+ <value>bar</value>
+ </property>
+ </javaApiLinks>
+ <!-- Workaround for https://stackoverflow.com/questions/49472783/maven-is-unable-to-find-javadoc-command -->
+ <javadocExecutable>${java.home}/bin/javadoc</javadocExecutable>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.4.3</version>
+ <configuration>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>eu.svjatoslav.sixth.e3d.examples.launcher.Main</mainClass>
+ </manifest>
+ </archive>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <finalName>sixth-3d-demos</finalName>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+
+ <executions>
+ <execution>
+ <id>package-jar-with-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <archive>
+ <manifest>
+ <mainClass>eu.svjatoslav.sixth.e3d.examples.launcher.Main</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-ssh-external</artifactId>
+ <version>2.6</version>
+ </extension>
+ </extensions>
+ </build>
+
+
+ <distributionManagement>
+ <snapshotRepository>
+ <id>svjatoslav.eu</id>
+ <name>svjatoslav.eu</name>
+ <url>scpexe://svjatoslav.eu:10006/srv/maven</url>
+ </snapshotRepository>
+ <repository>
+ <id>svjatoslav.eu</id>
+ <name>svjatoslav.eu</name>
+ <url>scpexe://svjatoslav.eu:10006/srv/maven</url>
+ </repository>
+ </distributionManagement>
+
+ <repositories>
+ <repository>
+ <id>svjatoslav.eu</id>
+ <name>Svjatoslav repository</name>
+ <url>https://www3.svjatoslav.eu/maven/</url>
+ </repository>
+ </repositories>
+
+ <scm>
+ <connection>scm:git:ssh://n0@svjatoslav.eu/home/git/repositories/sixth-3d-demos.git</connection>
+ <developerConnection>scm:git:ssh://n0@svjatoslav.eu/home/git/repositories/sixth-3d-demos.git
+ </developerConnection>
+ </scm>
+
+
+</project>
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
+
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point2D;
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.Camera;
+import eu.svjatoslav.sixth.e3d.gui.FrameListener;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationUserInputTracker;
+import eu.svjatoslav.sixth.e3d.math.Vertex;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.texturedpolygon.TexturedPolygon;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonCube;
+import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
+
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Fill-rate benchmark demo that tests the engine's rendering performance.
+ * Creates a 16x16x16 grid of cubes (4096 total) that orbit around the center point.
+ * The camera follows a wobbling orbital path while FPS statistics are printed to console.
+ *
+ * <p>Key controls:
+ * <ul>
+ * <li>Press 1 - Switch to solid color cubes (faster rendering)</li>
+ * <li>Press 2 - Switch to textured cubes (slower rendering, tests texture fill-rate)</li>
+ * </ul>
+ *
+ * @see SolidPolygonCube
+ * @see TexturedPolygon
+ */
+public class FillRateTest extends WorldNavigationUserInputTracker implements FrameListener {
+
+ /** Number of cubes along each axis of the grid. */
+ private static final int GRID_SIZE = 16;
+ /** Spacing between cube centers in world units. */
+ private static final double SPACING = 80;
+ /** Half-size of each cube. */
+ private static final double CUBE_SIZE = 25;
+ /** Distance of camera from center during orbit. */
+ private static final double ORBIT_DISTANCE = 1200;
+ /** Angular speed of camera orbit in radians per millisecond. */
+ private static final double ORBIT_SPEED = 0.0003;
+ /** Amplitude of vertical wobble during orbit. */
+ private static final double WOBBLE_AMPLITUDE = 800;
+ /** Number of unique textures to create for textured mode. */
+ private static final int TEXTURE_COUNT = 20;
+
+ private final ViewFrame viewFrame;
+ private final ViewPanel viewPanel;
+ private final ShapeCollection shapes;
+ private final Random random = new Random(42);
+ private final Camera camera;
+
+ private final List<Object> cubes = new ArrayList<>();
+ private final Texture[] textures = new Texture[TEXTURE_COUNT];
+ private final int[] cubeTextureIndices;
+
+ private boolean texturedMode = false;
+ private double orbitAngle = 0;
+
+ private long frameCount = 0;
+ private long fpsStartTime = System.currentTimeMillis();
+ private long totalFrameCount = 0;
+ private long appStartTime = System.currentTimeMillis();
+
+ /** Resets FPS statistics counters. */
+ private void resetFpsStats() {
+ frameCount = 0;
+ fpsStartTime = System.currentTimeMillis();
+ totalFrameCount = 0;
+ appStartTime = fpsStartTime;
+ }
+
+ /**
+ * Entry point for the fill-rate test demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(String[] args) {
+ new FillRateTest();
+ }
+
+ /**
+ * Constructs the fill-rate test demo with a 1920x1080 window.
+ * Creates the cube grid and initializes camera orbit animation.
+ */
+ public FillRateTest() {
+ viewFrame = new ViewFrame(1920, 1080);
+ viewPanel = viewFrame.getViewPanel();
+ viewPanel.setFrameRate(0);
+ shapes = viewPanel.getRootShapeCollection();
+
+ viewPanel.addFrameListener(this);
+ viewPanel.getKeyboardFocusStack().pushFocusOwner(this);
+
+ camera = viewPanel.getCamera();
+
+ cubeTextureIndices = new int[GRID_SIZE * GRID_SIZE * GRID_SIZE];
+ for (int i = 0; i < cubeTextureIndices.length; i++) {
+ cubeTextureIndices[i] = random.nextInt(TEXTURE_COUNT);
+ }
+
+ createTextures();
+ createCubes(false);
+ }
+
+ /** Creates the pool of randomly colored glow textures. */
+ private void createTextures() {
+ for (int i = 0; i < TEXTURE_COUNT; i++) {
+ textures[i] = createGlowTexture(
+ 50 + random.nextInt(200),
+ 50 + random.nextInt(200),
+ 50 + random.nextInt(200)
+ );
+ }
+ }
+
+ /**
+ * Creates a glow texture with the specified RGB color.
+ * @param r red component (0-255)
+ * @param g green component (0-255)
+ * @param b blue component (0-255)
+ * @return a 64x64 texture with glowing border effect
+ */
+ private Texture createGlowTexture(int r, int g, int b) {
+ int texSize = 64;
+ Texture texture = new Texture(texSize, texSize, 2);
+
+ java.awt.Graphics2D gr = texture.graphics;
+ gr.setBackground(new java.awt.Color(r, g, b, 80));
+ gr.clearRect(0, 0, texSize, texSize);
+
+ int glowWidth = 6;
+ for (int i = 0; i < glowWidth; i++) {
+ int intensity = (int) (255.0 * (glowWidth - i) / glowWidth);
+ java.awt.Color glowColor = new java.awt.Color(
+ Math.min(255, r + intensity),
+ Math.min(255, g + intensity),
+ Math.min(255, b + intensity),
+ 200 - i * 30
+ );
+ gr.setColor(glowColor);
+ gr.drawRect(i, i, texSize - 1 - 2 * i, texSize - 1 - 2 * i);
+ }
+
+ gr.dispose();
+ texture.resetResampledBitmapCache();
+ return texture;
+ }
+
+ /** Removes all cubes from the scene. */
+ private void clearCubes() {
+ for (Object cube : cubes) {
+ shapes.getShapes().remove(cube);
+ }
+ cubes.clear();
+ }
+
+ /**
+ * Creates the grid of cubes in the scene.
+ * @param textured if true, creates textured cubes; if false, creates solid-colored cubes
+ */
+ private void createCubes(boolean textured) {
+ clearCubes();
+ random.setSeed(42);
+
+ double offset = -(GRID_SIZE - 1) * SPACING / 2;
+ int idx = 0;
+
+ for (int x = 0; x < GRID_SIZE; x++) {
+ for (int y = 0; y < GRID_SIZE; y++) {
+ for (int z = 0; z < GRID_SIZE; z++) {
+ double px = offset + x * SPACING;
+ double py = offset + y * SPACING;
+ double pz = offset + z * SPACING;
+
+ if (textured) {
+ Texture tex = textures[cubeTextureIndices[idx]];
+ TexturedCube cube = new TexturedCube(
+ new Point3D(px, py, pz),
+ CUBE_SIZE,
+ tex
+ );
+ shapes.addShape(cube);
+ cubes.add(cube);
+ } else {
+ Color color = new Color(
+ 50 + random.nextInt(150),
+ 100 + random.nextInt(155),
+ 50 + random.nextInt(150),
+ 40
+ );
+ SolidPolygonCube cube = new SolidPolygonCube(
+ new Point3D(px, py, pz),
+ CUBE_SIZE,
+ color
+ );
+ shapes.addShape(cube);
+ cubes.add(cube);
+ }
+ idx++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Called each frame to animate the camera orbit and track FPS.
+ * @param viewPanel the view panel rendering the scene
+ * @param millisecondsSinceLastFrame time elapsed since last frame
+ * @return true to continue rendering
+ */
+ @Override
+ public boolean onFrame(ViewPanel viewPanel, int millisecondsSinceLastFrame) {
+ orbitAngle += ORBIT_SPEED * millisecondsSinceLastFrame;
+
+ double x = Math.sin(orbitAngle) * ORBIT_DISTANCE;
+ double z = Math.cos(orbitAngle) * ORBIT_DISTANCE;
+ double y = Math.sin(orbitAngle * 1.8934) * WOBBLE_AMPLITUDE;
+
+ camera.getTransform().setTranslation(new Point3D(x, y, z));
+ camera.lookAt(new Point3D(0, 0, 0));
+
+ frameCount++;
+ totalFrameCount++;
+ long now = System.currentTimeMillis();
+ long elapsed = now - fpsStartTime;
+ if (elapsed >= 1000) {
+ int fps = (int) (frameCount * 1000 / elapsed);
+ long totalElapsed = now - appStartTime;
+ double avgFps = totalFrameCount * 1000.0 / totalElapsed;
+ System.out.println("current: " + fps + " average: " + String.format("%.2f", avgFps));
+ frameCount = 0;
+ fpsStartTime = now;
+ }
+
+ return true;
+ }
+
+ /**
+ * Handles keyboard input for switching between rendering modes.
+ * @param event the key event
+ * @param viewPanel the view panel
+ * @return true if the event was consumed
+ */
+ @Override
+ public boolean keyPressed(KeyEvent event, ViewPanel viewPanel) {
+ switch (event.getKeyCode()) {
+ case KeyEvent.VK_1:
+ if (texturedMode) {
+ texturedMode = false;
+ createCubes(false);
+ resetFpsStats();
+ }
+ return true;
+ case KeyEvent.VK_2:
+ if (!texturedMode) {
+ texturedMode = true;
+ createCubes(true);
+ resetFpsStats();
+ }
+ return true;
+ }
+ return super.keyPressed(event, viewPanel);
+ }
+
+ /**
+ * A cube composed of textured polygons.
+ * Each face is rendered as two triangles with UV coordinates for texture mapping.
+ */
+ private static class TexturedCube extends AbstractCompositeShape {
+
+ /**
+ * Constructs a textured cube at the specified position.
+ * @param center the center position of the cube
+ * @param size half-size of the cube (total width is 2*size)
+ * @param texture the texture to apply to all faces
+ */
+ public TexturedCube(Point3D center, double size, Texture texture) {
+ double s = size;
+ Point3D p1 = new Point3D(center.x - s, center.y - s, center.z - s);
+ Point3D p7 = new Point3D(center.x + s, center.y + s, center.z + s);
+
+ Point3D p2 = new Point3D(p7.x, p1.y, p1.z);
+ Point3D p3 = new Point3D(p7.x, p1.y, p7.z);
+ Point3D p4 = new Point3D(p1.x, p1.y, p7.z);
+ Point3D p5 = new Point3D(p1.x, p7.y, p1.z);
+ Point3D p6 = new Point3D(p7.x, p7.y, p1.z);
+ Point3D p8 = new Point3D(p1.x, p7.y, p7.z);
+
+ Point2D t00 = new Point2D(0, 0);
+ Point2D t10 = new Point2D(64, 0);
+ Point2D t01 = new Point2D(0, 64);
+ Point2D t11 = new Point2D(64, 64);
+
+ addTexturedFace(p1, p2, p3, p4, t00, t10, t11, t01, texture);
+ addTexturedFace(p5, p8, p7, p6, t00, t01, t11, t10, texture);
+ addTexturedFace(p1, p5, p6, p2, t00, t01, t11, t10, texture);
+ addTexturedFace(p3, p7, p8, p4, t00, t10, t11, t01, texture);
+ addTexturedFace(p1, p4, p8, p5, t00, t10, t11, t01, texture);
+ addTexturedFace(p2, p6, p7, p3, t00, t01, t11, t10, texture);
+
+ setBackfaceCulling(true);
+ }
+
+ /**
+ * Adds a quad face as two textured triangles.
+ * @param p1 first corner position
+ * @param p2 second corner position
+ * @param p3 third corner position
+ * @param p4 fourth corner position
+ * @param t1 texture coordinate for p1
+ * @param t2 texture coordinate for p2
+ * @param t3 texture coordinate for p3
+ * @param t4 texture coordinate for p4
+ * @param texture the texture to apply
+ */
+ private void addTexturedFace(Point3D p1, Point3D p2, Point3D p3, Point3D p4,
+ Point2D t1, Point2D t2, Point2D t3, Point2D t4,
+ Texture texture) {
+ TexturedPolygon tri1 = new TexturedPolygon(
+ new Vertex(p1, t1),
+ new Vertex(p2, t2),
+ new Vertex(p3, t3),
+ texture
+ );
+ tri1.setBackfaceCulling(true);
+
+ TexturedPolygon tri2 = new TexturedPolygon(
+ new Vertex(p1, t1),
+ new Vertex(p3, t3),
+ new Vertex(p4, t4),
+ texture
+ );
+ tri2.setBackfaceCulling(true);
+
+ addShape(tri1);
+ addShape(tri2);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point2D;
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.Graph;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.WireframeSphere;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Demo showing various mathematical function graphs rendered in 3D.
+ * Displays sine, cosine, tangent, and composite function graphs arranged around
+ * a central sphere, with two wobbly surfaces above and below.
+ */
+public class GraphDemo {
+
+ /** Frequency of the wave pattern in the wobbly surfaces. */
+ private static final double WAVE_FREQUENCY = 50d;
+ /** Amplitude of the wave pattern in the wobbly surfaces. */
+ private static final double WAVE_AMPLITUDE = 50d;
+ /** Color for the square plates in the wobbly surfaces. */
+ private static final Color SQUARE_PLATE_COLOR = new Color("88F7");
+ /** Scale factor for the graph rendering. */
+ private static final double GRAPH_SCALE = 50d;
+
+ /**
+ * Creates a single square plate at the specified position.
+ * @param shapeCollection the collection to add the plate to
+ * @param y the Y coordinate (elevation)
+ * @param x the X coordinate
+ * @param z the Z coordinate
+ */
+ private static void makeSquarePlate(final ShapeCollection shapeCollection,
+ final double y, final double x, final double z) {
+ final Point3D p1 = new Point3D(x, y, z);
+ final Point3D p2 = new Point3D(x + 20, y, z);
+ final Point3D p3 = new Point3D(x, y, z + 20);
+ final Point3D p4 = new Point3D(x + 20, y, z + 20);
+ final SolidPolygon polygon1 = new SolidPolygon(p1, p2, p3, SQUARE_PLATE_COLOR);
+ final SolidPolygon polygon2 = new SolidPolygon(p4, p2, p3, SQUARE_PLATE_COLOR);
+ shapeCollection.addShape(polygon1);
+ shapeCollection.addShape(polygon2);
+ }
+
+ /**
+ * Creates a wobbly surface composed of square plates arranged in a wave pattern.
+ * @param shapeCollection the collection to add plates to
+ * @param surfaceElevation the base Y elevation of the surface
+ */
+ private static void addWobblySurface(final ShapeCollection shapeCollection,
+ final double surfaceElevation) {
+ for (double x = -500; x < 500; x += 20)
+ for (double z = -500; z < 500; z += 20) {
+
+ // use Pythagorean theorem to compute distance from the center
+ final double distanceFromCenter = Math.sqrt((x * x) + (z * z));
+
+ double plateElevation = Math.sin(distanceFromCenter / WAVE_FREQUENCY) * WAVE_AMPLITUDE;
+
+ makeSquarePlate(shapeCollection, plateElevation + surfaceElevation, x,
+ z);
+ }
+ }
+
+ /**
+ * Creates a graph of the cosine function.
+ * @param location the position of the graph in 3D space
+ * @return a Graph component showing y = cos(x)
+ */
+ private static Graph getCosineGraph(final Point3D location) {
+ final List<Point2D> data = new ArrayList<>();
+ for (double x = 0; x < 20; x += 0.25) {
+ final double y = Math.cos(x);
+
+ final Point2D p = new Point2D(x, y);
+ data.add(p);
+ }
+
+ return new Graph(GRAPH_SCALE, data, "Cosine", location);
+ }
+
+ /**
+ * Creates a graph of y = sin(tan(x)).
+ * @param location the position of the graph in 3D space
+ * @return a Graph component showing the composite function
+ */
+ private static Graph getFormula1Graph(final Point3D location) {
+ final List<Point2D> data = new ArrayList<>();
+ for (double x = 0; x < 20; x += 0.25) {
+ final double y = Math.sin(Math.tan(x));
+
+ final Point2D p = new Point2D(x, y);
+ data.add(p);
+ }
+
+ return new Graph(GRAPH_SCALE, data, "y = sin(tan(x))", location);
+ }
+
+ /**
+ * Creates a graph of y = (10-x)^2 / 30.
+ * @param location the position of the graph in 3D space
+ * @return a Graph component showing the parabola
+ */
+ private static Graph getFormula2Graph(final Point3D location) {
+ final List<Point2D> data = new ArrayList<>();
+ for (double x = 0; x < 20; x += 0.25) {
+ final double y = (Math.pow((10 - x), 2) / 30) - 2;
+
+ final Point2D p = new Point2D(x, y);
+ data.add(p);
+ }
+
+ return new Graph(GRAPH_SCALE, data, "y = ( (10-x)^2 ) / 30", location);
+ }
+
+ /**
+ * Creates a graph of y = sin(x/2) + sin(x/1.26).
+ * @param location the position of the graph in 3D space
+ * @return a Graph component showing the composite sine wave
+ */
+ private static Graph getFormula3Graph(final Point3D location) {
+ final List<Point2D> data = new ArrayList<>();
+ for (double x = 0; x < 20; x += 0.25) {
+ final double y = Math.sin(x / 2) + Math.sin(x / 1.26);
+
+ final Point2D p = new Point2D(x, y);
+ data.add(p);
+ }
+
+ return new Graph(GRAPH_SCALE, data, "y = sin(x/2) + sin(x/1.26)", location);
+ }
+
+ /**
+ * Creates a graph of the sine function.
+ * @param location the position of the graph in 3D space
+ * @return a Graph component showing y = sin(x)
+ */
+ private static Graph getSineGraph(final Point3D location) {
+ final List<Point2D> data = new ArrayList<>();
+ for (double x = 0; x < 20; x += 0.25) {
+ final double y = Math.sin(x);
+
+ final Point2D p = new Point2D(x, y);
+ data.add(p);
+ }
+
+ return new Graph(GRAPH_SCALE, data, "Sine", location);
+ }
+
+ /**
+ * Creates a graph of the tangent function with clamped values.
+ * @param location the position of the graph in 3D space
+ * @return a Graph component showing y = tan(x) with clamped range
+ */
+ private static Graph getTangentGraph(final Point3D location) {
+ final List<Point2D> data = new ArrayList<>();
+ for (double x = 0; x < 20; x += 0.25) {
+ double y = Math.tan(x);
+
+ if (y > 2)
+ y = 2;
+ if (y < -2)
+ y = -2;
+
+ final Point2D p = new Point2D(x, y);
+ data.add(p);
+ }
+
+ return new Graph(GRAPH_SCALE, data, "Tangent", location);
+ }
+
+ /**
+ * Entry point for the graph demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+
+ final ViewFrame viewFrame = new ViewFrame();
+ final ShapeCollection geometryCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ addMathFormulas(geometryCollection);
+ addSphere(geometryCollection);
+ addWobblySurface(geometryCollection, 200);
+ addWobblySurface(geometryCollection, -200);
+
+ setCameraLocation(viewFrame);
+ }
+
+ /**
+ * Adds a wireframe sphere at the center of the scene.
+ * @param geometryCollection the collection to add the sphere to
+ */
+ private static void addSphere(ShapeCollection geometryCollection) {
+ // add sphere
+ geometryCollection.addShape(new WireframeSphere(new Point3D(0, 0, 0),
+ 100,
+ new LineAppearance(
+ 4,
+ new Color(255,0, 0, 30))
+ ));
+ }
+
+ /**
+ * Adds all mathematical formula graphs to the scene.
+ * @param geometryCollection the collection to add graphs to
+ */
+ private static void addMathFormulas(ShapeCollection geometryCollection) {
+ int z = 1000;
+ Point3D location = new Point3D(-600, -300, z);
+ geometryCollection.addShape(getSineGraph(location));
+
+ location = new Point3D(600, -300, z);
+ geometryCollection.addShape(getFormula1Graph(location));
+
+ location = new Point3D(-600, 0, z);
+ geometryCollection.addShape(getCosineGraph(location));
+
+ location = new Point3D(600, 0, z);
+ geometryCollection.addShape(getFormula2Graph(location));
+
+ location = new Point3D(-600, 300, z);
+ geometryCollection.addShape(getTangentGraph(location));
+
+ location = new Point3D(600, 300, z);
+ geometryCollection.addShape(getFormula3Graph(location));
+ }
+
+ /**
+ * Sets the camera to an initial viewing position.
+ * @param viewFrame the view frame whose camera to configure
+ */
+ private static void setCameraLocation(ViewFrame viewFrame) {
+ viewFrame.getViewPanel().getCamera().getTransform().setTranslation(new Point3D(0, 0, -500));
+ }
+
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationUserInputTracker;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.octree.IntegerPoint;
+import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
+import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.RaytracingCamera;
+import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.LightSource;
+import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.RayTracer;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.GlowingPoint;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.LightSourceMarker;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonRectangularBox;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid3D;
+
+import java.awt.event.KeyEvent;
+import java.util.Vector;
+
+/**
+ * Demo showing volumetric octree rendering with raytracing capability.
+ * Creates a 3D scene with various geometric shapes stored in an octree data structure.
+ * Press 'r' to render the current view using software raytracing.
+ */
+public class OctreeDemo extends WorldNavigationUserInputTracker {
+
+ /** Scale factor for rendering octree voxels in the scene. */
+ private static final double magnification = 5;
+ private final LineAppearance gridAppearance = new LineAppearance(40, new Color(255,
+ 0, 0, 60));
+ private final Vector<LightSource> lights = new Vector<>();
+ private OctreeVolume octreeVolume;
+ private ShapeCollection shapeCollection;
+ private ViewPanel viewPanel;
+
+ /**
+ * Entry point for the octree demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+ new OctreeDemo().init();
+ }
+
+ /**
+ * Adds a light source to both the visual scene and the raytracer.
+ * @param location position of the light
+ * @param color color of the light
+ * @param brightness intensity of the light
+ */
+ private void addLight(final Point3D location, final Color color,
+ final float brightness) {
+ shapeCollection.addShape(new LightSourceMarker(new Point3D(location)
+ .scaleUp(magnification), color));
+
+ final LightSource lightSource = new LightSource(location, color,
+ brightness);
+
+ lights.add(lightSource);
+ }
+
+ /** Creates a colorful spiral pattern of voxels in the octree. */
+ private void dotSpiral() {
+ for (double i = 0; i < 20; i = i + .1) {
+
+ double w = 1;
+ double h = 1;
+
+ final double x = Math.sin(i) * 20f * h;
+ final double y = Math.cos(i) * 20f * w;
+ final double c1 = (Math.cos(i * 3f) * 100) + 127;
+ final double c2 = (Math.cos(i * 5.3332f) * 100f) + 127;
+ final double c3 = (Math.cos(i * 1.342f) * 100f) + 127;
+
+ putPixel((int) x, (int) y, (int) (i * 4f), new Color((int) c1,
+ (int) c2, (int) c3, 255));
+ }
+ }
+
+ /**
+ * Recursively creates a fractal pattern of rectangles.
+ * @param x center X coordinate
+ * @param y center Y coordinate
+ * @param z center Z coordinate
+ * @param size size of the current rectangle
+ * @param step recursion depth counter
+ */
+ private void fractal(final int x, final int y, final int z, final int size,
+ final int step) {
+ final double c1 = (Math.cos(y / 7f) * 100f) + 127;
+ final double c2 = (Math.cos(x / 10f) * 100f) + 127;
+ final double c3 = (Math.cos(z / 12f) * 100f) + 127;
+
+ putRect(
+ new IntegerPoint( x - size, y - size, z - size),
+ new IntegerPoint( x + size, y + size, z + size),
+ new Color((int) c1, (int) c2, (int) c3, 100));
+
+ if (size > 1) {
+ fractal(x, y - (size * 3), z, size / 2, step + 1);
+ fractal(x + (size * 3), y, z, size / 2, step + 1);
+ fractal(x, y, z + (size * 3), size / 2, step + 1);
+ }
+ }
+
+ /** Initializes the demo scene with grid, lights, shapes, and fractal pattern. */
+ private void init() {
+
+ final ViewFrame viewFrame = new ViewFrame();
+ viewPanel = viewFrame.getViewPanel();
+
+ viewPanel.getCamera().getTransform().setTranslation(new Point3D(0, -30, -300));
+
+ octreeVolume = new OctreeVolume();
+
+ shapeCollection = viewPanel.getRootShapeCollection();
+
+ shapeCollection.addShape(new Grid3D(
+ new Point3D(-10000, -10000, -10000), new Point3D(10000, 10000,
+ 10000), 4000, gridAppearance));
+
+ // yellow light
+ addLight(new Point3D(20, -450, 240), new Color(255, 255, 255, 255), 100);
+
+ // red light
+ addLight(new Point3D(-150, -116, 141), new Color(255, 0, 0, 255), 10);
+
+ dotSpiral();
+
+ // arbitrary rectangles
+ putRect(new IntegerPoint(-10, -10, -10),
+ new IntegerPoint(10, 10, -20),
+ new Color(200, 255, 200, 100));
+
+ putRect(new IntegerPoint(-3, 0, -30),
+ new IntegerPoint( 12, 3, 300),
+ new Color(255, 200, 200, 100));
+
+ putRect(new IntegerPoint(-20, 20, -20),
+ new IntegerPoint(20, 80, 20),
+ new Color(255, 200, 255, 100));
+
+ tiledFloor();
+
+ fractal(-50, 20, 100, 32, 1);
+
+ final TextCanvas message = new TextCanvas(new Transform(new Point3D(
+ -10, 20, -180)), "Press \"r\" to raytrace current view",
+ Color.WHITE, Color.PURPLE);
+ shapeCollection.addShape(message);
+
+ viewPanel.getKeyboardFocusStack().pushFocusOwner(this);
+ viewPanel.repaintDuringNextViewUpdate();
+ }
+
+ /**
+ * Handles keyboard input for triggering raytracing.
+ * @param event the key event
+ * @param viewPanel the view panel
+ * @return true if the event was consumed
+ */
+ @Override
+ public boolean keyPressed(final KeyEvent event, final ViewPanel viewPanel) {
+
+ if ('r' == event.getKeyChar()) {
+ raytrace();
+ return true;
+ }
+ return super.keyPressed(event, viewPanel);
+ }
+
+ /**
+ * Places a single voxel at the specified position with the given color.
+ * @param x X coordinate in octree space
+ * @param y Y coordinate in octree space
+ * @param z Z coordinate in octree space
+ * @param color the color of the voxel
+ */
+ private void putPixel(final int x, final int y, final int z,
+ final Color color) {
+ shapeCollection.addShape(new GlowingPoint(new Point3D(x, y, z)
+ .scaleUp(magnification), 3 * magnification, color));
+ octreeVolume.putCell(x, y, z, color);
+
+ }
+
+ /**
+ * Fills a rectangular region in the octree with the specified color.
+ * @param p1 first corner of the rectangle
+ * @param p2 opposite corner of the rectangle
+ * @param color the color to fill
+ */
+ private void putRect(IntegerPoint p1, IntegerPoint p2, final Color color) {
+
+ shapeCollection
+ .addShape(new SolidPolygonRectangularBox(
+ new Point3D(p1).scaleUp(magnification),
+ new Point3D(p2).scaleUp(magnification), color));
+
+ octreeVolume.fillRectangle(p1, p2, color);
+ }
+
+ /** Starts a raytracing render of the current view in a background thread. */
+ private void raytrace() {
+ // create and add camera object to scene
+ final RaytracingCamera raytracingCamera = new RaytracingCamera(viewPanel.getCamera(), magnification);
+ shapeCollection.addShape(raytracingCamera);
+
+ // initialize and start Raytracer in a separate thread
+ final RayTracer rayTracer = new RayTracer(raytracingCamera.getTexture(),
+ octreeVolume, lights, raytracingCamera, viewPanel);
+ final Thread thread = new Thread(rayTracer);
+ thread.start();
+ }
+
+ /** Creates a tiled floor pattern using small rectangular tiles. */
+ private void tiledFloor() {
+ final int step = 40;
+ final int size = step - 15;
+ Color color = new Color(255, 255, 255, 100);
+ for (int x = -200; x < 200; x += step)
+ for (int z = -200; z < 200; z += step)
+ putRect(
+ new IntegerPoint(x, 100, z),
+ new IntegerPoint(x + size, 110, z + size),
+ color);
+ }
+
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.gui.FrameListener;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.AbstractShape;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas;
+
+import java.util.Collection;
+import java.util.Random;
+
+/**
+ * Demo showing numbers falling through 3D space like rain.
+ * Creates 1000 randomly positioned text canvases displaying digits 0-9,
+ * which continuously fall downward and wrap around to create a "Matrix" style effect.
+ */
+public class RainingNumbersDemo implements FrameListener {
+
+ /** Number of falling numbers in the scene. */
+ private static final int NUMBERS_COUNT = 1000;
+ /** Size of the cubic area containing the numbers. */
+ private final static int AREA = 600;
+ /** Half of the area for positioning calculations. */
+ private final static int AREA_HALF = AREA / 2;
+
+ /**
+ * Entry point for the raining numbers demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+ new RainingNumbersDemo().run();
+ }
+
+ /**
+ * Animates all text canvases to fall downward each frame.
+ * Numbers that fall below the area wrap around to the top.
+ * @param viewPanel the view panel
+ * @param millisecondsSinceLastFrame time elapsed since last frame
+ * @return true to continue animation
+ */
+ @Override
+ public boolean onFrame(final ViewPanel viewPanel,
+ final int millisecondsSinceLastFrame) {
+
+ final Collection<AbstractShape> shapes = viewPanel
+ .getRootShapeCollection().getShapes();
+
+ final double translateAmount = millisecondsSinceLastFrame / 50d;
+
+ shapes.stream().filter(shape -> shape instanceof TextCanvas).forEach(shape -> {
+ final TextCanvas block = (TextCanvas) shape;
+ final Point3D location = block.getLocation();
+ location.translateY(translateAmount);
+
+ if (location.y > AREA_HALF)
+ location.y -= AREA;
+ });
+
+ return true;
+ }
+
+ /** Initializes the demo by creating the view frame and adding falling numbers. */
+ private void run() {
+ final ViewFrame viewFrame = new ViewFrame();
+
+ final ShapeCollection geometryCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ Random random = new Random();
+
+ for (int i = 0; i < NUMBERS_COUNT; i++) {
+ final Point3D location = new Point3D((Math.random() * AREA)
+ - AREA_HALF, (Math.random() * AREA) - AREA_HALF,
+ (Math.random() * AREA) - AREA_HALF);
+
+ final Color color = new Color(Math.random(), Math.random(),
+ Math.random(), Math.random());
+
+ final TextCanvas textCanvas = new TextCanvas(
+ new Transform(location), String.valueOf(random.nextInt(10)), color,
+ Color.TRANSPARENT);
+
+ geometryCollection.addShape(textCanvas);
+ }
+
+ viewFrame.getViewPanel().addFrameListener(this);
+ }
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+ */
+
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid3D;
+
+/**
+ * Demo showing 1000 randomly positioned and colored triangles in 3D space.
+ * Demonstrates the engine's ability to render many semi-transparent polygons
+ * with proper depth sorting.
+ */
+public class RandomPolygonsDemo {
+
+ /** Average size of each random polygon. */
+ private static final double POLYGON_AVERAGE_SIZE = 130;
+ /** Number of polygons to generate. */
+ private static final int POLYGON_COUNT = 1000;
+
+ /**
+ * Adds a single random triangle to the scene.
+ * @param geometryCollection the collection to add the polygon to
+ */
+ private static void addRandomPolygon(final ShapeCollection geometryCollection) {
+ final Point3D polygonLocation = getRandomPoint(1000);
+
+ final Point3D point1 = new Point3D(polygonLocation);
+ point1.add(getRandomPoint(POLYGON_AVERAGE_SIZE));
+
+ final Point3D point2 = new Point3D(polygonLocation);
+ point2.add(getRandomPoint(POLYGON_AVERAGE_SIZE));
+
+ final Point3D point3 = new Point3D(polygonLocation);
+ point3.add(getRandomPoint(POLYGON_AVERAGE_SIZE));
+
+ final Color color = new Color(
+ getColorChannelBrightness(),
+ getColorChannelBrightness(),
+ getColorChannelBrightness(),
+ 1);
+
+ final SolidPolygon polygon = new SolidPolygon(point1, point2, point3,
+ color);
+ geometryCollection.addShape(polygon);
+ }
+
+ /**
+ * Generates a random color channel brightness.
+ * Ensures minimum brightness of 0.3 to avoid very dark polygons.
+ * @return a brightness value between 0.3 and 1.0
+ */
+ private static double getColorChannelBrightness() {
+ return Math.random() * 0.7 + 0.3f;
+ }
+
+ /**
+ * Generates a random 3D point within a cube centered at the origin.
+ * @param amplitude the half-size of the cube
+ * @return a random point within [-amplitude, amplitude] on each axis
+ */
+ private static Point3D getRandomPoint(final double amplitude) {
+ return new Point3D((Math.random() * amplitude * 2d) - amplitude,
+ (Math.random() * amplitude * 2d) - amplitude, (Math.random()
+ * amplitude * 2d)
+ - amplitude);
+ }
+
+ /**
+ * Entry point for the random polygons demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+
+ final ViewFrame viewFrame = new ViewFrame();
+
+ final ShapeCollection shapeCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ // add grid
+ final LineAppearance appearance = new LineAppearance(5, new Color(100,
+ 100, 255, 60));
+
+ shapeCollection.addShape(new Grid3D(new Point3D(1000, -1000, -1000),
+ new Point3D(-1000, 1000, 1000), 300, appearance));
+
+ // add random polygons
+ for (int i = 0; i < POLYGON_COUNT; i++)
+ addRandomPolygon(shapeCollection);
+
+ }
+}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.lighting.LightSource;
+import eu.svjatoslav.sixth.e3d.renderer.raster.lighting.LightingManager;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.LightSourceMarker;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonCube;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonCylinder;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonPyramid;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonSphere;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Demo showing a shaded sphere, cube, pyramid, and cylinder with multiple colored light sources.
+ * Ten light sources orbit around the shapes on different paths to demonstrate dynamic lighting.
+ */
+public class ShadedShapesDemo {
+
+ /** Number of orbiting light sources in the scene. */
+ private static final int LIGHT_COUNT = 10;
+
+ /**
+ * Entry point for the shaded shapes demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(String[] args) {
+ ViewFrame viewFrame = new ViewFrame();
+ ViewPanel viewPanel = viewFrame.getViewPanel();
+ ShapeCollection shapes = viewPanel.getRootShapeCollection();
+
+ LightingManager lightingManager = new LightingManager();
+ lightingManager.setAmbientLight(new Color(25, 25, 25));
+
+ Random random = new Random(42);
+ List<OrbitingLight> orbitingLights = new ArrayList<>();
+
+ for (int i = 0; i < LIGHT_COUNT; i++) {
+ Color color = new Color(
+ random.nextInt(256),
+ random.nextInt(256),
+ random.nextInt(256)
+ );
+
+ double orbitRadius = 500 + random.nextInt(200);
+ double speed = 0.01 + random.nextDouble() * 0.03;
+ double angleOffset = random.nextDouble() * Math.PI * 2;
+ double intensity = 2.0 + random.nextDouble() * 3.0;
+
+ int axis = random.nextInt(3);
+ double ellipseFactor = 0.7 + random.nextDouble() * 0.3;
+
+ LightSource light = new LightSource(new Point3D(0, 0, 0), color, intensity);
+ LightSourceMarker marker = new LightSourceMarker(light.getPosition(), color);
+
+ lightingManager.addLight(light);
+ shapes.addShape(marker);
+
+ orbitingLights.add(new OrbitingLight(
+ light, marker,
+ orbitRadius, speed, angleOffset, axis, ellipseFactor
+ ));
+ }
+
+ // Sphere
+ SolidPolygonSphere sphere = new SolidPolygonSphere(
+ new Point3D(-400, 0, 0), 150, 28, new Color(200, 210, 255)
+ );
+ sphere.setLightingManager(lightingManager);
+ shapes.addShape(sphere);
+
+ // Pyramid
+ SolidPolygonPyramid pyramid = new SolidPolygonPyramid(
+ new Point3D(0, 130, 0), 150, 260, new Color(255, 200, 200)
+ );
+ pyramid.setLightingManager(lightingManager);
+ shapes.addShape(pyramid);
+
+ // Cube
+ SolidPolygonCube cube = new SolidPolygonCube(
+ new Point3D(400, 0, 0), 150, new Color(200, 255, 200)
+ );
+ cube.setLightingManager(lightingManager);
+ shapes.addShape(cube);
+
+ // Cylinder
+ SolidPolygonCylinder cylinder = new SolidPolygonCylinder(
+ new Point3D(800, 0, 0), 120, 260, 24, new Color(255, 220, 180)
+ );
+ cylinder.setLightingManager(lightingManager);
+ shapes.addShape(cylinder);
+
+ // Camera
+ viewPanel.getCamera().getTransform().setTranslation(new Point3D(200, -250, -900));
+
+ MultiLightAnimator animator = new MultiLightAnimator(orbitingLights);
+ viewPanel.addFrameListener(animator);
+
+ viewPanel.repaintDuringNextViewUpdate();
+ }
+
+ /**
+ * Represents a light source that orbits around the scene center.
+ * Each light follows an elliptical path on one of three possible axes.
+ */
+ private static class OrbitingLight {
+ final LightSource light;
+ final LightSourceMarker marker;
+ final double orbitRadius;
+ final double speed;
+ final int axis;
+ final double ellipseFactor;
+ double angle;
+
+ /**
+ * Creates an orbiting light with the specified parameters.
+ * @param light the light source to orbit
+ * @param marker the visual marker for the light position
+ * @param orbitRadius the base radius of the orbit
+ * @param speed the angular speed of orbit
+ * @param angleOffset the starting angle offset
+ * @param axis the axis of orbit (0, 1, or 2)
+ * @param ellipseFactor the ellipse distortion factor
+ */
+ OrbitingLight(LightSource light, LightSourceMarker marker,
+ double orbitRadius, double speed, double angleOffset,
+ int axis, double ellipseFactor) {
+ this.light = light;
+ this.marker = marker;
+ this.orbitRadius = orbitRadius;
+ this.speed = speed;
+ this.angle = angleOffset;
+ this.axis = axis;
+ this.ellipseFactor = ellipseFactor;
+ }
+ }
+
+ /**
+ * Frame listener that animates all orbiting lights each frame.
+ * Updates light positions based on their individual orbital parameters.
+ */
+ private static class MultiLightAnimator implements eu.svjatoslav.sixth.e3d.gui.FrameListener {
+ private final List<OrbitingLight> lights;
+
+ /**
+ * Creates an animator for the specified lights.
+ * @param lights the list of lights to animate
+ */
+ MultiLightAnimator(List<OrbitingLight> lights) {
+ this.lights = lights;
+ }
+
+ /**
+ * Updates all light positions each frame.
+ * @param viewPanel the view panel
+ * @param millisecondsSinceLastFrame time elapsed since last frame
+ * @return true to continue animation
+ */
+ @Override
+ public boolean onFrame(ViewPanel viewPanel, int millisecondsSinceLastFrame) {
+ for (OrbitingLight orbitingLight : lights) {
+ orbitingLight.angle += orbitingLight.speed * millisecondsSinceLastFrame / 100;
+
+ double r = orbitingLight.orbitRadius;
+ double e = orbitingLight.ellipseFactor;
+
+ double x, y, z;
+ switch (orbitingLight.axis) {
+ case 0:
+ x = r * Math.cos(orbitingLight.angle);
+ y = r * e * Math.sin(orbitingLight.angle);
+ z = r * 0.5 * Math.sin(orbitingLight.angle * 2);
+ break;
+ case 1:
+ x = r * e * Math.sin(orbitingLight.angle * 2);
+ y = r * Math.cos(orbitingLight.angle);
+ z = r * 0.5 * Math.sin(orbitingLight.angle);
+ break;
+ default:
+ x = r * 0.5 * Math.sin(orbitingLight.angle);
+ y = r * Math.sin(orbitingLight.angle * 2);
+ z = r * e * Math.cos(orbitingLight.angle);
+ break;
+ }
+
+ Point3D newPosition = new Point3D(x, y + 50, z);
+ orbitingLight.light.setPosition(newPosition);
+ orbitingLight.marker.setTransform(new eu.svjatoslav.sixth.e3d.math.Transform(newPosition, 0, 0));
+ }
+ return true;
+ }
+ }
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point2D;
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.geometry.Rectangle;
+import eu.svjatoslav.sixth.e3d.gui.Camera;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.gui.textEditorComponent.LookAndFeel;
+import eu.svjatoslav.sixth.e3d.gui.textEditorComponent.TextEditComponent;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid2D;
+
+/**
+ * Demo showing a grid of 3D text editor components.
+ * Creates a 5x5 grid of text editors floating in 3D space with a decorative grid
+ * below them. This demonstrates the basic text editing capabilities of the Sixth 3D engine.
+ */
+public class TextEditorDemo {
+
+ /**
+ * Entry point for the text editor demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+
+ final ViewFrame viewFrame = new ViewFrame();
+ final ViewPanel viewPanel = viewFrame.getViewPanel();
+
+ final ShapeCollection shapeCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ setCameraLocation(viewPanel);
+
+ addGrid(shapeCollection);
+
+ addTextEditors(viewPanel, shapeCollection);
+ }
+
+ /**
+ * Adds a decorative grid below the text editors.
+ * @param shapeCollection the collection to add the grid to
+ */
+ private static void addGrid(ShapeCollection shapeCollection) {
+ final Transform transform = new Transform(new Point3D(0, 100, 0), 0,
+ Math.PI / 2);
+
+ final Rectangle rectangle = new Rectangle(2000);
+ final LineAppearance appearance = new LineAppearance(10, new Color(
+ "00b3ad"));
+
+ shapeCollection.addShape(new Grid2D(transform, rectangle, 10, 10, appearance));
+ }
+
+ /**
+ * Creates a grid of text editor components arranged in 3D space.
+ * @param viewPanel the view panel for the text editors
+ * @param shapeCollection the collection to add editors to
+ */
+ private static void addTextEditors(ViewPanel viewPanel, ShapeCollection shapeCollection) {
+ final double m = 1.5;
+ for (double z = -500 * m; z <= (500 * m); z += 250 * m)
+ for (double x = -500 * m; x <= (500 * m); x += 250 * m) {
+
+ final TextEditComponent textEditor = new TextEditComponent(
+ new Transform(new Point3D(x, 0, z)), viewPanel,
+ new Point2D(200, 120), new LookAndFeel());
+
+ shapeCollection.addShape(textEditor);
+ }
+ }
+
+ /**
+ * Sets the camera to an initial viewing position.
+ * @param viewPanel the view panel whose camera to configure
+ */
+ private static void setCameraLocation(ViewPanel viewPanel) {
+ Camera camera = viewPanel.getCamera();
+ camera.getTransform().setTranslation(new Point3D(500, -300, -800));
+ camera.getTransform().setRotation(0.6, -0.5);
+ }
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point2D;
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.geometry.Rectangle;
+import eu.svjatoslav.sixth.e3d.gui.Camera;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.gui.textEditorComponent.LookAndFeel;
+import eu.svjatoslav.sixth.e3d.gui.textEditorComponent.TextEditComponent;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid2D;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URISyntaxException;
+import java.util.stream.Collectors;
+
+/**
+ * "Text Editor City" demo showing a 3D city of text editor components.
+ * Creates a grid of buildings where each building has four text editor panels
+ * facing different directions. This demonstrates the 3D text editing capabilities
+ * of the Sixth 3D engine in a large-scale scene.
+ */
+public class TextEditorDemo2 {
+
+ /**
+ * Entry point for the text editor city demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+ try {
+ new TextEditorDemo2().build();
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Builds and displays the 3D city scene with text editors.
+ * @throws URISyntaxException if resource URI is malformed
+ * @throws IOException if demo text file cannot be read
+ */
+ public void build() throws URISyntaxException, IOException {
+ final ViewFrame viewFrame = new ViewFrame();
+ final ViewPanel viewPanel = viewFrame.getViewPanel();
+
+ final ShapeCollection shapeCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ setCameraLocation(viewPanel);
+
+ addGrid(shapeCollection);
+
+ addCity(viewPanel, shapeCollection);
+ }
+
+ /**
+ * Creates a grid of buildings in the city.
+ * @param viewPanel the view panel for the text editors
+ * @param shapeCollection the collection to add buildings to
+ * @throws URISyntaxException if resource URI is malformed
+ * @throws IOException if demo text file cannot be read
+ */
+ private void addCity(ViewPanel viewPanel, ShapeCollection shapeCollection) throws URISyntaxException, IOException {
+ int citySize = 4000;
+ for (int z = -citySize; z< citySize; z+= 1000 ){
+ for (int x = -citySize; x< citySize; x+= 1000 ){
+ addBuilding(viewPanel, shapeCollection, x, z);
+ }
+ }
+ }
+
+
+ /**
+ * Adds a grid to the scene for visual reference.
+ * @param shapeCollection the collection to add the grid to
+ */
+ private static void addGrid(ShapeCollection shapeCollection) {
+ final Transform transform = new Transform(new Point3D(0, 100, 0), 0,
+ Math.PI / 2);
+
+ final Rectangle rectangle = new Rectangle(10000);
+ final LineAppearance appearance = new LineAppearance(10, new Color(
+ "00b3ad"));
+
+ shapeCollection.addShape(new Grid2D(transform, rectangle, 50, 50, appearance));
+ }
+
+
+ /**
+ * Adds a single building with four text editor panels facing different directions.
+ * @param viewPanel the view panel for the text editors
+ * @param shapeCollection the collection to add the building to
+ * @param x the X coordinate of the building center
+ * @param z the Z coordinate of the building center
+ * @throws URISyntaxException if resource URI is malformed
+ * @throws IOException if demo text file cannot be read
+ */
+ private void addBuilding(ViewPanel viewPanel, ShapeCollection shapeCollection, double x, double z) throws URISyntaxException, IOException {
+ Transform transform = new Transform(new Point3D(x, -390, z-200));
+ addTextEditor(viewPanel, shapeCollection, transform);
+
+ transform = new Transform(new Point3D(x, -390, z+200),Math.PI, 0);
+ addTextEditor(viewPanel, shapeCollection, transform);
+
+ transform = new Transform(new Point3D(x-200, -390, z),Math.PI/2, 0);
+ addTextEditor(viewPanel, shapeCollection, transform);
+
+ transform = new Transform(new Point3D(x+200, -390, z),Math.PI/2*3f, 0);
+ addTextEditor(viewPanel, shapeCollection, transform);
+ }
+
+ /**
+ * Adds a single text editor component at the specified transform.
+ * @param viewPanel the view panel for the text editor
+ * @param shapeCollection the collection to add the editor to
+ * @param transform the position and orientation of the editor
+ * @throws IOException if demo text file cannot be read
+ */
+ private void addTextEditor(ViewPanel viewPanel, ShapeCollection shapeCollection, Transform transform) throws IOException {
+ LookAndFeel lookAndFeel = getLookAndFeel();
+
+ final TextEditComponent textEditor = new TextEditComponent(
+ transform,
+ viewPanel,
+ new Point2D(400, 1000),
+ lookAndFeel
+ );
+
+ String text = getResourceFileAsString("demo.txt");
+
+ textEditor.setText(text);
+ textEditor.goToLine((int)(Math.random()*200f));
+ shapeCollection.addShape(textEditor);
+ }
+
+ /**
+ * Creates the look and feel for text editors with a dark theme.
+ * @return a LookAndFeel configured with dark blue background and light text
+ */
+ private LookAndFeel getLookAndFeel() {
+ LookAndFeel lookAndFeel = new LookAndFeel();
+ lookAndFeel.background = new Color(20, 20, 50, 150);
+ lookAndFeel.tabStopBackground = lookAndFeel.background;
+ lookAndFeel.foreground = new Color(150, 150, 255,250);
+ return lookAndFeel;
+ }
+
+ /**
+ * Reads a resource file as a string.
+ * @param fileName the name of the resource file
+ * @return the file contents as a string, or null if not found
+ * @throws IOException if an I/O error occurs
+ */
+ static String getResourceFileAsString(String fileName) throws IOException {
+ ClassLoader classLoader = ClassLoader.getSystemClassLoader();
+ try (InputStream is = classLoader.getResourceAsStream(fileName)) {
+ if (is == null) return null;
+ try (InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader reader = new BufferedReader(isr)) {
+ return reader.lines().collect(Collectors.joining(System.lineSeparator()));
+ }
+ }
+ }
+
+ /**
+ * Sets the camera to an initial viewing position for the city scene.
+ * @param viewPanel the view panel whose camera to configure
+ */
+ private static void setCameraLocation(ViewPanel viewPanel) {
+ Camera camera = viewPanel.getCamera();
+ camera.getTransform().setTranslation(new Point3D(500, -300, -800));
+ camera.getTransform().setRotation(0.6, -0.5);
+ }
+}
--- /dev/null
+/*
+ * Sixth 3D engine. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
+package eu.svjatoslav.sixth.e3d.examples.galaxy_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.GlowingPoint;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static java.lang.Math.*;
+
+/**
+ * Represents a spiral galaxy composed of glowing points.
+ * Uses a mathematical spiral distribution to create a realistic galaxy shape
+ * with multiple spiral arms. Points are colored from a limited palette to
+ * enable texture reuse optimization.
+ */
+public class Galaxy extends AbstractCompositeShape {
+
+ /**
+ * The number of unique colors used in the galaxy.
+ * Used to reuse textures of glowing points of the same color.
+ */
+ public static final int UNIQUE_COLORS_COUNT = 30;
+
+ /**
+ * A list of all colors used in the galaxy.
+ * Used to reuse textures of glowing points of the same color.
+ */
+ private static List<Color> colors;
+
+ /**
+ * Constructs a galaxy with the specified parameters.
+ * @param galaxySize the overall size scale of the galaxy
+ * @param tailCount the number of spiral arms
+ * @param starsCount the total number of stars to generate
+ * @param transform the position and orientation of the galaxy
+ */
+ public Galaxy(final int galaxySize, final int tailCount, final int starsCount,
+ Transform transform) {
+
+ super(transform);
+
+ ensureColorsAreInitialized();
+
+ final double angle1 = random() * 10;
+ final double angle2 = random() * 10;
+
+ final double angleSin1 = sin(angle1);
+ final double angleCos1 = cos(angle1);
+ final double angleSin2 = sin(angle2);
+ final double angleCos2 = cos(angle2);
+
+ Random random = new Random();
+
+ double starSize = galaxySize / 70d;
+
+ for (int i = 1; i < starsCount; i++) {
+ final double b = random() * 10;
+
+ final double s = (b * b) / 30;
+
+ final double v1 = (random() * (11.5 - b)) / 3;
+ final double v1p = v1 / 2;
+
+ final double ane = ((random() * (s / 2)) / tailCount) * 2;
+ final double sba = ((2 * PI) / tailCount)
+ * random.nextInt(tailCount);
+
+ final double x = (((sin((b - sba) + ane) * s) + (random() * v1)) - v1p) * galaxySize;
+ final double z = (((cos((b - sba) + ane) * s) + (random() * v1)) - v1p) * galaxySize;
+ final double y = ((random() * v1) - v1p) * galaxySize;
+
+ final double x1 = (x * angleCos1) + (z * angleSin1);
+ final double z1 = (z * angleCos1) - (x * angleSin1);
+
+ final double y1 = (y * angleCos2) + (z1 * angleSin2);
+ final double z2 = (z1 * angleCos2) - (y * angleSin2);
+
+ addStar(new Point3D(x1, y1, z2), starSize);
+ }
+ }
+
+ /**
+ * Adds a single star at the specified location.
+ * @param starLocation the position of the star
+ * @param size the visual size of the star
+ */
+ private void addStar(final Point3D starLocation, double size) {
+ addShape(new GlowingPoint(starLocation, size, colors.get((int) (random() * colors.size()))));
+ }
+
+ /**
+ * Initializes the shared color palette for all galaxies.
+ * Creates a limited set of random colors to enable texture reuse.
+ */
+ private synchronized void ensureColorsAreInitialized() {
+ if (colors != null) return;
+
+ colors = new ArrayList<>();
+
+ for (int i = 0; i < UNIQUE_COLORS_COUNT; i++)
+ colors.add(
+ new Color(
+ random() + 0.5,
+ random() + 0.5,
+ random() + 0.5,
+ 255));
+ }
+
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples.galaxy_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+
+/**
+ * Demo showing a point cloud galaxy simulation.
+ * Creates a spiral galaxy with 10,000 glowing points using the Galaxy class.
+ */
+public class PointCloudDemo {
+
+ /**
+ * Entry point for the point cloud demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+
+ final ViewFrame viewFrame = new ViewFrame();
+
+ final ShapeCollection geometryCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ Transform transform = new Transform(new Point3D(0, -1000, 1000), 0, 0);
+
+ // add galaxy
+ geometryCollection.addShape(new Galaxy(500, 3, 10000, transform));
+
+ }
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples.launcher;
+
+import eu.svjatoslav.sixth.e3d.examples.*;
+import eu.svjatoslav.sixth.e3d.examples.galaxy_demo.PointCloudDemo;
+import eu.svjatoslav.sixth.e3d.examples.ShadedShapesDemo;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+
+/**
+ * Panel containing buttons to launch each demo application.
+ * Displays a vertical list of buttons organized in a sequential group layout.
+ */
+class ApplicationListPanel extends JPanel {
+ private static final long serialVersionUID = 2012721856427052560L;
+
+ /** Constructs the panel with all demo launcher buttons. */
+ ApplicationListPanel() {
+ final GroupLayout groupLayout = new GroupLayout(this);
+ GroupLayout.SequentialGroup sequentialGroup = groupLayout.createSequentialGroup();
+ sequentialGroup.addComponent(new JLabel("Choose an example to launch:"));
+ sequentialGroup.addComponent(new JButton(new ShowOctree()));
+ sequentialGroup.addComponent(new JButton(new ShowMathGraphs()));
+ sequentialGroup.addComponent(new JButton(new ShowPointCloud()));
+ sequentialGroup.addComponent(new JButton(new ShowRain()));
+ sequentialGroup.addComponent(new JButton(new ShowTextEditors()));
+ sequentialGroup.addComponent(new JButton(new ShowTextEditors2()));
+ sequentialGroup.addComponent(new JButton(new ShowGameOfLife()));
+ sequentialGroup.addComponent(new JButton(new ShowRandomPolygons()));
+ sequentialGroup.addComponent(new JButton(new ShowShadedShapes()));
+ sequentialGroup.addComponent(new JButton(new ShowFillRateTest()));
+ }
+
+ /** Action to launch the TextEditorDemo. */
+ private static class ShowTextEditors extends AbstractAction {
+ ShowTextEditors() {
+ putValue(NAME, "Text editors");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ TextEditorDemo.main(null);
+ }
+ }
+
+ /** Action to launch the TextEditorDemo2 (city view). */
+ private static class ShowTextEditors2 extends AbstractAction {
+ ShowTextEditors2() {
+ putValue(NAME, "Text editors city");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ TextEditorDemo2.main(null);
+ }
+ }
+
+
+ /** Action to launch the RainingNumbersDemo. */
+ private static class ShowRain extends AbstractAction {
+ ShowRain() {
+ putValue(NAME, "Raining numbers");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ RainingNumbersDemo.main(null);
+ }
+ }
+
+ /** Action to launch the PointCloudDemo (galaxy simulation). */
+ private static class ShowPointCloud extends AbstractAction {
+ ShowPointCloud() {
+ putValue(NAME, "Point cloud galaxy");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ PointCloudDemo.main(null);
+ }
+ }
+
+ /** Action to launch the GraphDemo (mathematical graphs). */
+ private static class ShowMathGraphs extends AbstractAction {
+ ShowMathGraphs() {
+ putValue(NAME, "Mathematical graphs");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ GraphDemo.main(null);
+ }
+ }
+
+ /** Action to launch the RandomPolygonsDemo. */
+ private static class ShowRandomPolygons extends AbstractAction {
+ ShowRandomPolygons() {
+ putValue(NAME, "Random polygons");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ RandomPolygonsDemo.main(null);
+ }
+ }
+
+ /** Action to launch the OctreeDemo (volumetric rendering). */
+ private static class ShowOctree extends AbstractAction {
+ ShowOctree() {
+ putValue(NAME, "Volumetric Octree");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ OctreeDemo.main(null);
+ }
+ }
+
+ /** Action to launch the Game of Life 3D demo. */
+ private static class ShowGameOfLife extends AbstractAction {
+ ShowGameOfLife() {
+ putValue(NAME, "Game of Life");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ eu.svjatoslav.sixth.e3d.examples.life_demo.Main.main(null);
+ }
+ }
+
+ /** Action to launch the ShadedShapesDemo (lighting demonstration). */
+ private static class ShowShadedShapes extends AbstractAction {
+ ShowShadedShapes() {
+ putValue(NAME, "Shaded Shapes with Lights");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ ShadedShapesDemo.main(null);
+ }
+ }
+
+ /** Action to launch the FillRateTest benchmark. */
+ private static class ShowFillRateTest extends AbstractAction {
+ ShowFillRateTest() {
+ putValue(NAME, "Fill-rate Test");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ FillRateTest.main(null);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples.launcher;
+
+import javax.swing.*;
+import java.awt.*;
+
+import static java.awt.BorderLayout.CENTER;
+import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
+
+
+/**
+ * Launcher application for all Sixth 3D demos.
+ * Displays a window with buttons to launch each demo application.
+ */
+class Main {
+
+ /**
+ * Entry point for the demo launcher.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+ buildAndShowGuiWindow();
+ }
+
+ /**
+ * Builds and shows the main window of the application.
+ */
+ private static void buildAndShowGuiWindow() {
+ JFrame frame = new JFrame("Sixth 3D engine demos");
+
+ // Keep application running until last frame is closed.
+ frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+
+ frame.getContentPane().setLayout(new BorderLayout());
+ frame.getContentPane().add(new ApplicationListPanel(), CENTER);
+ frame.setSize(400, 300);
+
+ frame.setLocationRelativeTo(null); // center frame on screen
+ frame.setVisible(true);
+ }
+
+}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples.life_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseInteractionController;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
+
+/**
+ * Represents a single cell in Conway's Game of Life matrix.
+ * Each cell can be active (alive) or inactive (dead), and responds to mouse
+ * interactions for toggling its state. The cell changes color based on its
+ * state and whether the mouse is hovering over it.
+ */
+class Cell extends AbstractCompositeShape implements
+ MouseInteractionController {
+
+ /** Visual size of each cell in world units. */
+ static final int SIZE = 20;
+ /**
+ * Color of the active cell (R, G, B, A)
+ */
+ private static final Color ACTIVE_COLOR = new Color("A8FF");
+ /**
+ * Color of the active cell (R, G, B, A) while mouse is over it.
+ */
+ private static final Color ACTIVE_COLOR_MOUSE_OVER = new Color("F9FF");
+ /**
+ * Color of the inactive cell (R, G, B, A)
+ */
+ private static final Color INACTIVE_COLOR = new Color("55F8");
+ /**
+ * Color of the inactive cell (R, G, B, A) while mouse is over it.
+ */
+ private static final Color INACTIVE_COLOR_MOUSE_OVER = new Color("77F8");
+ /**
+ * A placeholder variable to help in next generation computation. Indicates
+ * whether cell is going to survive within next generation.
+ */
+ public boolean survives;
+ /**
+ * Indicates whether cell is currently active
+ */
+ private boolean active;
+ /**
+ * Indicates whether mouse pointer is currently over this cell.
+ */
+ private boolean isMouseOver = false;
+
+ /**
+ * Constructs a cell at the specified center position.
+ * @param center the 3D position of the cell center
+ */
+ public Cell(final Point3D center) {
+ super(center);
+
+ createCellShape();
+
+ // enable receiving of mouse events
+ setMouseInteractionController(this);
+ }
+
+ /** Creates the visual representation of the cell as two triangles. */
+ private void createCellShape() {
+ final double halfSize = SIZE / 2f;
+
+ // define 4 points corresponding to cell borders
+ final Point3D p1 = new Point3D(-halfSize, 0, -halfSize);
+
+ final Point3D p2 = new Point3D(+halfSize, 0, -halfSize);
+
+ final Point3D p3 = new Point3D(+halfSize, 0, +halfSize);
+
+ final Point3D p4 = new Point3D(-halfSize, 0, +halfSize);
+
+ // connect 4 points with 2 polygons
+ addShape(new SolidPolygon(p1, p2, p3, computeCellColor()));
+ addShape(new SolidPolygon(p1, p4, p3, computeCellColor()));
+ }
+
+ /**
+ * Computes the cell color based on active state and mouse hover.
+ * @return the appropriate color for the current state
+ */
+ private Color computeCellColor() {
+ if (active)
+ if (isMouseOver)
+ return ACTIVE_COLOR_MOUSE_OVER;
+ else
+ return ACTIVE_COLOR;
+ else if (isMouseOver)
+ return INACTIVE_COLOR_MOUSE_OVER;
+ else
+ return INACTIVE_COLOR;
+ }
+
+ /**
+ * Returns whether this cell is currently active (alive).
+ * @return true if the cell is active
+ */
+ public boolean isActive() {
+ return active;
+ }
+
+ /**
+ * Sets the active state of this cell and updates its color.
+ * @param active true to make the cell active, false for inactive
+ */
+ public void setActive(final boolean active) {
+ this.active = active;
+ updateColor();
+ }
+
+ /**
+ * Handles mouse click by toggling the cell state.
+ * @param button the mouse button that was clicked
+ * @return true to indicate the event was consumed
+ */
+ @Override
+ public boolean mouseClicked(int button) {
+ setActive(!isActive());
+ return true;
+ }
+
+ /**
+ * Handles mouse entering the cell area by highlighting it.
+ * @return true to indicate the event was consumed
+ */
+ @Override
+ public boolean mouseEntered() {
+ setMouseOver(true);
+ return true;
+ }
+
+ /**
+ * Handles mouse exiting the cell area by removing highlight.
+ * @return true to indicate the event was consumed
+ */
+ @Override
+ public boolean mouseExited() {
+ setMouseOver(false);
+ return true;
+ }
+
+ /**
+ * Sets the mouse-over state and updates the cell color.
+ * @param isMouseOver true if mouse is over the cell
+ */
+ private void setMouseOver(final boolean isMouseOver) {
+ this.isMouseOver = isMouseOver;
+ updateColor();
+ }
+
+ /** Updates the cell's visual color to match its current state. */
+ private void updateColor() {
+ setColor(computeCellColor());
+ }
+
+}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples.life_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.geometry.Rectangle;
+import eu.svjatoslav.sixth.e3d.gui.Camera;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationUserInputTracker;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid2D;
+
+import java.awt.event.KeyEvent;
+
+
+/**
+ * Main entry point for Conway's Game of Life 3D demo.
+ * Creates a 30x30 cell matrix where cells evolve based on Conway's rules.
+ * The user can interact with cells by clicking to toggle their state.
+ *
+ * <p>Key controls:
+ * <ul>
+ * <li>Space - Evolve one generation</li>
+ * <li>Enter - Evolve with history (leaves stars marking previous positions)</li>
+ * <li>C - Clear the matrix</li>
+ * </ul>
+ */
+public class Main extends WorldNavigationUserInputTracker {
+
+ /** The game of life matrix, centered at the origin. */
+ private static final Matrix MATRIX = new Matrix(
+ new Point3D() // position matrix in the center of the scene
+ );
+
+ /**
+ * Entry point for the Game of Life demo.
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+ new Main().run();
+ }
+
+ /**
+ * Handle keyboard input.
+ */
+ @Override
+ public boolean keyPressed(final KeyEvent event, final ViewPanel viewPanel) {
+ switch (event.getKeyChar()) {
+ case ' ': // space key
+ MATRIX.evolve(false);
+ break;
+ case 10: // ENTER
+ MATRIX.evolve(true);
+ break;
+ case 'c': // reset matrix
+ MATRIX.clear();
+ break;
+ default:
+ return super.keyPressed(event, viewPanel);
+ }
+ return true;
+ }
+
+ /** Initializes and displays the Game of Life demo. */
+ private void run() {
+
+ // create application frame visible to the user
+ final ViewFrame viewFrame = new ViewFrame();
+
+ final ShapeCollection shapeCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ // add matrix
+ shapeCollection.addShape(MATRIX);
+
+ // add wire-frame grid (optional)
+ shapeCollection.addShape(createGrid());
+
+ final ViewPanel viewPanel = viewFrame.getViewPanel();
+
+ setCameraOrientation(viewPanel.getCamera());
+
+ // enable receiving of keyboard events
+ viewPanel.getKeyboardFocusStack().pushFocusOwner(this);
+
+ // Done! World is built. So ensure screen is updated too.
+ viewPanel.repaintDuringNextViewUpdate();
+ }
+
+ /**
+ * Creates a pink wire-frame grid below the matrix for decorative purposes.
+ * @return a Grid2D positioned below the game matrix
+ */
+ private Grid2D createGrid() {
+ return new Grid2D(
+ new Transform(
+ new Point3D( // Grid positioning:
+ 0, // center
+ 100, // below the main scene
+ 0), // center
+
+ // Grid orientation:
+ 0, // no rotation along XZ axis
+ Math.PI / 2), // face down
+
+ new Rectangle(800), // large enough, square grid
+
+ 5, 5, // grid will be divided to 5x5 segments
+
+ new LineAppearance(3, // line thickness
+ new Color("FF000050") // red and quite transparent
+ )
+ );
+ }
+
+ /**
+ * Sets the camera to an initial viewing position for the matrix.
+ * @param camera the camera to configure
+ */
+ private void setCameraOrientation(final Camera camera) {
+ camera.getTransform().setTranslation(new Point3D(100, -50, -200));
+ camera.getTransform().setRotation(0.2f, -0.7f);
+ }
+
+}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples.life_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.SubShape;
+
+/**
+ * Represents the 2D game board for Conway's Game of Life.
+ * Contains a 30x30 grid of cells that can evolve according to Conway's rules.
+ * Supports optional history tracking where stars mark previously active cells.
+ *
+ * @see Cell
+ * @see Star
+ */
+class Matrix extends AbstractCompositeShape {
+
+ /** Empty space between adjacent cells. */
+ private static final int BORDER = 5;
+
+ /** Number of cells along each dimension (30x30 grid). */
+ private static final int SIZE = 30;
+
+ /** Group ID for history tracking stars. */
+ private static final String GROUP_STARS = "stars";
+
+ /** Group ID for the cell surface. */
+ private static final String GROUP_SURFACE = "surface";
+
+ /** 2D array of cells forming the game board. */
+ private final Cell[][] cells = new Cell[SIZE][];
+
+ /**
+ * Constructs a game matrix at the specified location.
+ * @param location the center position of the matrix in 3D space
+ */
+ public Matrix(final Point3D location) {
+ super(location);
+
+
+ for (int x = 0; x < SIZE; x++) {
+ cells[x] = new Cell[SIZE];
+
+ // init Y row
+ for (int z = 0; z < SIZE; z++) {
+ // create cell and register it
+ final Cell cell = new Cell(getCellLocation(x, z));
+ cells[x][z] = cell;
+ addShape(cell);
+ }
+ }
+
+ setGroupForUngrouped(GROUP_SURFACE);
+ }
+
+ /**
+ * Clears all cells to inactive state and removes history stars.
+ */
+ public void clear() {
+
+ // mark every cell as inactive
+ for (int x = 0; x < SIZE; x++)
+ for (int y = 0; y < SIZE; y++)
+ cells[x][y].setActive(false);
+
+ // remove history stars
+ removeGroup(GROUP_STARS);
+ }
+
+ /**
+ * Computes the next generation using Conway's Game of Life rules.
+ * Each cell's survival is determined by its number of alive neighbors.
+ */
+ private void computeSurvivedCells() {
+
+ for (int y = 0; y < SIZE; y++)
+ for (int x = 0; x < SIZE; x++)
+ processCell(x, y);
+
+ for (int y = 0; y < SIZE; y++)
+ for (int x = 0; x < SIZE; x++)
+ cells[x][y].setActive(cells[x][y].survives);
+
+ }
+
+ /**
+ * Processes a single cell to determine if it survives to the next generation.
+ * @param x the X coordinate of the cell
+ * @param y the Y coordinate of the cell
+ */
+ private void processCell(int x, int y) {
+ int aliveNeighbours = countNeighbours(x, y);
+
+ if (cells[x][y].isActive()) {
+ cells[x][y].survives = ((aliveNeighbours == 2) || (aliveNeighbours == 3));
+ } else {
+ cells[x][y].survives = aliveNeighbours == 3;
+ }
+ }
+
+ /**
+ * Counts the number of alive neighbors around the specified cell.
+ * @param x the X coordinate of the cell
+ * @param y the Y coordinate of the cell
+ * @return the count of alive neighboring cells
+ */
+ private int countNeighbours(int x, int y) {
+ int result = 0;
+ for (int ny = y - 1; ny <= y + 1; ny++)
+ for (int nx = x - 1; nx <= x + 1; nx++)
+ if (isCellAlive(nx, ny)) result++;
+
+ if (isCellAlive(x, y)) result--;
+
+ return result;
+ }
+
+ /**
+ * Checks if the cell at the specified coordinates is alive.
+ * @param x the X coordinate of the cell
+ * @param y the Y coordinate of the cell
+ * @return true if the cell is within bounds and active
+ */
+ private boolean isCellAlive(int x, int y) {
+ if (x < 0) return false;
+ if (x >= SIZE) return false;
+ if (y < 0) return false;
+ if (y >= SIZE) return false;
+ return cells[x][y].isActive();
+ }
+
+ /**
+ * Evolves the matrix by one generation.
+ * @param preserveHistory if true, places stars at positions of previously active cells
+ */
+ public void evolve(final boolean preserveHistory) {
+ if (preserveHistory)
+ markActiveCells();
+
+ shiftStarsUp();
+
+ computeSurvivedCells();
+ }
+
+ /**
+ * Computes the world position of a cell given its grid coordinates.
+ * @param x the X grid coordinate
+ * @param z the Z grid coordinate
+ * @return the 3D world position of the cell center
+ */
+ private Point3D getCellLocation(final int x, final int z) {
+ final int shift = -((SIZE / 2) * (Cell.SIZE + BORDER));
+
+ return new Point3D(
+ (x * (Cell.SIZE + BORDER)) + shift,
+ 0,
+ (z * (Cell.SIZE + BORDER)) + shift);
+ }
+
+ /**
+ * Marks all currently active cells with stars for history tracking.
+ * Stars are added to the GROUP_STARS group.
+ */
+ private void markActiveCells() {
+ // mark survived cells
+ for (int x = 0; x < SIZE; x++)
+ for (int y = 0; y < SIZE; y++)
+ if (cells[x][y].isActive())
+ addShape(new Star(getCellLocation(x, y)));
+
+ setGroupForUngrouped(GROUP_STARS);
+ }
+
+ /**
+ * Shifts all history tracking stars upward to create a trailing effect.
+ */
+ private void shiftStarsUp() {
+
+ for (final SubShape subShape : getGroup(GROUP_STARS))
+ ((Star) subShape.getShape()).getLocation().translateY(-10);
+ }
+}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples.life_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.GlowingPoint;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a glowing star marker in the Game of Life history trail.
+ * When cells evolve with history enabled, stars are placed at previous
+ * active cell positions to create a visual trail of the game's evolution.
+ * Uses a limited color palette to enable texture reuse optimization.
+ */
+class Star extends GlowingPoint {
+ /** Visual size of each star. */
+ public static final int STAR_SIZE = 10;
+
+ /** Number of unique star colors for texture reuse optimization. */
+ public static final int UNIQUE_STARS_COUNT = 30;
+
+ /** Shared pool of star colors for texture reuse. */
+ private static final List<Color> uniqueStarColors = new ArrayList<>();
+
+ /*
+ * Initializes a limited set of precomputed star colors.
+ * This optimization allows the Sixth 3D engine to reuse textures
+ * for stars with identical colors, saving memory when many stars are present.
+ */
+ static {
+ for (int i = 0; i < UNIQUE_STARS_COUNT; i++)
+ uniqueStarColors.add(
+ new Color(
+ Math.random() + 0.5,
+ Math.random() + 0.5,
+ Math.random() + 0.5,
+ 255));
+ }
+
+ /**
+ * Constructs a star at the specified location with a random color from the palette.
+ * @param location the 3D position of the star
+ */
+ public Star(Point3D location) {
+ super(location,
+ STAR_SIZE,
+ uniqueStarColors.get((int) (Math.random() * uniqueStarColors.size())) // pick random pre-generated color
+ );
+ }
+
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+/**
+ * Example applications that make use of the API.
+ */
+
+package eu.svjatoslav.sixth.e3d.examples;
+
--- /dev/null
+microcode: microcode updated early to revision 0xe2, date = 2020-07-14
+Linux version 5.10.0-6-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2) #1 SMP Debian 5.10.28-1 (2021-04-09)
+Command line: BOOT_IMAGE=/vmlinuz-5.10.0-6-amd64 root=/dev/mapper/main-root ro quiet
+x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
+x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
+x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
+x86/fpu: Supporting XSAVE feature 0x008: 'MPX bounds registers'
+x86/fpu: Supporting XSAVE feature 0x010: 'MPX CSR'
+x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256
+x86/fpu: xstate_offset[3]: 832, xstate_sizes[3]: 64
+x86/fpu: xstate_offset[4]: 896, xstate_sizes[4]: 64
+x86/fpu: Enabled xstate features 0x1f, context size is 960 bytes, using 'compacted' format.
+BIOS-provided physical RAM map:
+BIOS-e820: [mem 0x0000000000000000-0x000000000009e7ff] usable
+BIOS-e820: [mem 0x000000000009e800-0x000000000009ffff] reserved
+BIOS-e820: [mem 0x00000000000e0000-0x00000000000fffff] reserved
+BIOS-e820: [mem 0x0000000000100000-0x000000005f692fff] usable
+BIOS-e820: [mem 0x000000005f693000-0x000000005f693fff] ACPI NVS
+BIOS-e820: [mem 0x000000005f694000-0x000000005f6ddfff] reserved
+BIOS-e820: [mem 0x000000005f6de000-0x000000005f789fff] usable
+BIOS-e820: [mem 0x000000005f78a000-0x0000000060089fff] reserved
+BIOS-e820: [mem 0x000000006008a000-0x000000007558efff] usable
+BIOS-e820: [mem 0x000000007558f000-0x0000000075f7efff] reserved
+BIOS-e820: [mem 0x0000000075f7f000-0x0000000077f7efff] ACPI NVS
+BIOS-e820: [mem 0x0000000077f7f000-0x0000000077ffefff] ACPI data
+BIOS-e820: [mem 0x0000000077fff000-0x0000000077ffffff] usable
+BIOS-e820: [mem 0x0000000078000000-0x00000000780fffff] reserved
+BIOS-e820: [mem 0x0000000079000000-0x000000007e7fffff] reserved
+BIOS-e820: [mem 0x00000000e0000000-0x00000000efffffff] reserved
+BIOS-e820: [mem 0x00000000fd000000-0x00000000fe7fffff] reserved
+BIOS-e820: [mem 0x00000000feb00000-0x00000000feb03fff] reserved
+BIOS-e820: [mem 0x00000000fec00000-0x00000000fec00fff] reserved
+BIOS-e820: [mem 0x00000000fed00000-0x00000000fed00fff] reserved
+BIOS-e820: [mem 0x00000000fed10000-0x00000000fed19fff] reserved
+BIOS-e820: [mem 0x00000000fed84000-0x00000000fed84fff] reserved
+BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
+BIOS-e820: [mem 0x00000000ffa00000-0x00000000ffffffff] reserved
+BIOS-e820: [mem 0x0000000100000000-0x00000004807fffff] usable
+NX (Execute Disable) protection: active
+SMBIOS 2.8 present.
+DMI: LENOVO 80NV/Allsparks 5A, BIOS CDCN53WW 09/19/2016
+tsc: Detected 2600.000 MHz processor
+tsc: Detected 2599.992 MHz TSC
+e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
+e820: remove [mem 0x000a0000-0x000fffff] usable
+last_pfn = 0x480800 max_arch_pfn = 0x400000000
+MTRR default type: uncachable
+MTRR fixed ranges enabled:
+ 00000-9FFFF write-back
+ A0000-BFFFF uncachable
+ C0000-FFFFF write-protect
+MTRR variable ranges enabled:
+ 0 base 0000000000 mask 7800000000 write-back
+ 1 base 0078000000 mask 7FF8000000 uncachable
+ 2 base 0080000000 mask 7F80000000 uncachable
+ 3 disabled
+ 4 disabled
+ 5 disabled
+ 6 disabled
+ 7 disabled
+ 8 disabled
+ 9 disabled
+x86/PAT: Configuration [0-7]: WB WC UC- UC WB WP UC- WT
+e820: update [mem 0x78000000-0xffffffff] usable ==> reserved
+last_pfn = 0x78000 max_arch_pfn = 0x400000000
+found SMP MP-table at [mem 0x000fe1b0-0x000fe1bf]
+ACPI: Early table checksum verification disabled
+ACPI: RSDP 0x00000000000FE020 000024 (v02 LENOVO)
+ACPI: XSDT 0x0000000077FC0188 0000D4 (v01 LENOVO CB-01 00000001 01000013)
+ACPI: FACP 0x0000000077FEE000 0000F4 (v05 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: DSDT 0x0000000077FCB000 01E97D (v02 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: FACS 0x0000000077F60000 000040
+ACPI: UEFI 0x0000000077FFD000 000236 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: UEFI 0x0000000077FFC000 000042 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: MSDM 0x0000000077FFB000 000055 (v03 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: SSDT 0x0000000077FF5000 005104 (v02 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: DBGP 0x0000000077FF4000 000034 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: DBG2 0x0000000077FF3000 000061 (v00 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: SSDT 0x0000000077FF2000 00077C (v02 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: ASF! 0x0000000077FF1000 0000A5 (v32 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: ASPT 0x0000000077FF0000 000034 (v07 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: BOOT 0x0000000077FEF000 000028 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: HPET 0x0000000077FED000 000038 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: LPIT 0x0000000077FEC000 000094 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: APIC 0x0000000077FEB000 0000BC (v03 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: MCFG 0x0000000077FEA000 00003C (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: SSDT 0x0000000077FCA000 0002D4 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: SSDT 0x0000000077FC9000 00019A (v02 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: SSDT 0x0000000077FC8000 0003F4 (v02 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: SSDT 0x0000000077FC7000 000E58 (v02 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: SSDT 0x0000000077FC2000 004354 (v01 Insyde NVOP 00001000 INTL 20130927)
+ACPI: DMAR 0x0000000077FC1000 0000A8 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: FPDT 0x0000000077FBF000 000044 (v01 LENOVO CB-01 00000001 ACPI 00040000)
+ACPI: Reserving FACP table memory at [mem 0x77fee000-0x77fee0f3]
+ACPI: Reserving DSDT table memory at [mem 0x77fcb000-0x77fe997c]
+ACPI: Reserving FACS table memory at [mem 0x77f60000-0x77f6003f]
+ACPI: Reserving UEFI table memory at [mem 0x77ffd000-0x77ffd235]
+ACPI: Reserving UEFI table memory at [mem 0x77ffc000-0x77ffc041]
+ACPI: Reserving MSDM table memory at [mem 0x77ffb000-0x77ffb054]
+ACPI: Reserving SSDT table memory at [mem 0x77ff5000-0x77ffa103]
+ACPI: Reserving DBGP table memory at [mem 0x77ff4000-0x77ff4033]
+ACPI: Reserving DBG2 table memory at [mem 0x77ff3000-0x77ff3060]
+ACPI: Reserving SSDT table memory at [mem 0x77ff2000-0x77ff277b]
+ACPI: Reserving ASF! table memory at [mem 0x77ff1000-0x77ff10a4]
+ACPI: Reserving ASPT table memory at [mem 0x77ff0000-0x77ff0033]
+ACPI: Reserving BOOT table memory at [mem 0x77fef000-0x77fef027]
+ACPI: Reserving HPET table memory at [mem 0x77fed000-0x77fed037]
+ACPI: Reserving LPIT table memory at [mem 0x77fec000-0x77fec093]
+ACPI: Reserving APIC table memory at [mem 0x77feb000-0x77feb0bb]
+ACPI: Reserving MCFG table memory at [mem 0x77fea000-0x77fea03b]
+ACPI: Reserving SSDT table memory at [mem 0x77fca000-0x77fca2d3]
+ACPI: Reserving SSDT table memory at [mem 0x77fc9000-0x77fc9199]
+ACPI: Reserving SSDT table memory at [mem 0x77fc8000-0x77fc83f3]
+ACPI: Reserving SSDT table memory at [mem 0x77fc7000-0x77fc7e57]
+ACPI: Reserving SSDT table memory at [mem 0x77fc2000-0x77fc6353]
+ACPI: Reserving DMAR table memory at [mem 0x77fc1000-0x77fc10a7]
+ACPI: Reserving FPDT table memory at [mem 0x77fbf000-0x77fbf043]
+Using GB pages for direct mapping
+RAMDISK: [mem 0x2efdd000-0x337e5fff]
+ACPI: Local APIC address 0xfee00000
+No NUMA configuration found
+Faking a node at [mem 0x0000000000000000-0x00000004807fffff]
+NODE_DATA(0) allocated [mem 0x4807d6000-0x4807fffff]
+Zone ranges:
+ DMA [mem 0x0000000000001000-0x0000000000ffffff]
+ DMA32 [mem 0x0000000001000000-0x00000000ffffffff]
+ Normal [mem 0x0000000100000000-0x00000004807fffff]
+ Device empty
+Movable zone start for each node
+Early memory node ranges
+ node 0: [mem 0x0000000000001000-0x000000000009dfff]
+ node 0: [mem 0x0000000000100000-0x000000005f692fff]
+ node 0: [mem 0x000000005f6de000-0x000000005f789fff]
+ node 0: [mem 0x000000006008a000-0x000000007558efff]
+ node 0: [mem 0x0000000077fff000-0x0000000077ffffff]
+ node 0: [mem 0x0000000100000000-0x00000004807fffff]
+Initmem setup node 0 [mem 0x0000000000001000-0x00000004807fffff]
+On node 0 totalpages: 4150242
+ DMA zone: 64 pages used for memmap
+ DMA zone: 21 pages reserved
+ DMA zone: 3997 pages, LIFO batch:0
+ DMA zone: 28771 pages in unavailable ranges
+ DMA32 zone: 7410 pages used for memmap
+ DMA32 zone: 474181 pages, LIFO batch:63
+ DMA32 zone: 13243 pages in unavailable ranges
+ Normal zone: 57376 pages used for memmap
+ Normal zone: 3672064 pages, LIFO batch:63
+ Normal zone: 30720 pages in unavailable ranges
+Reserving Intel graphics memory at [mem 0x7a800000-0x7e7fffff]
+ACPI: PM-Timer IO Port: 0x1808
+ACPI: Local APIC address 0xfee00000
+ACPI: LAPIC_NMI (acpi_id[0x01] high edge lint[0x1])
+ACPI: LAPIC_NMI (acpi_id[0x02] high edge lint[0x1])
+ACPI: LAPIC_NMI (acpi_id[0x03] high edge lint[0x1])
+ACPI: LAPIC_NMI (acpi_id[0x04] high edge lint[0x1])
+ACPI: LAPIC_NMI (acpi_id[0x05] high edge lint[0x1])
+ACPI: LAPIC_NMI (acpi_id[0x06] high edge lint[0x1])
+ACPI: LAPIC_NMI (acpi_id[0x07] high edge lint[0x1])
+ACPI: LAPIC_NMI (acpi_id[0x08] high edge lint[0x1])
+IOAPIC[0]: apic_id 2, version 32, address 0xfec00000, GSI 0-119
+ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
+ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
+ACPI: IRQ0 used by override.
+ACPI: IRQ9 used by override.
+Using ACPI (MADT) for SMP configuration information
+ACPI: HPET id: 0x8086a201 base: 0xfed00000
+TSC deadline timer available
+smpboot: Allowing 8 CPUs, 0 hotplug CPUs
+PM: hibernation: Registered nosave memory: [mem 0x00000000-0x00000fff]
+PM: hibernation: Registered nosave memory: [mem 0x0009e000-0x0009efff]
+PM: hibernation: Registered nosave memory: [mem 0x0009f000-0x0009ffff]
+PM: hibernation: Registered nosave memory: [mem 0x000a0000-0x000dffff]
+PM: hibernation: Registered nosave memory: [mem 0x000e0000-0x000fffff]
+PM: hibernation: Registered nosave memory: [mem 0x5f693000-0x5f693fff]
+PM: hibernation: Registered nosave memory: [mem 0x5f694000-0x5f6ddfff]
+PM: hibernation: Registered nosave memory: [mem 0x5f78a000-0x60089fff]
+PM: hibernation: Registered nosave memory: [mem 0x7558f000-0x75f7efff]
+PM: hibernation: Registered nosave memory: [mem 0x75f7f000-0x77f7efff]
+PM: hibernation: Registered nosave memory: [mem 0x77f7f000-0x77ffefff]
+PM: hibernation: Registered nosave memory: [mem 0x78000000-0x780fffff]
+PM: hibernation: Registered nosave memory: [mem 0x78100000-0x78ffffff]
+PM: hibernation: Registered nosave memory: [mem 0x79000000-0x7e7fffff]
+PM: hibernation: Registered nosave memory: [mem 0x7e800000-0xdfffffff]
+PM: hibernation: Registered nosave memory: [mem 0xe0000000-0xefffffff]
+PM: hibernation: Registered nosave memory: [mem 0xf0000000-0xfcffffff]
+PM: hibernation: Registered nosave memory: [mem 0xfd000000-0xfe7fffff]
+PM: hibernation: Registered nosave memory: [mem 0xfe800000-0xfeafffff]
+PM: hibernation: Registered nosave memory: [mem 0xfeb00000-0xfeb03fff]
+PM: hibernation: Registered nosave memory: [mem 0xfeb04000-0xfebfffff]
+PM: hibernation: Registered nosave memory: [mem 0xfec00000-0xfec00fff]
+PM: hibernation: Registered nosave memory: [mem 0xfec01000-0xfecfffff]
+PM: hibernation: Registered nosave memory: [mem 0xfed00000-0xfed00fff]
+PM: hibernation: Registered nosave memory: [mem 0xfed01000-0xfed0ffff]
+PM: hibernation: Registered nosave memory: [mem 0xfed10000-0xfed19fff]
+PM: hibernation: Registered nosave memory: [mem 0xfed1a000-0xfed83fff]
+PM: hibernation: Registered nosave memory: [mem 0xfed84000-0xfed84fff]
+PM: hibernation: Registered nosave memory: [mem 0xfed85000-0xfedfffff]
+PM: hibernation: Registered nosave memory: [mem 0xfee00000-0xfee00fff]
+PM: hibernation: Registered nosave memory: [mem 0xfee01000-0xff9fffff]
+PM: hibernation: Registered nosave memory: [mem 0xffa00000-0xffffffff]
+[mem 0x7e800000-0xdfffffff] available for PCI devices
+Booting paravirtualized kernel on bare hardware
+clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645519600211568 ns
+setup_percpu: NR_CPUS:8192 nr_cpumask_bits:8 nr_cpu_ids:8 nr_node_ids:1
+percpu: Embedded 54 pages/cpu s183960 r8192 d29032 u262144
+pcpu-alloc: s183960 r8192 d29032 u262144 alloc=1*2097152
+pcpu-alloc: [0] 0 1 2 3 4 5 6 7
+Built 1 zonelists, mobility grouping on. Total pages: 4085371
+Policy zone: Normal
+Kernel command line: BOOT_IMAGE=/vmlinuz-5.10.0-6-amd64 root=/dev/mapper/main-root ro quiet
+Dentry cache hash table entries: 2097152 (order: 12, 16777216 bytes, linear)
+Inode-cache hash table entries: 1048576 (order: 11, 8388608 bytes, linear)
+mem auto-init: stack:off, heap alloc:on, heap free:off
+Memory: 1904140K/16600968K available (12295K kernel code, 2544K rwdata, 7548K rodata, 2388K init, 3712K bss, 463332K reserved, 0K cma-reserved)
+random: get_random_u64 called from __kmem_cache_create+0x2e/0x550 with crng_init=0
+SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1
+Kernel/User page tables isolation: enabled
+ftrace: allocating 36387 entries in 143 pages
+ftrace: allocated 143 pages with 5 groups
+rcu: Hierarchical RCU implementation.
+rcu: RCU restricting CPUs from NR_CPUS=8192 to nr_cpu_ids=8.
+ Rude variant of Tasks RCU enabled.
+ Tracing variant of Tasks RCU enabled.
+rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
+rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=8
+NR_IRQS: 524544, nr_irqs: 2048, preallocated irqs: 16
+random: crng done (trusting CPU's manufacturer)
+Console: colour VGA+ 80x25
+printk: console [tty0] enabled
+ACPI: Core revision 20200925
+clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 79635855245 ns
+APIC: Switch to symmetric I/O mode setup
+DMAR: Host address width 39
+DMAR: DRHD base: 0x000000fed90000 flags: 0x0
+DMAR: dmar0: reg_base_addr fed90000 ver 1:0 cap 1c0000c40660462 ecap 7e3ff0501e
+DMAR: DRHD base: 0x000000fed91000 flags: 0x1
+DMAR: dmar1: reg_base_addr fed91000 ver 1:0 cap d2008c40660462 ecap f050da
+DMAR: RMRR base: 0x00000075e5a000 end: 0x00000075e79fff
+DMAR: RMRR base: 0x0000007a000000 end: 0x0000007e7fffff
+DMAR-IR: IOAPIC id 2 under DRHD base 0xfed91000 IOMMU 1
+DMAR-IR: HPET id 0 under DRHD base 0xfed91000
+DMAR-IR: x2apic is disabled because BIOS sets x2apic opt out bit.
+DMAR-IR: Use 'intremap=no_x2apic_optout' to override the BIOS setting.
+DMAR-IR: Enabled IRQ remapping in xapic mode
+x2apic: IRQ remapping doesn't support X2APIC mode
+..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
+clocksource: tsc-early: mask: 0xffffffffffffffff max_cycles: 0x257a34a6eea, max_idle_ns: 440795264358 ns
+Calibrating delay loop (skipped), value calculated using timer frequency.. 5199.98 BogoMIPS (lpj=10399968)
+pid_max: default: 32768 minimum: 301
+LSM: Security Framework initializing
+Yama: disabled by default; enable with sysctl kernel.yama.*
+AppArmor: AppArmor initialized
+TOMOYO Linux initialized
+Mount-cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
+Mountpoint-cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
+mce: CPU0: Thermal monitoring enabled (TM1)
+process: using mwait in idle threads
+Last level iTLB entries: 4KB 64, 2MB 8, 4MB 8
+Last level dTLB entries: 4KB 64, 2MB 0, 4MB 0, 1GB 4
+Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization
+Spectre V2 : Mitigation: Full generic retpoline
+Spectre V2 : Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch
+Spectre V2 : Enabling Restricted Speculation for firmware calls
+Spectre V2 : mitigation: Enabling conditional Indirect Branch Prediction Barrier
+Spectre V2 : User space: Mitigation: STIBP via seccomp and prctl
+Speculative Store Bypass: Mitigation: Speculative Store Bypass disabled via prctl and seccomp
+TAA: Mitigation: Clear CPU buffers
+SRBDS: Mitigation: Microcode
+MDS: Mitigation: Clear CPU buffers
+Freeing SMP alternatives memory: 32K
+smpboot: CPU0: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz (family: 0x6, model: 0x5e, stepping: 0x3)
+Performance Events: PEBS fmt3+, Skylake events, 32-deep LBR, full-width counters, Intel PMU driver.
+... version: 4
+... bit width: 48
+... generic registers: 4
+... value mask: 0000ffffffffffff
+... max period: 00007fffffffffff
+... fixed-purpose events: 3
+... event mask: 000000070000000f
+rcu: Hierarchical SRCU implementation.
+NMI watchdog: Enabled. Permanently consumes one hw-PMU counter.
+smp: Bringing up secondary CPUs ...
+x86: Booting SMP configuration:
+.... node #0, CPUs: #1 #2 #3 #4
+MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.
+TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.
+ #5 #6 #7
+smp: Brought up 1 node, 8 CPUs
+smpboot: Max logical packages: 1
+smpboot: Total of 8 processors activated (41599.87 BogoMIPS)
+node 0 deferred pages initialised in 16ms
+devtmpfs: initialized
+x86/mm: Memory block size: 128MB
+PM: Registering ACPI NVS region [mem 0x5f693000-0x5f693fff] (4096 bytes)
+PM: Registering ACPI NVS region [mem 0x75f7f000-0x77f7efff] (33554432 bytes)
+clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
+futex hash table entries: 2048 (order: 5, 131072 bytes, linear)
+pinctrl core: initialized pinctrl subsystem
+NET: Registered protocol family 16
+audit: initializing netlink subsys (disabled)
+audit: type=2000 audit(1622213389.056:1): state=initialized audit_enabled=0 res=1
+thermal_sys: Registered thermal governor 'fair_share'
+thermal_sys: Registered thermal governor 'bang_bang'
+thermal_sys: Registered thermal governor 'step_wise'
+thermal_sys: Registered thermal governor 'user_space'
+thermal_sys: Registered thermal governor 'power_allocator'
+cpuidle: using governor ladder
+cpuidle: using governor menu
+Simple Boot Flag at 0x44 set to 0x1
+ACPI: bus type PCI registered
+acpiphp: ACPI Hot Plug PCI Controller Driver version: 0.5
+PCI: MMCONFIG for domain 0000 [bus 00-ff] at [mem 0xe0000000-0xefffffff] (base 0xe0000000)
+PCI: MMCONFIG at [mem 0xe0000000-0xefffffff] reserved in E820
+pmd_set_huge: Cannot satisfy [mem 0xe0000000-0xe0200000] with a huge-page mapping due to MTRR override.
+PCI: Using configuration type 1 for base access
+ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+Kprobes globally optimized
+HugeTLB registered 1.00 GiB page size, pre-allocated 0 pages
+HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
+ACPI: Added _OSI(Module Device)
+ACPI: Added _OSI(Processor Device)
+ACPI: Added _OSI(3.0 _SCP Extensions)
+ACPI: Added _OSI(Processor Aggregator Device)
+ACPI: Added _OSI(Linux-Dell-Video)
+ACPI: Added _OSI(Linux-Lenovo-NV-HDMI-Audio)
+ACPI: Added _OSI(Linux-HPI-Hybrid-Graphics)
+ACPI: 8 ACPI AML tables successfully acquired and loaded
+ACPI: [Firmware Bug]: BIOS _OSI(Linux) query ignored
+ACPI: Dynamic OEM Table Load:
+ACPI: SSDT 0xFFFF9FC7C0C14800 0005DC (v02 PmRef Cpu0Ist 00003000 INTL 20130927)
+ACPI: \_PR_.CPU0: _OSC native thermal LVT Acked
+ACPI: Dynamic OEM Table Load:
+ACPI: SSDT 0xFFFF9FC7C10D0800 00037F (v02 PmRef Cpu0Cst 00003001 INTL 20130927)
+ACPI: Dynamic OEM Table Load:
+ACPI: SSDT 0xFFFF9FC7C0C12000 0005AA (v02 PmRef ApIst 00003000 INTL 20130927)
+ACPI: Dynamic OEM Table Load:
+ACPI: SSDT 0xFFFF9FC7C1023200 000119 (v02 PmRef ApCst 00003000 INTL 20130927)
+ACPI: EC: EC started
+ACPI: EC: interrupt blocked
+ACPI: EC: EC_CMD/EC_SC=0x66, EC_DATA=0x62
+ACPI: \_SB_.PCI0.LPCB.EC0_: Boot DSDT EC used to handle transactions
+ACPI: Interpreter enabled
+ACPI: (supports S0 S3 S4 S5)
+ACPI: Using IOAPIC for interrupt routing
+PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug
+ACPI: Enabled 9 GPEs in block 00 to 7F
+ACPI: Power Resource [PG00] (on)
+ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-fe])
+acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI HPX-Type3]
+acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug SHPCHotplug PME AER PCIeCapability LTR]
+PCI host bridge to bus 0000:00
+pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7 window]
+pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window]
+pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window]
+pci_bus 0000:00: root bus resource [mem 0x7e800000-0xdfffffff window]
+pci_bus 0000:00: root bus resource [mem 0xfd000000-0xfe7fffff window]
+pci_bus 0000:00: root bus resource [bus 00-fe]
+pci 0000:00:00.0: [8086:1910] type 00 class 0x060000
+pci 0000:00:01.0: [8086:1901] type 01 class 0x060400
+pci 0000:00:01.0: PME# supported from D0 D3hot D3cold
+pci 0000:00:02.0: [8086:191b] type 00 class 0x030000
+pci 0000:00:02.0: reg 0x10: [mem 0x92000000-0x92ffffff 64bit]
+pci 0000:00:02.0: reg 0x18: [mem 0xa0000000-0xafffffff 64bit pref]
+pci 0000:00:02.0: reg 0x20: [io 0x5000-0x503f]
+pci 0000:00:14.0: [8086:a12f] type 00 class 0x0c0330
+pci 0000:00:14.0: reg 0x10: [mem 0x94300000-0x9430ffff 64bit]
+pci 0000:00:14.0: PME# supported from D3hot D3cold
+pci 0000:00:16.0: [8086:a13a] type 00 class 0x078000
+pci 0000:00:16.0: reg 0x10: [mem 0x9432a000-0x9432afff 64bit]
+pci 0000:00:16.0: PME# supported from D3hot
+pci 0000:00:17.0: [8086:a103] type 00 class 0x010601
+pci 0000:00:17.0: reg 0x10: [mem 0x94328000-0x94329fff]
+pci 0000:00:17.0: reg 0x14: [mem 0x9432d000-0x9432d0ff]
+pci 0000:00:17.0: reg 0x18: [io 0x5080-0x5087]
+pci 0000:00:17.0: reg 0x1c: [io 0x5088-0x508b]
+pci 0000:00:17.0: reg 0x20: [io 0x5060-0x507f]
+pci 0000:00:17.0: reg 0x24: [mem 0x9432b000-0x9432b7ff]
+pci 0000:00:17.0: PME# supported from D3hot
+pci 0000:00:1c.0: [8086:a111] type 01 class 0x060400
+pci 0000:00:1c.0: PME# supported from D0 D3hot D3cold
+pci 0000:00:1c.0: Intel SPT PCH root port ACS workaround enabled
+pci 0000:00:1c.2: [8086:a112] type 01 class 0x060400
+pci 0000:00:1c.2: PME# supported from D0 D3hot D3cold
+pci 0000:00:1c.2: Intel SPT PCH root port ACS workaround enabled
+pci 0000:00:1c.3: [8086:a113] type 01 class 0x060400
+pci 0000:00:1c.3: PME# supported from D0 D3hot D3cold
+pci 0000:00:1c.3: Intel SPT PCH root port ACS workaround enabled
+pci 0000:00:1f.0: [8086:a14e] type 00 class 0x060100
+pci 0000:00:1f.2: [8086:a121] type 00 class 0x058000
+pci 0000:00:1f.2: reg 0x10: [mem 0x94324000-0x94327fff]
+pci 0000:00:1f.3: [8086:a170] type 00 class 0x040300
+pci 0000:00:1f.3: reg 0x10: [mem 0x94320000-0x94323fff 64bit]
+pci 0000:00:1f.3: reg 0x20: [mem 0x94310000-0x9431ffff 64bit]
+pci 0000:00:1f.3: PME# supported from D3hot D3cold
+pci 0000:00:1f.4: [8086:a123] type 00 class 0x0c0500
+pci 0000:00:1f.4: reg 0x10: [mem 0x9432c000-0x9432c0ff 64bit]
+pci 0000:00:1f.4: reg 0x20: [io 0x5040-0x505f]
+pci 0000:01:00.0: [10de:139b] type 00 class 0x030200
+pci 0000:01:00.0: reg 0x10: [mem 0x93000000-0x93ffffff]
+pci 0000:01:00.0: reg 0x14: [mem 0x80000000-0x8fffffff 64bit pref]
+pci 0000:01:00.0: reg 0x1c: [mem 0x90000000-0x91ffffff 64bit pref]
+pci 0000:01:00.0: reg 0x24: [io 0x4000-0x407f]
+pci 0000:01:00.0: reg 0x30: [mem 0xfff80000-0xffffffff pref]
+pci 0000:01:00.0: Enabling HDA controller
+pci 0000:00:01.0: PCI bridge to [bus 01-06]
+pci 0000:00:01.0: bridge window [io 0x4000-0x4fff]
+pci 0000:00:01.0: bridge window [mem 0x93000000-0x93ffffff]
+pci 0000:00:01.0: bridge window [mem 0x80000000-0x91ffffff 64bit pref]
+pci 0000:07:00.0: [1217:8520] type 00 class 0x080501
+pci 0000:07:00.0: reg 0x10: [mem 0x94201000-0x94201fff]
+pci 0000:07:00.0: reg 0x14: [mem 0x94200000-0x942007ff]
+pci 0000:07:00.0: PME# supported from D3hot D3cold
+pci 0000:00:1c.0: PCI bridge to [bus 07]
+pci 0000:00:1c.0: bridge window [mem 0x94200000-0x942fffff]
+pci 0000:08:00.0: [8086:3166] type 00 class 0x028000
+pci 0000:08:00.0: reg 0x10: [mem 0x94100000-0x94101fff 64bit]
+pci 0000:08:00.0: PME# supported from D0 D3hot D3cold
+pci 0000:00:1c.2: PCI bridge to [bus 08]
+pci 0000:00:1c.2: bridge window [mem 0x94100000-0x941fffff]
+pci 0000:09:00.0: [10ec:8168] type 00 class 0x020000
+pci 0000:09:00.0: reg 0x10: [io 0x3000-0x30ff]
+pci 0000:09:00.0: reg 0x18: [mem 0x94004000-0x94004fff 64bit]
+pci 0000:09:00.0: reg 0x20: [mem 0x94000000-0x94003fff 64bit]
+pci 0000:09:00.0: supports D1 D2
+pci 0000:09:00.0: PME# supported from D0 D1 D2 D3hot D3cold
+pci 0000:00:1c.3: PCI bridge to [bus 09]
+pci 0000:00:1c.3: bridge window [io 0x3000-0x3fff]
+pci 0000:00:1c.3: bridge window [mem 0x94000000-0x940fffff]
+ACPI: PCI Interrupt Link [LNKA] (IRQs 3 4 5 6 10 *11 12 14 15)
+ACPI: PCI Interrupt Link [LNKB] (IRQs 3 4 5 6 *10 11 12 14 15)
+ACPI: PCI Interrupt Link [LNKC] (IRQs 3 4 5 6 10 *11 12 14 15)
+ACPI: PCI Interrupt Link [LNKD] (IRQs 3 4 5 6 10 *11 12 14 15)
+ACPI: PCI Interrupt Link [LNKE] (IRQs 3 4 5 6 10 *11 12 14 15)
+ACPI: PCI Interrupt Link [LNKF] (IRQs 3 4 5 6 10 *11 12 14 15)
+ACPI: PCI Interrupt Link [LNKG] (IRQs 3 4 5 6 10 *11 12 14 15)
+ACPI: PCI Interrupt Link [LNKH] (IRQs 3 4 5 6 10 *11 12 14 15)
+ACPI: EC: interrupt unblocked
+ACPI: EC: event unblocked
+ACPI: EC: EC_CMD/EC_SC=0x66, EC_DATA=0x62
+ACPI: EC: GPE=0x2
+ACPI: \_SB_.PCI0.LPCB.EC0_: Boot DSDT EC initialization complete
+ACPI: \_SB_.PCI0.LPCB.EC0_: EC: Used to handle transactions and events
+iommu: Default domain type: Translated
+pci 0000:00:02.0: vgaarb: setting as boot VGA device
+pci 0000:00:02.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none
+pci 0000:00:02.0: vgaarb: bridge control possible
+vgaarb: loaded
+EDAC MC: Ver: 3.0.0
+NetLabel: Initializing
+NetLabel: domain hash size = 128
+NetLabel: protocols = UNLABELED CIPSOv4 CALIPSO
+NetLabel: unlabeled traffic allowed by default
+PCI: Using ACPI for IRQ routing
+PCI: pci_cache_line_size set to 64 bytes
+e820: reserve RAM buffer [mem 0x0009e800-0x0009ffff]
+e820: reserve RAM buffer [mem 0x5f693000-0x5fffffff]
+e820: reserve RAM buffer [mem 0x5f78a000-0x5fffffff]
+e820: reserve RAM buffer [mem 0x7558f000-0x77ffffff]
+e820: reserve RAM buffer [mem 0x480800000-0x483ffffff]
+hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0, 0, 0, 0, 0, 0
+hpet0: 8 comparators, 64-bit 24.000000 MHz counter
+clocksource: Switched to clocksource tsc-early
+VFS: Disk quotas dquot_6.6.0
+VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
+AppArmor: AppArmor Filesystem Enabled
+pnp: PnP ACPI init
+system 00:00: [mem 0xfd000000-0xfdabffff] has been reserved
+system 00:00: [mem 0xfdad0000-0xfdadffff] has been reserved
+system 00:00: [mem 0xfdb00000-0xfdffffff] has been reserved
+system 00:00: [mem 0xfe000000-0xfe01ffff] has been reserved
+system 00:00: [mem 0xfe036000-0xfe03bfff] has been reserved
+system 00:00: [mem 0xfe03d000-0xfe3fffff] has been reserved
+system 00:00: [mem 0xfe410000-0xfe7fffff] has been reserved
+system 00:00: Plug and Play ACPI device, IDs PNP0c02 (active)
+system 00:01: [io 0x2000-0x20fe] has been reserved
+system 00:01: Plug and Play ACPI device, IDs PNP0c02 (active)
+system 00:02: [io 0x0680-0x069f] has been reserved
+system 00:02: [io 0xffff] has been reserved
+system 00:02: [io 0xffff] has been reserved
+system 00:02: [io 0xffff] has been reserved
+system 00:02: [io 0x1800-0x18fe] has been reserved
+system 00:02: [io 0x164e-0x164f] has been reserved
+system 00:02: Plug and Play ACPI device, IDs PNP0c02 (active)
+system 00:03: [io 0x0800-0x087f] has been reserved
+system 00:03: Plug and Play ACPI device, IDs PNP0c02 (active)
+pnp 00:04: Plug and Play ACPI device, IDs PNP0b00 (active)
+system 00:05: [io 0x1854-0x1857] has been reserved
+system 00:05: Plug and Play ACPI device, IDs INT3f0d PNP0c02 (active)
+pnp 00:06: Plug and Play ACPI device, IDs PNP0303 (active)
+pnp 00:07: Plug and Play ACPI device, IDs SYN2b5b PNP0f03 (active)
+system 00:08: [mem 0xfe035000-0xfe035fff] has been reserved
+system 00:08: [mem 0xfe034008-0xfe034fff] has been reserved
+system 00:08: [mem 0xfdaf0000-0xfdafffff] has been reserved
+system 00:08: [mem 0xfdae0000-0xfdaeffff] has been reserved
+system 00:08: [mem 0xfdac0000-0xfdacffff] has been reserved
+system 00:08: Plug and Play ACPI device, IDs PNP0c02 (active)
+system 00:09: [mem 0xfe034000-0xfe034007] has been reserved
+system 00:09: Plug and Play ACPI device, IDs PNP0c02 (active)
+system 00:0a: [mem 0xfed10000-0xfed17fff] has been reserved
+system 00:0a: [mem 0xfed18000-0xfed18fff] has been reserved
+system 00:0a: [mem 0xfed19000-0xfed19fff] has been reserved
+system 00:0a: [mem 0xe0000000-0xefffffff] has been reserved
+system 00:0a: [mem 0xfed20000-0xfed3ffff] has been reserved
+system 00:0a: [mem 0xfed90000-0xfed93fff] could not be reserved
+system 00:0a: [mem 0xfed45000-0xfed8ffff] could not be reserved