From: Svjatoslav Agejenko Date: Sun, 15 Mar 2026 01:16:30 +0000 (+0200) Subject: Initial commit X-Git-Url: http://www2.svjatoslav.eu/gitweb/?a=commitdiff_plain;h=7be92e2d151f71d9a525de74d6f93f57408fcf27;p=sixth-3d-demos.git Initial commit --- 7be92e2d151f71d9a525de74d6f93f57408fcf27 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31378ad --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/.idea/ +/target/ +/.classpath +/.project +/.settings/ +/doc/graphs/ +/doc/apidocs/ +/*.iml +*.html diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..8b6057f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,121 @@ +# 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. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/COPYING @@ -0,0 +1,121 @@ +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. diff --git a/Tools/Open with IntelliJ IDEA b/Tools/Open with IntelliJ IDEA new file mode 100755 index 0000000..304bf94 --- /dev/null +++ b/Tools/Open with IntelliJ IDEA @@ -0,0 +1,54 @@ +#!/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 diff --git a/Tools/Update web site b/Tools/Update web site new file mode 100755 index 0000000..26537ed --- /dev/null +++ b/Tools/Update web site @@ -0,0 +1,103 @@ +#!/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 diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..0cc8fd2 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,2 @@ +apidocs/ +sixth-3d-demos.jar diff --git a/doc/index.org b/doc/index.org new file mode 100644 index 0000000..6ca38c4 --- /dev/null +++ b/doc/index.org @@ -0,0 +1,242 @@ +#+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 + +#+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 | +| | 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. diff --git a/doc/overview.png b/doc/overview.png new file mode 100644 index 0000000..ba977ab Binary files /dev/null and b/doc/overview.png differ diff --git a/doc/screenshots/life.png b/doc/screenshots/life.png new file mode 100644 index 0000000..565f5ab Binary files /dev/null and b/doc/screenshots/life.png differ diff --git a/doc/screenshots/mathematical formulas.png b/doc/screenshots/mathematical formulas.png new file mode 100644 index 0000000..fab8469 Binary files /dev/null and b/doc/screenshots/mathematical formulas.png differ diff --git a/doc/screenshots/raytracing fractal in voxel polygon hybrid scene.png b/doc/screenshots/raytracing fractal in voxel polygon hybrid scene.png new file mode 100644 index 0000000..7094240 Binary files /dev/null and b/doc/screenshots/raytracing fractal in voxel polygon hybrid scene.png differ diff --git a/doc/screenshots/sinus heightmaps and sphere.png b/doc/screenshots/sinus heightmaps and sphere.png new file mode 100644 index 0000000..0d3e92b Binary files /dev/null and b/doc/screenshots/sinus heightmaps and sphere.png differ diff --git a/doc/screenshots/text editors 2.png b/doc/screenshots/text editors 2.png new file mode 100644 index 0000000..cb1733f Binary files /dev/null and b/doc/screenshots/text editors 2.png differ diff --git a/doc/screenshots/text editors.png b/doc/screenshots/text editors.png new file mode 100644 index 0000000..8567b8b Binary files /dev/null and b/doc/screenshots/text editors.png differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4baf761 --- /dev/null +++ b/pom.xml @@ -0,0 +1,173 @@ + + 4.0.0 + eu.svjatoslav + sixth-3d-demos + 1.0-SNAPSHOT + Sixth 3D demos + 3D engine demos + + + UTF-8 + UTF-8 + 21 + 21 + + + + svjatoslav.eu + https://svjatoslav.eu + + + + + eu.svjatoslav + sixth-3d + 1.4-SNAPSHOT + + + eu.svjatoslav + svjatoslavcommons + 1.8 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 21 + 21 + true + UTF-8 + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.0 + + + attach-javadocs + + jar + + + + + + + + foo + bar + + + + ${java.home}/bin/javadoc + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.4.3 + + UTF-8 + + + + + maven-assembly-plugin + + + + + eu.svjatoslav.sixth.e3d.examples.launcher.Main + + + + jar-with-dependencies + + sixth-3d-demos + false + + + + + package-jar-with-dependencies + package + + single + + + + jar-with-dependencies + + + + eu.svjatoslav.sixth.e3d.examples.launcher.Main + + + + + + + + + + + org.apache.maven.wagon + wagon-ssh-external + 2.6 + + + + + + + + svjatoslav.eu + svjatoslav.eu + scpexe://svjatoslav.eu:10006/srv/maven + + + svjatoslav.eu + svjatoslav.eu + scpexe://svjatoslav.eu:10006/srv/maven + + + + + + svjatoslav.eu + Svjatoslav repository + https://www3.svjatoslav.eu/maven/ + + + + + scm:git:ssh://n0@svjatoslav.eu/home/git/repositories/sixth-3d-demos.git + scm:git:ssh://n0@svjatoslav.eu/home/git/repositories/sixth-3d-demos.git + + + + + diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/FillRateTest.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/FillRateTest.java new file mode 100644 index 0000000..74f415b --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/FillRateTest.java @@ -0,0 +1,351 @@ +/* + * 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. + * + *

Key controls: + *

+ * + * @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 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 diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/GraphDemo.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/GraphDemo.java new file mode 100755 index 0000000..ae7ff23 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/GraphDemo.java @@ -0,0 +1,249 @@ +/* + * 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 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 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 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 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 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 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)); + } + +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/OctreeDemo.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/OctreeDemo.java new file mode 100755 index 0000000..23a5282 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/OctreeDemo.java @@ -0,0 +1,239 @@ +/* + * 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 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); + } + +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/RainingNumbersDemo.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/RainingNumbersDemo.java new file mode 100644 index 0000000..7f97540 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/RainingNumbersDemo.java @@ -0,0 +1,98 @@ +/* + * 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 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); + } +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/RandomPolygonsDemo.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/RandomPolygonsDemo.java new file mode 100755 index 0000000..8754044 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/RandomPolygonsDemo.java @@ -0,0 +1,100 @@ +/* + * 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); + + } +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/ShadedShapesDemo.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/ShadedShapesDemo.java new file mode 100644 index 0000000..c0cbd50 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/ShadedShapesDemo.java @@ -0,0 +1,199 @@ +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 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 lights; + + /** + * Creates an animator for the specified lights. + * @param lights the list of lights to animate + */ + MultiLightAnimator(List 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; + } + } +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/TextEditorDemo.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/TextEditorDemo.java new file mode 100644 index 0000000..ec5c6b6 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/TextEditorDemo.java @@ -0,0 +1,91 @@ +/* + * 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); + } +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/TextEditorDemo2.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/TextEditorDemo2.java new file mode 100644 index 0000000..887fb30 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/TextEditorDemo2.java @@ -0,0 +1,189 @@ +/* + * 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); + } +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/galaxy_demo/Galaxy.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/galaxy_demo/Galaxy.java new file mode 100755 index 0000000..a632268 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/galaxy_demo/Galaxy.java @@ -0,0 +1,118 @@ +/* + * 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 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)); + } + +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/galaxy_demo/PointCloudDemo.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/galaxy_demo/PointCloudDemo.java new file mode 100644 index 0000000..bc9f227 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/galaxy_demo/PointCloudDemo.java @@ -0,0 +1,37 @@ +/* + * 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)); + + } +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/launcher/ApplicationListPanel.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/launcher/ApplicationListPanel.java new file mode 100644 index 0000000..424406d --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/launcher/ApplicationListPanel.java @@ -0,0 +1,161 @@ +/* + * 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); + } + } + +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/launcher/Main.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/launcher/Main.java new file mode 100755 index 0000000..9f87947 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/launcher/Main.java @@ -0,0 +1,47 @@ +/* + * 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); + } + +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Cell.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Cell.java new file mode 100755 index 0000000..80622ff --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Cell.java @@ -0,0 +1,159 @@ +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()); + } + +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Main.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Main.java new file mode 100644 index 0000000..86ac7f1 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Main.java @@ -0,0 +1,127 @@ +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. + * + *

Key controls: + *

    + *
  • Space - Evolve one generation
  • + *
  • Enter - Evolve with history (leaves stars marking previous positions)
  • + *
  • C - Clear the matrix
  • + *
+ */ +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); + } + +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Matrix.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Matrix.java new file mode 100644 index 0000000..44fedcc --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Matrix.java @@ -0,0 +1,181 @@ +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); + } +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Star.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Star.java new file mode 100644 index 0000000..f3303db --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/life_demo/Star.java @@ -0,0 +1,52 @@ +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 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 + ); + } + +} diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/package-info.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/package-info.java new file mode 100755 index 0000000..0c166bd --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/examples/package-info.java @@ -0,0 +1,12 @@ +/* + * 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; + diff --git a/src/main/resources/demo.txt b/src/main/resources/demo.txt new file mode 100644 index 0000000..fffb8fe --- /dev/null +++ b/src/main/resources/demo.txt @@ -0,0 +1,505 @@ +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