Initial commit
This commit is contained in:
commit
e96a30c275
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#
|
||||||
|
# https://help.github.com/articles/dealing-with-line-endings/
|
||||||
|
#
|
||||||
|
# These are explicitly windows files and should use crlf
|
||||||
|
*.bat text eol=crlf
|
||||||
|
|
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Ignore Gradle project-specific cache directory
|
||||||
|
.gradle
|
||||||
|
|
||||||
|
# Ignore Gradle build output directory
|
||||||
|
build
|
||||||
|
|
||||||
|
# Ignore Eclipse IDE files
|
||||||
|
bin
|
||||||
|
.settings
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
|
||||||
|
# Ignore Windows Thumb.db files
|
||||||
|
**/Thumbs.db
|
||||||
|
|
||||||
|
# Ignore MacOS
|
||||||
|
**/.DS_Store
|
674
LICENSE
Normal file
674
LICENSE
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
73
build.gradle
Normal file
73
build.gradle
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
plugins {
|
||||||
|
// Apply the java-library plugin to add support for Java Library
|
||||||
|
id 'java-library'
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
jcenter()
|
||||||
|
|
||||||
|
maven { url 'http://windcorp.ru/./maven' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'org.apache.commons:commons-math3:3.6.1'
|
||||||
|
implementation 'com.google.guava:guava:28.0-jre'
|
||||||
|
implementation 'net.sf.trove4j:trove4j:3.0.3'
|
||||||
|
|
||||||
|
implementation 'ru.windcorp.fork.io.github.java-graphics:glm:1.0.1'
|
||||||
|
|
||||||
|
testImplementation 'junit:junit:4.12'
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LWJGL
|
||||||
|
* (auto-generated script)
|
||||||
|
* ((here be dragons))
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.gradle.internal.os.OperatingSystem
|
||||||
|
|
||||||
|
project.ext.lwjglVersion = "3.2.3"
|
||||||
|
|
||||||
|
switch (OperatingSystem.current()) {
|
||||||
|
case OperatingSystem.LINUX:
|
||||||
|
def osArch = System.getProperty("os.arch")
|
||||||
|
project.ext.lwjglNatives = osArch.startsWith("arm") || osArch.startsWith("aarch64")
|
||||||
|
? "natives-linux-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}"
|
||||||
|
: "natives-linux"
|
||||||
|
break
|
||||||
|
case OperatingSystem.MAC_OS:
|
||||||
|
project.ext.lwjglNatives = "natives-macos"
|
||||||
|
break
|
||||||
|
case OperatingSystem.WINDOWS:
|
||||||
|
project.ext.lwjglNatives = System.getProperty("os.arch").contains("64") ? "natives-windows" : "natives-windows-x86"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
|
||||||
|
|
||||||
|
implementation "org.lwjgl:lwjgl"
|
||||||
|
implementation "org.lwjgl:lwjgl-assimp"
|
||||||
|
implementation "org.lwjgl:lwjgl-bgfx"
|
||||||
|
implementation "org.lwjgl:lwjgl-glfw"
|
||||||
|
implementation "org.lwjgl:lwjgl-nanovg"
|
||||||
|
implementation "org.lwjgl:lwjgl-nuklear"
|
||||||
|
implementation "org.lwjgl:lwjgl-openal"
|
||||||
|
implementation "org.lwjgl:lwjgl-opengl"
|
||||||
|
implementation "org.lwjgl:lwjgl-par"
|
||||||
|
implementation "org.lwjgl:lwjgl-stb"
|
||||||
|
implementation "org.lwjgl:lwjgl-vulkan"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-assimp::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-bgfx::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-nanovg::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-nuklear::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-par::$lwjglNatives"
|
||||||
|
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
|
||||||
|
if (lwjglNatives == "natives-macos") runtimeOnly "org.lwjgl:lwjgl-vulkan::$lwjglNatives"
|
||||||
|
}
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
183
gradlew
vendored
Normal file
183
gradlew
vendored
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
100
gradlew.bat
vendored
Normal file
100
gradlew.bat
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
1
settings.gradle
Normal file
1
settings.gradle
Normal file
@ -0,0 +1 @@
|
|||||||
|
rootProject.name = 'Optica'
|
22
src/main/java/ru/windcorp/optica/Optica.java
Normal file
22
src/main/java/ru/windcorp/optica/Optica.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica;
|
||||||
|
|
||||||
|
public class Optica {
|
||||||
|
|
||||||
|
}
|
26
src/main/java/ru/windcorp/optica/OpticaLauncher.java
Normal file
26
src/main/java/ru/windcorp/optica/OpticaLauncher.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica;
|
||||||
|
|
||||||
|
public class OpticaLauncher {
|
||||||
|
|
||||||
|
public static void launch(String[] args, Proxy proxy) {
|
||||||
|
proxy.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
src/main/java/ru/windcorp/optica/Proxy.java
Normal file
24
src/main/java/ru/windcorp/optica/Proxy.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica;
|
||||||
|
|
||||||
|
public interface Proxy {
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
}
|
42
src/main/java/ru/windcorp/optica/client/ClientProxy.java
Normal file
42
src/main/java/ru/windcorp/optica/client/ClientProxy.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.Proxy;
|
||||||
|
import ru.windcorp.optica.client.graphics.GUI;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.GraphicsBackend;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.RenderTaskQueue;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.ShapeRenderProgram;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.LayerWorld;
|
||||||
|
|
||||||
|
public class ClientProxy implements Proxy {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
GraphicsBackend.initialize();
|
||||||
|
try {
|
||||||
|
RenderTaskQueue.waitAndInvoke(ShapeRenderProgram::init);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.addBottomLayer(new LayerWorld());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.OpticaLauncher;
|
||||||
|
|
||||||
|
public class OpticaClientMain {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
OpticaLauncher.launch(args, new ClientProxy());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
167
src/main/java/ru/windcorp/optica/client/TestLayer.java
Normal file
167
src/main/java/ru/windcorp/optica/client/TestLayer.java
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client;
|
||||||
|
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
|
||||||
|
import glm.mat._3.Mat3;
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.optica.client.graphics.Layer;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.GraphicsBackend;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.GraphicsInterface;
|
||||||
|
import ru.windcorp.optica.client.graphics.input.KeyEvent;
|
||||||
|
import ru.windcorp.optica.client.graphics.input.CursorMoveEvent;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Model;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.DynamicModel;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Shapes;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.SimpleTexture;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Sprite;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.TextureManager;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.Camera;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
|
||||||
|
public class TestLayer extends Layer {
|
||||||
|
|
||||||
|
private final Model model;
|
||||||
|
|
||||||
|
private final Camera camera = new Camera(
|
||||||
|
new Vec3(),
|
||||||
|
0, (float) Math.PI,
|
||||||
|
(float) Math.toRadians(70)
|
||||||
|
);
|
||||||
|
|
||||||
|
private final Vec3 velocity = new Vec3();
|
||||||
|
private final Vec3 tmp = new Vec3();
|
||||||
|
|
||||||
|
private final Mat3 angMat = new Mat3();
|
||||||
|
|
||||||
|
private int movementX = 0;
|
||||||
|
private int movementY = 0;
|
||||||
|
private int movementZ = 0;
|
||||||
|
|
||||||
|
public TestLayer() {
|
||||||
|
super("Test");
|
||||||
|
|
||||||
|
Texture top = qtex("grass_top");
|
||||||
|
Texture side = qtex("grass_side");
|
||||||
|
Texture bottom = qtex("grass_bottom");
|
||||||
|
|
||||||
|
model = new DynamicModel(DynamicModel.builder()
|
||||||
|
.addDynamicPart(
|
||||||
|
new Shapes.PppBuilder(top, bottom, side, side, side, side)
|
||||||
|
.create()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
@Override
|
||||||
|
protected void getDynamicTransform(int shapeIndex, Mat4 result) {
|
||||||
|
result.translate(0, 0, +5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Texture qtex(String name) {
|
||||||
|
return new SimpleTexture(new Sprite(TextureManager.load(name, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initialize() {
|
||||||
|
GraphicsInterface.subscribeToInputEvents(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final WorldRenderer renderer = new WorldRenderer();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doRender() {
|
||||||
|
camera.apply(renderer);
|
||||||
|
|
||||||
|
angMat.set().rotateY(-camera.getYaw());
|
||||||
|
|
||||||
|
tmp.set(movementX, 0, movementZ);
|
||||||
|
angMat.mul_(tmp); // bug in jglm
|
||||||
|
tmp.y = movementY;
|
||||||
|
tmp.mul(0.1f);
|
||||||
|
tmp.sub(velocity);
|
||||||
|
tmp.mul(0.1f);
|
||||||
|
velocity.add(tmp);
|
||||||
|
camera.move(velocity);
|
||||||
|
|
||||||
|
model.render(renderer);
|
||||||
|
|
||||||
|
renderer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean flag = true;
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onKeyEvent(KeyEvent event) {
|
||||||
|
if (event.isRepeat()) return;
|
||||||
|
|
||||||
|
int multiplier = event.isPress() ? 1 : -1;
|
||||||
|
|
||||||
|
switch (event.getKey()) {
|
||||||
|
case GLFW.GLFW_KEY_W:
|
||||||
|
movementZ += -1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_S:
|
||||||
|
movementZ += +1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_A:
|
||||||
|
movementX += -1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_D:
|
||||||
|
movementX += +1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_SPACE:
|
||||||
|
movementY += +1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_LEFT_SHIFT:
|
||||||
|
movementY += -1 * multiplier;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW.GLFW_KEY_ESCAPE:
|
||||||
|
if (!event.isPress()) return;
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL);
|
||||||
|
} else {
|
||||||
|
GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = !flag;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onMouseMoved(CursorMoveEvent event) {
|
||||||
|
if (!flag) return;
|
||||||
|
|
||||||
|
final float yawScale = 0.002f;
|
||||||
|
final float pitchScale = yawScale;
|
||||||
|
|
||||||
|
camera.turn(
|
||||||
|
(float) (event.getChangeY() * pitchScale),
|
||||||
|
(float) (event.getChangeX() * yawScale)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
src/main/java/ru/windcorp/optica/client/graphics/GUI.java
Normal file
47
src/main/java/ru/windcorp/optica/client/graphics/GUI.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GUI {
|
||||||
|
|
||||||
|
private static final List<Layer> LAYERS = new ArrayList<>();
|
||||||
|
|
||||||
|
private GUI() {}
|
||||||
|
|
||||||
|
public synchronized static void addBottomLayer(Layer layer) {
|
||||||
|
LAYERS.add(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized static void addTopLayer(Layer layer) {
|
||||||
|
LAYERS.add(0, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized static void removeLayer(Layer layer) {
|
||||||
|
LAYERS.remove(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized static void render() {
|
||||||
|
for (int i = LAYERS.size() - 1; i >= 0; --i) {
|
||||||
|
LAYERS.get(i).render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
src/main/java/ru/windcorp/optica/client/graphics/Layer.java
Normal file
47
src/main/java/ru/windcorp/optica/client/graphics/Layer.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics;
|
||||||
|
|
||||||
|
public abstract class Layer {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private boolean hasInitialized = false;
|
||||||
|
|
||||||
|
public Layer(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Layer " + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render() {
|
||||||
|
if (!hasInitialized) {
|
||||||
|
initialize();
|
||||||
|
hasInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
doRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void initialize();
|
||||||
|
|
||||||
|
protected abstract void doRender();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
public class GraphicsBackend {
|
||||||
|
|
||||||
|
private static RenderThread renderThread;
|
||||||
|
|
||||||
|
private static long windowHandle;
|
||||||
|
|
||||||
|
private static int framebufferWidth;
|
||||||
|
private static int framebufferHeight;
|
||||||
|
|
||||||
|
private static double frameLength = 1.0 / 60; // TODO do something about it
|
||||||
|
private static int framesRendered = 0;
|
||||||
|
private static double frameStart = Double.NaN;
|
||||||
|
|
||||||
|
private GraphicsBackend() {}
|
||||||
|
|
||||||
|
public static void initialize() {
|
||||||
|
startRenderThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void startRenderThread() {
|
||||||
|
renderThread = new RenderThread();
|
||||||
|
renderThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Thread getRenderThread() {
|
||||||
|
return renderThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setWindowHandle(long windowHandle) {
|
||||||
|
GraphicsBackend.windowHandle = windowHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getWindowHandle() {
|
||||||
|
return windowHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getFramebufferWidth() {
|
||||||
|
return framebufferWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getFramebufferHeight() {
|
||||||
|
return framebufferHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onFramebufferResized(long window, int newWidth, int newHeight) {
|
||||||
|
if (window != windowHandle) return;
|
||||||
|
|
||||||
|
framebufferWidth = newWidth;
|
||||||
|
framebufferHeight = newHeight;
|
||||||
|
|
||||||
|
glViewport(0, 0, framebufferWidth, framebufferHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void startFrame() {
|
||||||
|
double now = glfwGetTime();
|
||||||
|
|
||||||
|
if (Double.isNaN(frameStart)) {
|
||||||
|
frameStart = now;
|
||||||
|
} else {
|
||||||
|
frameLength = now - frameStart;
|
||||||
|
frameStart = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void endFrame() {
|
||||||
|
framesRendered++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getFrameStart() {
|
||||||
|
return frameStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getFrameLength() {
|
||||||
|
return frameLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getFramesRendered() {
|
||||||
|
return framesRendered;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import glm.vec._2.d.Vec2d;
|
||||||
|
|
||||||
|
public class GraphicsInterface {
|
||||||
|
|
||||||
|
private GraphicsInterface() {}
|
||||||
|
|
||||||
|
public static Thread getRenderThread() {
|
||||||
|
return GraphicsBackend.getRenderThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRenderThread() {
|
||||||
|
return Thread.currentThread() == getRenderThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getFramebufferWidth() {
|
||||||
|
return GraphicsBackend.getFramebufferWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getFramebufferHeight() {
|
||||||
|
return GraphicsBackend.getFramebufferHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float getAspectRatio() {
|
||||||
|
return ((float) getFramebufferWidth()) / getFramebufferHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getTime() {
|
||||||
|
return GraphicsBackend.getFrameStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getFrameLength() {
|
||||||
|
return GraphicsBackend.getFrameLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getFPS() {
|
||||||
|
return 1 / GraphicsBackend.getFrameLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void subscribeToInputEvents(Object listener) {
|
||||||
|
InputHandler.register(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getCursorX() {
|
||||||
|
return InputHandler.getCursorX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getCursorY() {
|
||||||
|
return InputHandler.getCursorY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vec2d getCursorPosition() {
|
||||||
|
return InputHandler.getCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
|
import glm.vec._2.d.Vec2d;
|
||||||
|
import ru.windcorp.optica.client.graphics.input.*;
|
||||||
|
|
||||||
|
public class InputHandler {
|
||||||
|
|
||||||
|
private static final EventBus INPUT_EVENT_BUS = new EventBus("Input");
|
||||||
|
|
||||||
|
private static class ModifiableKeyEvent extends KeyEvent {
|
||||||
|
|
||||||
|
public void initialize(int key, int scancode, int action, int mods) {
|
||||||
|
this.key = key;
|
||||||
|
this.scancode = scancode;
|
||||||
|
this.action = action;
|
||||||
|
this.mods = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final ModifiableKeyEvent THE_KEY_EVENT = new ModifiableKeyEvent();
|
||||||
|
|
||||||
|
static void handleKeyInput(
|
||||||
|
long window,
|
||||||
|
int key,
|
||||||
|
int scancode,
|
||||||
|
int action,
|
||||||
|
int mods
|
||||||
|
) {
|
||||||
|
if (GraphicsBackend.getWindowHandle() != window) return;
|
||||||
|
THE_KEY_EVENT.initialize(key, scancode, action, mods);
|
||||||
|
dispatch(THE_KEY_EVENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ModifiableCursorMoveEvent extends CursorMoveEvent {
|
||||||
|
|
||||||
|
public void initialize(double x, double y) {
|
||||||
|
Vec2d newPos = getNewPosition();
|
||||||
|
newPos.x = x;
|
||||||
|
newPos.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Vec2d CURSOR_POSITION = new Vec2d().set(
|
||||||
|
Double.NaN, Double.NaN
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final ModifiableCursorMoveEvent THE_CURSOR_MOVE_EVENT =
|
||||||
|
new ModifiableCursorMoveEvent();
|
||||||
|
|
||||||
|
static void handleMouseMoveInput(
|
||||||
|
long window,
|
||||||
|
double x, double y
|
||||||
|
) {
|
||||||
|
if (GraphicsBackend.getWindowHandle() != window) return;
|
||||||
|
|
||||||
|
if (Double.isNaN(CURSOR_POSITION.x)) {
|
||||||
|
CURSOR_POSITION.set(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
THE_CURSOR_MOVE_EVENT.initialize(x, y);
|
||||||
|
dispatch(THE_CURSOR_MOVE_EVENT);
|
||||||
|
|
||||||
|
CURSOR_POSITION.set(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getCursorX() {
|
||||||
|
return CURSOR_POSITION.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getCursorY() {
|
||||||
|
return CURSOR_POSITION.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vec2d getCursorPosition() {
|
||||||
|
return CURSOR_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void dispatch(InputEvent event) {
|
||||||
|
INPUT_EVENT_BUS.post(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(Object listener) {
|
||||||
|
INPUT_EVENT_BUS.register(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
import static org.lwjgl.system.MemoryUtil.*;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL;
|
||||||
|
|
||||||
|
class LWJGLInitializer {
|
||||||
|
|
||||||
|
private LWJGLInitializer() {}
|
||||||
|
|
||||||
|
public static void initialize() {
|
||||||
|
checkEnvironment();
|
||||||
|
initializeGLFW();
|
||||||
|
createWindow();
|
||||||
|
positionWindow();
|
||||||
|
createWindowIcons();
|
||||||
|
initializeOpenGL();
|
||||||
|
setupWindowCallbacks();
|
||||||
|
|
||||||
|
glfwShowWindow(GraphicsBackend.getWindowHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkEnvironment() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initializeGLFW() {
|
||||||
|
// TODO Do GLFW error handling: check glfwInit, setup error callback
|
||||||
|
glfwInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createWindow() {
|
||||||
|
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
||||||
|
glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
|
||||||
|
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
|
||||||
|
|
||||||
|
long handle = glfwCreateWindow(900, 900, "OpticaTest", NULL, NULL);
|
||||||
|
|
||||||
|
// TODO Check that handle != NULL
|
||||||
|
|
||||||
|
GraphicsBackend.setWindowHandle(handle);
|
||||||
|
|
||||||
|
glfwSetInputMode(handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(handle);
|
||||||
|
glfwSwapInterval(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void positionWindow() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createWindowIcons() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initializeOpenGL() {
|
||||||
|
GL.createCapabilities();
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setupWindowCallbacks() {
|
||||||
|
long handle = GraphicsBackend.getWindowHandle();
|
||||||
|
|
||||||
|
glfwSetFramebufferSizeCallback(handle,
|
||||||
|
GraphicsBackend::onFramebufferResized);
|
||||||
|
|
||||||
|
glfwSetKeyCallback(handle, InputHandler::handleKeyInput);
|
||||||
|
glfwSetCursorPosCallback(handle, InputHandler::handleMouseMoveInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME deal with client invocations of .delete() when properly disposing of
|
||||||
|
* objects mid-execution
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class OpenGLObjectTracker {
|
||||||
|
|
||||||
|
public static interface OpenGLDeletable {
|
||||||
|
void delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Collection<OpenGLDeletable> TO_DELETE = new ArrayList<>();
|
||||||
|
|
||||||
|
public synchronized static void register(OpenGLDeletable object) {
|
||||||
|
TO_DELETE.add(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized static void deleteAllObjects() {
|
||||||
|
TO_DELETE.forEach(OpenGLDeletable::delete);
|
||||||
|
TO_DELETE.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.common.util.ThrowingRunnable;
|
||||||
|
|
||||||
|
public class RenderTaskQueue {
|
||||||
|
|
||||||
|
private static final Queue<Runnable> QUEUE = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
|
private RenderTaskQueue() {}
|
||||||
|
|
||||||
|
public static void invokeLater(Runnable task) {
|
||||||
|
QUEUE.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void invokeNow(Runnable task) {
|
||||||
|
if (GraphicsInterface.isRenderThread()) {
|
||||||
|
task.run();
|
||||||
|
} else {
|
||||||
|
invokeLater(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Object WAIT_AND_INVOKE_MONITOR = new Object();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T extends Throwable> void waitAndInvoke(
|
||||||
|
ThrowingRunnable<T> task
|
||||||
|
) throws InterruptedException, T {
|
||||||
|
|
||||||
|
if (GraphicsInterface.isRenderThread()) {
|
||||||
|
task.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final AtomicBoolean flag =
|
||||||
|
new AtomicBoolean(false);
|
||||||
|
final AtomicReference<Throwable> thrownContainer =
|
||||||
|
new AtomicReference<>(null);
|
||||||
|
|
||||||
|
invokeLater(() -> {
|
||||||
|
|
||||||
|
try {
|
||||||
|
task.run();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
thrownContainer.set(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.set(true);
|
||||||
|
|
||||||
|
synchronized (WAIT_AND_INVOKE_MONITOR) {
|
||||||
|
WAIT_AND_INVOKE_MONITOR.notifyAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while (!flag.get()) {
|
||||||
|
synchronized (WAIT_AND_INVOKE_MONITOR) {
|
||||||
|
WAIT_AND_INVOKE_MONITOR.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Throwable thrown = thrownContainer.get();
|
||||||
|
if (thrown != null) {
|
||||||
|
if (thrown instanceof RuntimeException) {
|
||||||
|
throw (RuntimeException) thrown;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thrown instanceof Error) {
|
||||||
|
throw (Error) thrown;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw (T) thrown; // Guaranteed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runTasks() {
|
||||||
|
Iterator<Runnable> tasks = QUEUE.iterator();
|
||||||
|
|
||||||
|
while (tasks.hasNext()) {
|
||||||
|
tasks.next().run();
|
||||||
|
tasks.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.GUI;
|
||||||
|
|
||||||
|
class RenderThread extends Thread {
|
||||||
|
|
||||||
|
public RenderThread() {
|
||||||
|
super("Render");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
LWJGLInitializer.initialize();
|
||||||
|
mainLoop();
|
||||||
|
freeResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mainLoop() {
|
||||||
|
while (shouldRun()) {
|
||||||
|
GraphicsBackend.startFrame();
|
||||||
|
RenderTaskQueue.runTasks();
|
||||||
|
render();
|
||||||
|
waitForFrame();
|
||||||
|
GraphicsBackend.endFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void render() {
|
||||||
|
clear();
|
||||||
|
doRender();
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clear() {
|
||||||
|
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRender() {
|
||||||
|
GUI.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitForFrame() {
|
||||||
|
glfwSwapBuffers(GraphicsBackend.getWindowHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void freeResources() {
|
||||||
|
OpenGLObjectTracker.deleteAllObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldRun() {
|
||||||
|
return !glfwWindowShouldClose(GraphicsBackend.getWindowHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL15.GL_DYNAMIC_DRAW;
|
||||||
|
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
|
||||||
|
import static org.lwjgl.opengl.GL15.GL_STREAM_DRAW;
|
||||||
|
|
||||||
|
public enum Usage { // TODO add _COPY and _READ, pref. as another enum
|
||||||
|
STATIC(GL_STATIC_DRAW),
|
||||||
|
DYNAMIC(GL_DYNAMIC_DRAW),
|
||||||
|
STREAM(GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
private final int glCode;
|
||||||
|
|
||||||
|
private Usage(int glCode) {
|
||||||
|
this.glCode = glCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlCode() {
|
||||||
|
return glCode;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,203 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
|
||||||
|
import java.nio.*;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
|
|
||||||
|
public class VertexBufferObject implements OpenGLDeletable {
|
||||||
|
|
||||||
|
public static enum BindTarget {
|
||||||
|
ARRAY(GL_ARRAY_BUFFER),
|
||||||
|
ELEMENT_ARRAY(GL_ELEMENT_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
private final int glCode;
|
||||||
|
|
||||||
|
private BindTarget(int glCode) {
|
||||||
|
this.glCode = glCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlCode() {
|
||||||
|
return glCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int handle;
|
||||||
|
|
||||||
|
private long length = 0;
|
||||||
|
private final Usage usage;
|
||||||
|
|
||||||
|
public VertexBufferObject(Usage usage) {
|
||||||
|
handle = glGenBuffers();
|
||||||
|
OpenGLObjectTracker.register(this);
|
||||||
|
|
||||||
|
this.usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(ByteBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.remaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(double[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.length * Double.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(DoubleBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.remaining() * Double.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(float[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.length * Float.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(FloatBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.remaining() * Float.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.length * Integer.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(IntBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.remaining() * Integer.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(long[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.length * Long.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(LongBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.remaining() * Long.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(short[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.length * Short.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(ShortBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
|
||||||
|
length = data.remaining() * Short.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initData(long length) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, length, usage.getGlCode());
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, ByteBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, double[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, DoubleBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, float[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, FloatBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, int[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, IntBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, long[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, LongBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, short[] data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int offset, ShortBuffer data) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(BindTarget target) {
|
||||||
|
glBindBuffer(target.getGlCode(), handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Usage getUsage() {
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandle() {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
glDeleteBuffers(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.common.resource.Resource;
|
||||||
|
|
||||||
|
public class CombinedShader extends Shader {
|
||||||
|
|
||||||
|
public CombinedShader(String... resources) {
|
||||||
|
super(getTypeOf(resources), combine(resources));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ShaderType getTypeOf(String[] resources) {
|
||||||
|
ShaderType first = ShaderType.guessByResourceName(resources[0]);
|
||||||
|
|
||||||
|
for (int i = 1; i < resources.length; ++i) {
|
||||||
|
if (ShaderType.guessByResourceName(resources[i]) != first) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Deduced shader types of "
|
||||||
|
+ resources[0]
|
||||||
|
+ " and "
|
||||||
|
+ resources[i]
|
||||||
|
+ " differ"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String combine(String[] resources) {
|
||||||
|
StringBuilder accumulator = new StringBuilder("#version 120\n");
|
||||||
|
|
||||||
|
for (String resourceName : resources) {
|
||||||
|
Resource resource = getShaderResource(resourceName);
|
||||||
|
|
||||||
|
accumulator.append("\n// START " + resourceName);
|
||||||
|
accumulator.append(stripVersionAnnotations(resource));
|
||||||
|
accumulator.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return accumulator.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String stripVersionAnnotations(Resource resource) {
|
||||||
|
String contents = resource.readAsString();
|
||||||
|
|
||||||
|
int versionIndex;
|
||||||
|
for (versionIndex = 0; versionIndex < contents.length(); ++versionIndex)
|
||||||
|
{
|
||||||
|
if (!Character.isWhitespace(contents.codePointAt(versionIndex)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (versionIndex < contents.length()) {
|
||||||
|
if (contents.codePointAt(versionIndex) == '#') {
|
||||||
|
final String versionAnnotation = "#version ";
|
||||||
|
|
||||||
|
if (contents.regionMatches(
|
||||||
|
versionIndex,
|
||||||
|
versionAnnotation,
|
||||||
|
0,
|
||||||
|
versionAnnotation.length()
|
||||||
|
)) {
|
||||||
|
contents = contents.substring(
|
||||||
|
versionIndex
|
||||||
|
+ versionAnnotation.length()
|
||||||
|
+ "120".length()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.OpenGLObjectTracker;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.attributes.Attribute;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.uniforms.Uniform;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
|
||||||
|
public class Program implements OpenGLDeletable {
|
||||||
|
|
||||||
|
private int handle;
|
||||||
|
|
||||||
|
public Program(Shader vertexShader, Shader fragmentShader) {
|
||||||
|
handle = glCreateProgram();
|
||||||
|
OpenGLObjectTracker.register(this);
|
||||||
|
|
||||||
|
glAttachShader(handle, vertexShader.getHandle());
|
||||||
|
glAttachShader(handle, fragmentShader.getHandle());
|
||||||
|
|
||||||
|
glLinkProgram(handle);
|
||||||
|
|
||||||
|
if (glGetProgrami(handle, GL_LINK_STATUS) == GL_FALSE) {
|
||||||
|
throw new RuntimeException("Bad program:\n" + glGetProgramInfoLog(handle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Attribute getAttribute(String name) {
|
||||||
|
return new Attribute(glGetAttribLocation(handle, name), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform getUniform(String name) {
|
||||||
|
return new Uniform(glGetUniformLocation(handle, name), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void use() {
|
||||||
|
glUseProgram(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
glDeleteProgram(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.OpenGLObjectTracker;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
|
import ru.windcorp.optica.common.resource.Resource;
|
||||||
|
import ru.windcorp.optica.common.resource.ResourceManager;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class Shader implements OpenGLDeletable {
|
||||||
|
|
||||||
|
public static enum ShaderType {
|
||||||
|
VERTEX(GL_VERTEX_SHADER),
|
||||||
|
FRAGMENT(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
private final int glCode;
|
||||||
|
|
||||||
|
private ShaderType(int glCode) {
|
||||||
|
this.glCode = glCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlCode() {
|
||||||
|
return glCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShaderType guessByResourceName(String resource) {
|
||||||
|
resource = resource.toLowerCase(Locale.ENGLISH);
|
||||||
|
|
||||||
|
if (resource.contains("vertex")) return VERTEX;
|
||||||
|
if (resource.contains("fragment")) return FRAGMENT;
|
||||||
|
if (resource.contains("vsh")) return VERTEX;
|
||||||
|
if (resource.contains("fsh")) return FRAGMENT;
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Cannot deduce shader type from resource name \"" +
|
||||||
|
resource + "\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String SHADER_ASSETS_PREFIX = "assets/shaders/";
|
||||||
|
|
||||||
|
protected static Resource getShaderResource(String name) {
|
||||||
|
return ResourceManager.getResource(SHADER_ASSETS_PREFIX + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int handle;
|
||||||
|
private final ShaderType type;
|
||||||
|
|
||||||
|
public Shader(ShaderType type, String source) {
|
||||||
|
handle = glCreateShader(type.getGlCode());
|
||||||
|
OpenGLObjectTracker.register(this);
|
||||||
|
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
|
glShaderSource(handle, source);
|
||||||
|
glCompileShader(handle);
|
||||||
|
|
||||||
|
if (glGetShaderi(handle, GL_COMPILE_STATUS) == GL_FALSE) {
|
||||||
|
System.out.println("***************** ERROR ******************");
|
||||||
|
System.out.println(source);
|
||||||
|
throw new RuntimeException("Bad shader:\n" + glGetShaderInfoLog(handle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shader(String resource) {
|
||||||
|
this(
|
||||||
|
ShaderType.guessByResourceName(resource),
|
||||||
|
getShaderResource(resource).readAsString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
glDeleteShader(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandle() {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.attributes;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
public class Attribute {
|
||||||
|
|
||||||
|
protected final int handle;
|
||||||
|
private final Program program;
|
||||||
|
|
||||||
|
public Attribute(int handle, Program program) {
|
||||||
|
if (handle < 0) {
|
||||||
|
throw new RuntimeException("Bad handle: " + handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handle = handle;
|
||||||
|
this.program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandle() {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Program getProgram() {
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeVertexArray asVertexArray() {
|
||||||
|
return new AttributeVertexArray(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.attributes;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.VertexBufferObject;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
public class AttributeVertexArray extends Attribute {
|
||||||
|
|
||||||
|
private boolean isEnabled = false;
|
||||||
|
|
||||||
|
public AttributeVertexArray(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enable() {
|
||||||
|
if (!isEnabled) {
|
||||||
|
glEnableVertexAttribArray(handle);
|
||||||
|
isEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable() {
|
||||||
|
if (isEnabled) {
|
||||||
|
glDisableVertexAttribArray(handle);
|
||||||
|
isEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(
|
||||||
|
int size, boolean normalized, int stride,
|
||||||
|
ByteBuffer pointer
|
||||||
|
) {
|
||||||
|
glVertexAttribPointer(
|
||||||
|
handle,
|
||||||
|
size, GL_BYTE, normalized, stride, pointer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(
|
||||||
|
int size, boolean normalized, int stride,
|
||||||
|
FloatBuffer pointer
|
||||||
|
) {
|
||||||
|
glVertexAttribPointer(
|
||||||
|
handle,
|
||||||
|
size, GL_FLOAT, normalized, stride, pointer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(
|
||||||
|
int size, boolean normalized, int stride,
|
||||||
|
IntBuffer pointer
|
||||||
|
) {
|
||||||
|
glVertexAttribPointer(
|
||||||
|
handle,
|
||||||
|
size, GL_INT, normalized, stride, pointer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(
|
||||||
|
int size, boolean normalized, int stride,
|
||||||
|
ShortBuffer pointer
|
||||||
|
) {
|
||||||
|
glVertexAttribPointer(
|
||||||
|
handle,
|
||||||
|
size, GL_SHORT, normalized, stride, pointer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(
|
||||||
|
int size, int type, boolean normalized, int stride,
|
||||||
|
long pointer
|
||||||
|
) {
|
||||||
|
glVertexAttribPointer(
|
||||||
|
handle,
|
||||||
|
size, type, normalized, stride, pointer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(
|
||||||
|
int size, int type, boolean normalized, int stride,
|
||||||
|
VertexBufferObject vbo, long offset
|
||||||
|
) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo.getHandle());
|
||||||
|
glVertexAttribPointer(
|
||||||
|
handle,
|
||||||
|
size, type, normalized, stride, offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
public class Uniform {
|
||||||
|
|
||||||
|
protected final int handle;
|
||||||
|
private final Program program;
|
||||||
|
|
||||||
|
public Uniform(int handle, Program program) {
|
||||||
|
if (handle < 0) {
|
||||||
|
throw new RuntimeException("Bad handle: " + handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handle = handle;
|
||||||
|
this.program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandle() {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Program getProgram() {
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform1Float as1Float() {
|
||||||
|
return new Uniform1Float(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform1Int as1Int() {
|
||||||
|
return new Uniform1Int(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform2Float as2Float() {
|
||||||
|
return new Uniform2Float(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform2Int as2Int() {
|
||||||
|
return new Uniform2Int(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform3Float as3Float() {
|
||||||
|
return new Uniform3Float(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform3Int as3Int() {
|
||||||
|
return new Uniform3Int(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform4Float as4Float() {
|
||||||
|
return new Uniform4Float(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform4Int as4Int() {
|
||||||
|
return new Uniform4Int(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform2Matrix as2Matrix() {
|
||||||
|
return new Uniform2Matrix(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform3Matrix as3Matrix() {
|
||||||
|
return new Uniform3Matrix(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uniform4Matrix as4Matrix() {
|
||||||
|
return new Uniform4Matrix(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
public class Uniform1Float extends Uniform {
|
||||||
|
|
||||||
|
public Uniform1Float(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float value) {
|
||||||
|
glUniform1f(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float[] value) {
|
||||||
|
glUniform1fv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(FloatBuffer value) {
|
||||||
|
glUniform1fv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
public class Uniform1Int extends Uniform {
|
||||||
|
|
||||||
|
public Uniform1Int(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int value) {
|
||||||
|
glUniform1i(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int[] value) {
|
||||||
|
glUniform1iv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(IntBuffer value) {
|
||||||
|
glUniform1iv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import glm.vec._2.Vec2;
|
||||||
|
|
||||||
|
public class Uniform2Float extends Uniform {
|
||||||
|
|
||||||
|
public Uniform2Float(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float x, float y) {
|
||||||
|
glUniform2f(handle, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float[] value) {
|
||||||
|
glUniform2fv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(FloatBuffer value) {
|
||||||
|
glUniform2fv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Vec2 value) {
|
||||||
|
glUniform2f(handle, value.x, value.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import glm.vec._2.i.Vec2i;
|
||||||
|
|
||||||
|
public class Uniform2Int extends Uniform {
|
||||||
|
|
||||||
|
public Uniform2Int(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int x, int y) {
|
||||||
|
glUniform2i(handle, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int[] value) {
|
||||||
|
glUniform2iv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(IntBuffer value) {
|
||||||
|
glUniform2iv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Vec2i value) {
|
||||||
|
glUniform2i(handle, value.x, value.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
public class Uniform2Matrix extends Uniform {
|
||||||
|
|
||||||
|
public Uniform2Matrix(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float[] value) {
|
||||||
|
glUniformMatrix2fv(handle, false, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(FloatBuffer value) {
|
||||||
|
glUniformMatrix2fv(handle, false, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
|
||||||
|
public class Uniform3Float extends Uniform {
|
||||||
|
|
||||||
|
public Uniform3Float(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float x, float y, float z) {
|
||||||
|
glUniform3f(handle, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float[] value) {
|
||||||
|
glUniform3fv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(FloatBuffer value) {
|
||||||
|
glUniform3fv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Vec3 value) {
|
||||||
|
glUniform3f(handle, value.x, value.y, value.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
|
||||||
|
public class Uniform3Int extends Uniform {
|
||||||
|
|
||||||
|
public Uniform3Int(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int x, int y, int z) {
|
||||||
|
glUniform3i(handle, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int[] value) {
|
||||||
|
glUniform3iv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(IntBuffer value) {
|
||||||
|
glUniform3iv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Vec3i value) {
|
||||||
|
glUniform3i(handle, value.x, value.y, value.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import glm.mat._3.Mat3;
|
||||||
|
|
||||||
|
public class Uniform3Matrix extends Uniform {
|
||||||
|
|
||||||
|
public Uniform3Matrix(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float[] value) {
|
||||||
|
glUniformMatrix3fv(handle, false, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(FloatBuffer value) {
|
||||||
|
glUniformMatrix3fv(handle, false, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final float[] BUFFER = new float[3 * 3];
|
||||||
|
|
||||||
|
public void set(Mat3 value) {
|
||||||
|
glUniformMatrix3fv(handle, false, value.toFa(BUFFER));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import glm.vec._4.Vec4;
|
||||||
|
|
||||||
|
public class Uniform4Float extends Uniform {
|
||||||
|
|
||||||
|
public Uniform4Float(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float x, float y, float z, float w) {
|
||||||
|
glUniform4f(handle, x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float[] value) {
|
||||||
|
glUniform4fv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(FloatBuffer value) {
|
||||||
|
glUniform4fv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Vec4 value) {
|
||||||
|
glUniform4f(handle, value.x, value.y, value.z, value.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import glm.vec._4.i.Vec4i;
|
||||||
|
|
||||||
|
public class Uniform4Int extends Uniform {
|
||||||
|
|
||||||
|
public Uniform4Int(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int x, int y, int z, int w) {
|
||||||
|
glUniform4i(handle, x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int[] value) {
|
||||||
|
glUniform4iv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(IntBuffer value) {
|
||||||
|
glUniform4iv(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Vec4i value) {
|
||||||
|
glUniform4i(handle, value.x, value.y, value.z, value.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
|
||||||
|
public class Uniform4Matrix extends Uniform {
|
||||||
|
|
||||||
|
public Uniform4Matrix(int handle, Program program) {
|
||||||
|
super(handle, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float[] value) {
|
||||||
|
glUniformMatrix4fv(handle, false, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(FloatBuffer value) {
|
||||||
|
glUniformMatrix4fv(handle, false, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final float[] BUFFER = new float[4 * 4];
|
||||||
|
|
||||||
|
public void set(Mat4 value) {
|
||||||
|
glUniformMatrix4fv(handle, false, value.toFa(BUFFER));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.input;
|
||||||
|
|
||||||
|
import glm.vec._2.d.Vec2d;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.GraphicsInterface;
|
||||||
|
|
||||||
|
public abstract class CursorEvent extends InputEvent {
|
||||||
|
|
||||||
|
public double getCursorX() {
|
||||||
|
return GraphicsInterface.getCursorX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCursorY() {
|
||||||
|
return GraphicsInterface.getCursorY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec2d getCursorPosition() {
|
||||||
|
return GraphicsInterface.getCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract CursorEvent snapshot();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.input;
|
||||||
|
|
||||||
|
import glm.vec._2.Vec2;
|
||||||
|
import glm.vec._2.d.Vec2d;
|
||||||
|
|
||||||
|
public class CursorMoveEvent extends CursorEvent {
|
||||||
|
|
||||||
|
private final Vec2d newPosition = new Vec2d();
|
||||||
|
|
||||||
|
protected CursorMoveEvent(double newX, double newY) {
|
||||||
|
newPosition.set(newX, newY);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CursorMoveEvent(Vec2d newPos) {
|
||||||
|
newPosition.set(newPos.x, newPos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCursorX() {
|
||||||
|
return getCursorPosition().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCursorY() {
|
||||||
|
return getCursorPosition().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec2d getCursorPosition() {
|
||||||
|
return getNewPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getNewX() {
|
||||||
|
return getNewPosition().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getNewY() {
|
||||||
|
return getNewPosition().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec2d getNewPosition() {
|
||||||
|
return newPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPreviousX() {
|
||||||
|
return getPreviousPosition().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPreviousY() {
|
||||||
|
return getPreviousPosition().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec2d getPreviousPosition() {
|
||||||
|
return super.getCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getChangeX() {
|
||||||
|
return getNewX() - getPreviousX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getChangeY() {
|
||||||
|
return getNewY() - getPreviousY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec2 getChange(Vec2 result) {
|
||||||
|
return result.set(getChangeX(), getChangeY());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CursorMoveEvent() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CursorMoveEvent snapshot() {
|
||||||
|
return new StaticMouseMoveEvent(
|
||||||
|
getPreviousPosition(),
|
||||||
|
getNewPosition(),
|
||||||
|
getTime()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StaticMouseMoveEvent extends CursorMoveEvent {
|
||||||
|
|
||||||
|
private final double time;
|
||||||
|
private final Vec2d previousPosition = new Vec2d();
|
||||||
|
|
||||||
|
public StaticMouseMoveEvent(
|
||||||
|
Vec2d previousPosition,
|
||||||
|
Vec2d newPosition,
|
||||||
|
double time
|
||||||
|
) {
|
||||||
|
super(newPosition);
|
||||||
|
this.previousPosition.set(previousPosition.x, previousPosition.y);
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec2d getPreviousPosition() {
|
||||||
|
return previousPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CursorMoveEvent snapshot() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.input;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.GraphicsInterface;
|
||||||
|
|
||||||
|
public abstract class InputEvent {
|
||||||
|
|
||||||
|
public double getTime() {
|
||||||
|
return GraphicsInterface.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract InputEvent snapshot();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.input;
|
||||||
|
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
public class KeyEvent extends InputEvent {
|
||||||
|
|
||||||
|
protected int key;
|
||||||
|
protected int scancode;
|
||||||
|
protected int action;
|
||||||
|
protected int mods;
|
||||||
|
|
||||||
|
protected KeyEvent(int key, int scancode, int action, int mods) {
|
||||||
|
this();
|
||||||
|
this.key = key;
|
||||||
|
this.scancode = scancode;
|
||||||
|
this.action = action;
|
||||||
|
this.mods = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeyEvent() {}
|
||||||
|
|
||||||
|
public int getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScancode() {
|
||||||
|
return scancode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPress() {
|
||||||
|
return action == GLFW.GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRelease() {
|
||||||
|
return action == GLFW.GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRepeat() {
|
||||||
|
return action == GLFW.GLFW_REPEAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMods() {
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputEvent snapshot() {
|
||||||
|
return new StaticKeyEvent(key, scancode, action, mods, getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StaticKeyEvent extends KeyEvent {
|
||||||
|
|
||||||
|
private final double time;
|
||||||
|
|
||||||
|
public StaticKeyEvent(
|
||||||
|
int key, int scancode, int action, int mods,
|
||||||
|
double time
|
||||||
|
) {
|
||||||
|
super(key, scancode, action, mods);
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputEvent snapshot() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.google.common.primitives.Booleans;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
|
||||||
|
public abstract class DynamicModel extends Model {
|
||||||
|
|
||||||
|
private static final Mat4 IDENTITY = new Mat4();
|
||||||
|
|
||||||
|
private final Mat4[] transforms;
|
||||||
|
private final boolean[] dynamics;
|
||||||
|
|
||||||
|
public DynamicModel(
|
||||||
|
WorldRenderable[] parts,
|
||||||
|
Mat4[] transforms,
|
||||||
|
boolean[] dynamic
|
||||||
|
) {
|
||||||
|
super(parts);
|
||||||
|
this.transforms = transforms;
|
||||||
|
this.dynamics = dynamic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DynamicModel(Builder builder) {
|
||||||
|
this(
|
||||||
|
builder.getParts(),
|
||||||
|
builder.getTransforms(),
|
||||||
|
builder.getDynamics()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Mat4 getTransform(int shapeIndex) {
|
||||||
|
Mat4 transform = transforms[shapeIndex];
|
||||||
|
|
||||||
|
if (dynamics[shapeIndex]) {
|
||||||
|
transform.identity();
|
||||||
|
getDynamicTransform(shapeIndex, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void getDynamicTransform(int shapeIndex, Mat4 result);
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private final List<WorldRenderable> parts = new ArrayList<>();
|
||||||
|
private final List<Mat4> transforms = new ArrayList<>();
|
||||||
|
private final List<Boolean> dynamics = new ArrayList<>();
|
||||||
|
|
||||||
|
protected Builder() {}
|
||||||
|
|
||||||
|
private Builder addPart(
|
||||||
|
WorldRenderable part,
|
||||||
|
Mat4 transform,
|
||||||
|
boolean isDynamic
|
||||||
|
) {
|
||||||
|
parts.add(Objects.requireNonNull(part, "part"));
|
||||||
|
transforms.add(Objects.requireNonNull(transform, "transform"));
|
||||||
|
dynamics.add(isDynamic);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addStaticPart(
|
||||||
|
WorldRenderable part,
|
||||||
|
Mat4 transform
|
||||||
|
) {
|
||||||
|
return addPart(part, new Mat4(transform), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addDynamicPart(
|
||||||
|
WorldRenderable part
|
||||||
|
) {
|
||||||
|
return addPart(part, new Mat4(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addStaticPart(
|
||||||
|
WorldRenderable part
|
||||||
|
) {
|
||||||
|
return addStaticPart(part, IDENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorldRenderable[] getParts() {
|
||||||
|
return parts.toArray(new WorldRenderable[parts.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mat4[] getTransforms() {
|
||||||
|
return transforms.toArray(new Mat4[transforms.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean[] getDynamics() {
|
||||||
|
return Booleans.toArray(dynamics);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
|
||||||
|
public class EmptyModel extends Model {
|
||||||
|
|
||||||
|
private static final EmptyModel INSTANCE = new EmptyModel();
|
||||||
|
|
||||||
|
private EmptyModel() {
|
||||||
|
super(new WorldRenderable[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EmptyModel getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(WorldRenderer renderer) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Mat4 getTransform(int shapeIndex) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
299
src/main/java/ru/windcorp/optica/client/graphics/model/Face.java
Normal file
299
src/main/java/ru/windcorp/optica/client/graphics/model/Face.java
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
|
||||||
|
public class Face {
|
||||||
|
|
||||||
|
private static final ShortBuffer GENERATE_SUCCESSIVE_LATER = null;
|
||||||
|
|
||||||
|
private Shape shape = null;
|
||||||
|
int locationOfIndices;
|
||||||
|
int locationOfVertices;
|
||||||
|
|
||||||
|
private Texture texture;
|
||||||
|
|
||||||
|
ByteBuffer vertices;
|
||||||
|
private boolean verticesUpdated = true;
|
||||||
|
|
||||||
|
private ShortBuffer userIndices;
|
||||||
|
private boolean userIndicesUpdated = true;
|
||||||
|
|
||||||
|
public Face(
|
||||||
|
Texture texture,
|
||||||
|
ByteBuffer vertices,
|
||||||
|
ShortBuffer indices
|
||||||
|
) {
|
||||||
|
setTexture(texture);
|
||||||
|
setVertices(vertices);
|
||||||
|
setIndices(indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Face(
|
||||||
|
Texture texture,
|
||||||
|
ByteBuffer vertices
|
||||||
|
) {
|
||||||
|
this(texture, vertices, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShape(Shape shape) {
|
||||||
|
this.shape = shape;
|
||||||
|
|
||||||
|
checkVertices();
|
||||||
|
checkIndices();
|
||||||
|
}
|
||||||
|
|
||||||
|
void computeNormals() {
|
||||||
|
Vec3 a = new Vec3();
|
||||||
|
Vec3 b = new Vec3();
|
||||||
|
Vec3 c = new Vec3();
|
||||||
|
Vec3 normal = new Vec3();
|
||||||
|
|
||||||
|
for (int i = 0; i < getIndexCount(); i += 3) {
|
||||||
|
int indexA = getIndex(i + 0);
|
||||||
|
int indexB = getIndex(i + 1);
|
||||||
|
int indexC = getIndex(i + 2);
|
||||||
|
|
||||||
|
loadVertexPosition(indexA, a);
|
||||||
|
loadVertexPosition(indexB, b);
|
||||||
|
loadVertexPosition(indexC, c);
|
||||||
|
|
||||||
|
computeOneNormal(a, b, c, normal);
|
||||||
|
|
||||||
|
saveVertexNormal(indexA, normal);
|
||||||
|
saveVertexNormal(indexB, normal);
|
||||||
|
saveVertexNormal(indexC, normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeOneNormal(
|
||||||
|
Vec3 a, Vec3 b, Vec3 c,
|
||||||
|
Vec3 normal
|
||||||
|
) {
|
||||||
|
b.sub(a);
|
||||||
|
c.sub(a);
|
||||||
|
b.cross(c, normal);
|
||||||
|
normal.normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkVertices() {
|
||||||
|
if (vertices.remaining() % getBytesPerVertex() != 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid vertex buffer: " +
|
||||||
|
(vertices.remaining() % getBytesPerVertex()) +
|
||||||
|
" extra bytes after last vertex"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIndices() {
|
||||||
|
if (userIndices != GENERATE_SUCCESSIVE_LATER) {
|
||||||
|
if (userIndices.remaining() % 3 != 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid vertex indices: " +
|
||||||
|
(userIndices.remaining() % 3) +
|
||||||
|
" extra indices after last triangle"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
userIndices.mark();
|
||||||
|
int vertexCount = getVertexCount();
|
||||||
|
|
||||||
|
while (userIndices.hasRemaining()) {
|
||||||
|
short index = userIndices.get();
|
||||||
|
if (index < 0 || index >= vertexCount) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid vertex index " + index +
|
||||||
|
" (" + vertexCount + " vertices available)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userIndices.reset();
|
||||||
|
} else {
|
||||||
|
if (getVertexCount() % 3 != 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid vertices: " +
|
||||||
|
(getVertexCount() % 3) +
|
||||||
|
" extra indices after last triangle " +
|
||||||
|
"(indices are automatic)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean needsVerticesUpdate() {
|
||||||
|
return verticesUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markForIndexUpdate() {
|
||||||
|
if (shape != null) checkIndices();
|
||||||
|
markShapeForReassembly();
|
||||||
|
userIndicesUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean needsIndicesUpdate() {
|
||||||
|
return userIndicesUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetUpdateFlags() {
|
||||||
|
verticesUpdated = false;
|
||||||
|
userIndicesUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markShapeForReassembly() {
|
||||||
|
if (shape != null) {
|
||||||
|
shape.markForReassembly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVertexCount() {
|
||||||
|
return vertices.remaining() / getBytesPerVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getBytesPerVertex() {
|
||||||
|
return shape.getProgram().getBytesPerVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getVertices() {
|
||||||
|
return vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadVertexPosition(int index, Vec3 result) {
|
||||||
|
int offset = vertices.position() + index * getBytesPerVertex();
|
||||||
|
|
||||||
|
result.set(
|
||||||
|
vertices.getFloat(offset + 0 * Float.BYTES),
|
||||||
|
vertices.getFloat(offset + 1 * Float.BYTES),
|
||||||
|
vertices.getFloat(offset + 2 * Float.BYTES)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveVertexNormal(int index, Vec3 normal) {
|
||||||
|
int offset = vertices.position() + index * getBytesPerVertex() + (
|
||||||
|
3 * Float.BYTES +
|
||||||
|
3 * Float.BYTES +
|
||||||
|
2 * Float.BYTES
|
||||||
|
);
|
||||||
|
|
||||||
|
vertices.putFloat(offset + 0 * Float.BYTES, normal.x);
|
||||||
|
vertices.putFloat(offset + 1 * Float.BYTES, normal.y);
|
||||||
|
vertices.putFloat(offset + 2 * Float.BYTES, normal.z);
|
||||||
|
|
||||||
|
verticesUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Face setVertices(ByteBuffer vertices) {
|
||||||
|
this.vertices = Objects.requireNonNull(vertices, "vertices");
|
||||||
|
markShapeForReassembly();
|
||||||
|
this.verticesUpdated = true;
|
||||||
|
|
||||||
|
if (shape != null) checkVertices();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLocationOfVertices() {
|
||||||
|
return locationOfVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getByteOffsetOfVertices() {
|
||||||
|
return locationOfVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShortBuffer getIndices() {
|
||||||
|
if (userIndices == GENERATE_SUCCESSIVE_LATER) {
|
||||||
|
userIndices = generateSuccessiveIndices(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return userIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex(int i) {
|
||||||
|
if (userIndices == GENERATE_SUCCESSIVE_LATER) {
|
||||||
|
return i;
|
||||||
|
} else {
|
||||||
|
ShortBuffer indices = getIndicesOrNull();
|
||||||
|
return indices.get(indices.position() + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShortBuffer getIndicesOrNull() {
|
||||||
|
if (userIndices == GENERATE_SUCCESSIVE_LATER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return userIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndexCount() {
|
||||||
|
if (userIndices == GENERATE_SUCCESSIVE_LATER) {
|
||||||
|
return getVertexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
return userIndices.remaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Face setIndices(ShortBuffer indices) {
|
||||||
|
if (indices == null) {
|
||||||
|
indices = GENERATE_SUCCESSIVE_LATER;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.userIndices = indices;
|
||||||
|
markForIndexUpdate();
|
||||||
|
|
||||||
|
if (shape != null) checkIndices();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShortBuffer generateSuccessiveIndices(int offset) {
|
||||||
|
int vertexCount = getVertexCount();
|
||||||
|
ShortBuffer result = ShortBuffer.allocate(vertexCount);
|
||||||
|
|
||||||
|
for (short vertex = 0; vertex < vertexCount; ++vertex) {
|
||||||
|
result.put((short) (vertex + offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.flip();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLocationOfIndices() {
|
||||||
|
return locationOfIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getByteOffsetOfIndices() {
|
||||||
|
return locationOfIndices * Short.BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Texture getTexture() {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexture(Texture texture) {
|
||||||
|
this.texture = Objects.requireNonNull(texture, "texture");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import glm.vec._2.Vec2;
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.ShapeRenderProgram.VertexBuilder;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.optica.common.block.BlockFace;
|
||||||
|
|
||||||
|
public class Faces {
|
||||||
|
|
||||||
|
private Faces() {}
|
||||||
|
|
||||||
|
public static Face createRectangle(
|
||||||
|
Texture texture,
|
||||||
|
Vec3 colorMultiplier,
|
||||||
|
Vec3 origin,
|
||||||
|
Vec3 width,
|
||||||
|
Vec3 height
|
||||||
|
) {
|
||||||
|
VertexBuilder builder = new VertexBuilder();
|
||||||
|
|
||||||
|
Vec3 pos = new Vec3();
|
||||||
|
Vec2 texCoords = new Vec2();
|
||||||
|
|
||||||
|
builder.addVertex(
|
||||||
|
origin,
|
||||||
|
colorMultiplier,
|
||||||
|
texCoords.set(0, 0)
|
||||||
|
).addVertex(
|
||||||
|
pos.set(origin).add(height),
|
||||||
|
colorMultiplier,
|
||||||
|
texCoords.set(0, 1)
|
||||||
|
).addVertex(
|
||||||
|
pos.set(origin).add(width),
|
||||||
|
colorMultiplier,
|
||||||
|
texCoords.set(1, 0)
|
||||||
|
).addVertex(
|
||||||
|
pos.add(height),
|
||||||
|
colorMultiplier,
|
||||||
|
texCoords.set(1, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Face(
|
||||||
|
texture,
|
||||||
|
builder.assemble(),
|
||||||
|
ShortBuffer.wrap(new short[] {
|
||||||
|
3, 1, 0,
|
||||||
|
2, 3, 0
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Face createBlockFace(
|
||||||
|
Texture texture,
|
||||||
|
Vec3 colorMultiplier,
|
||||||
|
Vec3 blockCenter,
|
||||||
|
BlockFace face
|
||||||
|
) {
|
||||||
|
switch (face) {
|
||||||
|
case TOP:
|
||||||
|
return createRectangle(
|
||||||
|
texture, colorMultiplier,
|
||||||
|
blockCenter.add(-0.5f, +0.5f, +0.5f),
|
||||||
|
new Vec3( 0, -1, 0),
|
||||||
|
new Vec3(+1, 0, 0)
|
||||||
|
);
|
||||||
|
case BOTTOM:
|
||||||
|
return createRectangle(
|
||||||
|
texture, colorMultiplier,
|
||||||
|
blockCenter.add(-0.5f, -0.5f, -0.5f),
|
||||||
|
new Vec3( 0, +1, 0),
|
||||||
|
new Vec3(+1, 0, 0)
|
||||||
|
);
|
||||||
|
case NORTH:
|
||||||
|
return createRectangle(
|
||||||
|
texture, colorMultiplier,
|
||||||
|
blockCenter.add(+0.5f, -0.5f, -0.5f),
|
||||||
|
new Vec3( 0, +1, 0),
|
||||||
|
new Vec3( 0, 0, +1)
|
||||||
|
);
|
||||||
|
case SOUTH:
|
||||||
|
return createRectangle(
|
||||||
|
texture, colorMultiplier,
|
||||||
|
blockCenter.add(-0.5f, +0.5f, -0.5f),
|
||||||
|
new Vec3( 0, -1, 0),
|
||||||
|
new Vec3( 0, 0, +1)
|
||||||
|
);
|
||||||
|
case EAST:
|
||||||
|
return createRectangle(
|
||||||
|
texture, colorMultiplier,
|
||||||
|
blockCenter.add(-0.5f, -0.5f, -0.5f),
|
||||||
|
new Vec3(+1, 0, 0),
|
||||||
|
new Vec3( 0, 0, +1)
|
||||||
|
);
|
||||||
|
case WEST:
|
||||||
|
return createRectangle(
|
||||||
|
texture, colorMultiplier,
|
||||||
|
blockCenter.add(+0.5f, +0.5f, -0.5f),
|
||||||
|
new Vec3(-1, 0, 0),
|
||||||
|
new Vec3( 0, 0, +1)
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw new NullPointerException("face");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
|
||||||
|
public abstract class Model implements WorldRenderable {
|
||||||
|
|
||||||
|
private final WorldRenderable[] parts;
|
||||||
|
|
||||||
|
public Model(WorldRenderable[] parts) {
|
||||||
|
this.parts = parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Mat4 getTransform(int partIndex);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(WorldRenderer renderer) {
|
||||||
|
for (int i = 0; i < parts.length; ++i) {
|
||||||
|
WorldRenderable part = parts[i];
|
||||||
|
Mat4 transform = getTransform(i);
|
||||||
|
|
||||||
|
try {
|
||||||
|
renderer.pushWorldTransform().mul(transform);
|
||||||
|
part.render(renderer);
|
||||||
|
} finally {
|
||||||
|
renderer.popWorldTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,199 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.Usage;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.VertexBufferObject;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
|
||||||
|
public class Shape implements WorldRenderable {
|
||||||
|
|
||||||
|
private final ShapeRenderProgram program;
|
||||||
|
private final Face[] faces;
|
||||||
|
private final Usage usage;
|
||||||
|
|
||||||
|
private ByteBuffer vertices;
|
||||||
|
private ShortBuffer indices;
|
||||||
|
|
||||||
|
private boolean initialized = false;
|
||||||
|
private boolean needsAssembly = true;
|
||||||
|
private boolean needsVBOUpdate = true;
|
||||||
|
|
||||||
|
private VertexBufferObject verticesVbo;
|
||||||
|
private VertexBufferObject indicesVbo;
|
||||||
|
|
||||||
|
public Shape(Usage usage, ShapeRenderProgram program, Face... faces) {
|
||||||
|
this.program = program;
|
||||||
|
this.faces = faces;
|
||||||
|
this.usage = usage;
|
||||||
|
|
||||||
|
configureFaces();
|
||||||
|
|
||||||
|
assembleBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape(Usage usage, Face... faces) {
|
||||||
|
this(usage, ShapeRenderProgram.getDefault(), faces);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureFaces() {
|
||||||
|
for (Face face : faces) {
|
||||||
|
face.setShape(this);
|
||||||
|
face.computeNormals();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assembleBuffers() {
|
||||||
|
// TODO optimize: only update faces that requested it
|
||||||
|
|
||||||
|
resizeBuffers();
|
||||||
|
|
||||||
|
for (Face face : faces) {
|
||||||
|
assembleVertices(face);
|
||||||
|
assembleIndices(face);
|
||||||
|
face.resetUpdateFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.vertices.flip();
|
||||||
|
this.indices.flip();
|
||||||
|
|
||||||
|
needsAssembly = false;
|
||||||
|
needsVBOUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resizeBuffers() {
|
||||||
|
int verticesRequired = 0, indicesRequired = 0;
|
||||||
|
for (Face face : faces) {
|
||||||
|
verticesRequired += face.getVertices().remaining();
|
||||||
|
indicesRequired += face.getIndices().remaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.vertices == null || vertices.capacity() < verticesRequired) {
|
||||||
|
this.vertices = BufferUtils.createByteBuffer(verticesRequired);
|
||||||
|
} else {
|
||||||
|
this.vertices.position(0).limit(verticesRequired);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.indices == null || this.indices.capacity() < indicesRequired) {
|
||||||
|
this.indices = BufferUtils.createShortBuffer(indicesRequired);
|
||||||
|
} else {
|
||||||
|
this.indices.position(0).limit(indicesRequired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assembleVertices(Face face) {
|
||||||
|
face.locationOfVertices = this.vertices.position();
|
||||||
|
|
||||||
|
insertVertices(face);
|
||||||
|
linkVerticesWith(face);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertVertices(Face face) {
|
||||||
|
ByteBuffer faceVertices = face.getVertices();
|
||||||
|
|
||||||
|
faceVertices.mark();
|
||||||
|
this.vertices.put(faceVertices);
|
||||||
|
faceVertices.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void linkVerticesWith(Face face) {
|
||||||
|
int limit = vertices.limit();
|
||||||
|
int position = vertices.position();
|
||||||
|
|
||||||
|
vertices.limit(position).position(face.getLocationOfVertices());
|
||||||
|
face.vertices = vertices.slice();
|
||||||
|
|
||||||
|
vertices.position(position).limit(limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assembleIndices(Face face) {
|
||||||
|
short vertexOffset = (short) (
|
||||||
|
face.getLocationOfVertices() / program.getBytesPerVertex()
|
||||||
|
);
|
||||||
|
|
||||||
|
face.locationOfIndices = indices.position();
|
||||||
|
|
||||||
|
ShortBuffer faceIndices = face.getIndices();
|
||||||
|
|
||||||
|
if (faceIndices == null) {
|
||||||
|
for (int i = 0; i < face.getVertexCount(); ++i) {
|
||||||
|
this.indices.put((short) (vertexOffset + i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = faceIndices.position(); i < faceIndices.limit(); ++i) {
|
||||||
|
short faceIndex = faceIndices.get(i);
|
||||||
|
faceIndex += vertexOffset;
|
||||||
|
this.indices.put(faceIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void markForReassembly() {
|
||||||
|
needsAssembly = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(WorldRenderer renderer) {
|
||||||
|
if (!initialized) initialize();
|
||||||
|
if (needsAssembly) assembleBuffers();
|
||||||
|
if (needsVBOUpdate) updateVBO();
|
||||||
|
|
||||||
|
program.render(renderer, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() {
|
||||||
|
verticesVbo = new VertexBufferObject(usage);
|
||||||
|
indicesVbo = new VertexBufferObject(usage);
|
||||||
|
needsVBOUpdate = true;
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVBO() {
|
||||||
|
verticesVbo.setData(vertices);
|
||||||
|
indicesVbo.setData(indices);
|
||||||
|
|
||||||
|
needsVBOUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexBufferObject getVerticesVbo() {
|
||||||
|
return verticesVbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexBufferObject getIndicesVbo() {
|
||||||
|
return indicesVbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapeRenderProgram getProgram() {
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Face[] getFaces() {
|
||||||
|
return faces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Usage getUsage() {
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,298 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import com.google.common.collect.ObjectArrays;
|
||||||
|
|
||||||
|
import glm.vec._2.Vec2;
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.VertexBufferObject;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.VertexBufferObject.BindTarget;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.CombinedShader;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.Program;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.attributes.AttributeVertexArray;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.uniforms.Uniform1Int;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.uniforms.Uniform2Float;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.shaders.uniforms.Uniform4Matrix;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Sprite;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
|
||||||
|
public class ShapeRenderProgram extends Program {
|
||||||
|
|
||||||
|
private static ShapeRenderProgram def = null;
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
def = new ShapeRenderProgram(
|
||||||
|
new String[] {"WorldDefault.vertex.glsl"},
|
||||||
|
new String[] {"WorldDefault.fragment.glsl"}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShapeRenderProgram getDefault() {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int DEFAULT_BYTES_PER_VERTEX =
|
||||||
|
3 * Float.BYTES + // Position
|
||||||
|
3 * Float.BYTES + // Color multiplier
|
||||||
|
2 * Float.BYTES + // Texture coordinates
|
||||||
|
3 * Float.BYTES; // Normals
|
||||||
|
|
||||||
|
private static final String SHAPE_VERTEX_SHADER_RESOURCE =
|
||||||
|
"Shape.vertex.glsl";
|
||||||
|
private static final String SHAPE_FRAGMENT_SHADER_RESOURCE =
|
||||||
|
"Shape.fragment.glsl";
|
||||||
|
|
||||||
|
private static final String
|
||||||
|
FINAL_TRANSFORM_UNIFORM_NAME = "finalTransform",
|
||||||
|
WORLD_TRANSFORM_UNIFORM_NAME = "worldTransform",
|
||||||
|
POSITIONS_ATTRIBUTE_NAME = "inputPositions",
|
||||||
|
COLOR_MULTIPLER_ATTRIBUTE_NAME = "inputColorMultiplier",
|
||||||
|
TEXTURE_COORDS_ATTRIBUTE_NAME = "inputTextureCoords",
|
||||||
|
TEXTURE_SLOT_UNIFORM_NAME = "textureSlot",
|
||||||
|
TEXTURE_START_UNIFORM_NAME = "textureStart",
|
||||||
|
TEXTURE_SIZE_UNIFORM_NAME = "textureSize",
|
||||||
|
NORMALS_ATTRIBUTE_NAME = "inputNormals";
|
||||||
|
|
||||||
|
private final Uniform4Matrix finalTransformUniform;
|
||||||
|
private final Uniform4Matrix worldTransformUniform;
|
||||||
|
private final AttributeVertexArray positionsAttribute;
|
||||||
|
private final AttributeVertexArray colorsAttribute;
|
||||||
|
private final AttributeVertexArray textureCoordsAttribute;
|
||||||
|
private final Uniform1Int textureSlotUniform;
|
||||||
|
private final Uniform2Float textureStartUniform;
|
||||||
|
private final Uniform2Float textureSizeUniform;
|
||||||
|
private final AttributeVertexArray normalsAttribute;
|
||||||
|
|
||||||
|
public ShapeRenderProgram(
|
||||||
|
String[] vertexShaderResources,
|
||||||
|
String[] fragmentShaderResources
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
new CombinedShader(
|
||||||
|
attachVertexShader(vertexShaderResources)
|
||||||
|
),
|
||||||
|
new CombinedShader(
|
||||||
|
attachFragmentShader(fragmentShaderResources)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.finalTransformUniform = getUniform(FINAL_TRANSFORM_UNIFORM_NAME)
|
||||||
|
.as4Matrix();
|
||||||
|
|
||||||
|
this.worldTransformUniform = getUniform(WORLD_TRANSFORM_UNIFORM_NAME)
|
||||||
|
.as4Matrix();
|
||||||
|
|
||||||
|
this.positionsAttribute =
|
||||||
|
getAttribute(POSITIONS_ATTRIBUTE_NAME).asVertexArray();
|
||||||
|
|
||||||
|
this.colorsAttribute =
|
||||||
|
getAttribute(COLOR_MULTIPLER_ATTRIBUTE_NAME).asVertexArray();
|
||||||
|
|
||||||
|
this.textureCoordsAttribute =
|
||||||
|
getAttribute(TEXTURE_COORDS_ATTRIBUTE_NAME).asVertexArray();
|
||||||
|
|
||||||
|
this.textureSlotUniform = getUniform(TEXTURE_SLOT_UNIFORM_NAME)
|
||||||
|
.as1Int();
|
||||||
|
|
||||||
|
this.textureStartUniform = getUniform(TEXTURE_START_UNIFORM_NAME)
|
||||||
|
.as2Float();
|
||||||
|
|
||||||
|
this.textureSizeUniform = getUniform(TEXTURE_SIZE_UNIFORM_NAME)
|
||||||
|
.as2Float();
|
||||||
|
|
||||||
|
this.normalsAttribute = getAttribute(NORMALS_ATTRIBUTE_NAME)
|
||||||
|
.asVertexArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] attachVertexShader(String[] others) {
|
||||||
|
return ObjectArrays.concat(SHAPE_VERTEX_SHADER_RESOURCE, others);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] attachFragmentShader(String[] others) {
|
||||||
|
return ObjectArrays.concat(SHAPE_FRAGMENT_SHADER_RESOURCE, others);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(
|
||||||
|
WorldRenderer renderer,
|
||||||
|
Shape shape
|
||||||
|
) {
|
||||||
|
use();
|
||||||
|
configure(renderer);
|
||||||
|
|
||||||
|
bindVertices(shape.getVerticesVbo());
|
||||||
|
bindIndices(shape.getIndicesVbo());
|
||||||
|
|
||||||
|
try {
|
||||||
|
positionsAttribute.enable();
|
||||||
|
colorsAttribute.enable();
|
||||||
|
textureCoordsAttribute.enable();
|
||||||
|
normalsAttribute.enable();
|
||||||
|
|
||||||
|
for (Face face : shape.getFaces()) {
|
||||||
|
renderFace(face);
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
positionsAttribute.disable();
|
||||||
|
colorsAttribute.disable();
|
||||||
|
textureCoordsAttribute.disable();
|
||||||
|
normalsAttribute.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configure(WorldRenderer renderer) {
|
||||||
|
finalTransformUniform.set(renderer.getFinalTransform());
|
||||||
|
worldTransformUniform.set(renderer.getWorldTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int bindVertices(VertexBufferObject vertices) {
|
||||||
|
int vertexStride = getBytesPerVertex();
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
positionsAttribute.set(
|
||||||
|
3, GL11.GL_FLOAT, false, vertexStride, vertices,
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
offset += 3 * Float.BYTES;
|
||||||
|
|
||||||
|
colorsAttribute.set(
|
||||||
|
3, GL11.GL_FLOAT, false, vertexStride, vertices,
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
offset += 3 * Float.BYTES;
|
||||||
|
|
||||||
|
textureCoordsAttribute.set(
|
||||||
|
2, GL11.GL_FLOAT, false, vertexStride, vertices,
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
offset += 2 * Float.BYTES;
|
||||||
|
|
||||||
|
normalsAttribute.set(
|
||||||
|
3, GL11.GL_FLOAT, false, vertexStride, vertices,
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
offset += 3 * Float.BYTES;
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void bindIndices(VertexBufferObject indices) {
|
||||||
|
indices.bind(BindTarget.ELEMENT_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderFace(Face face) {
|
||||||
|
Sprite sprite = face.getTexture().getSprite();
|
||||||
|
|
||||||
|
sprite.getPrimitive().bind(0);
|
||||||
|
textureSlotUniform.set(0);
|
||||||
|
|
||||||
|
textureStartUniform.set(sprite.getStart());
|
||||||
|
textureSizeUniform.set(sprite.getSize());
|
||||||
|
|
||||||
|
GL11.glDrawElements(
|
||||||
|
GL11.GL_TRIANGLES,
|
||||||
|
face.getIndexCount(),
|
||||||
|
GL11.GL_UNSIGNED_SHORT,
|
||||||
|
face.getByteOffsetOfIndices()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBytesPerVertex() {
|
||||||
|
return DEFAULT_BYTES_PER_VERTEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class VertexBuilder {
|
||||||
|
|
||||||
|
private static class Vertex {
|
||||||
|
final Vec3 position;
|
||||||
|
final Vec3 colorMultiplier;
|
||||||
|
final Vec2 textureCoords;
|
||||||
|
|
||||||
|
Vertex(Vec3 position, Vec3 colorMultiplier, Vec2 textureCoords) {
|
||||||
|
this.position = position;
|
||||||
|
this.colorMultiplier = colorMultiplier;
|
||||||
|
this.textureCoords = textureCoords;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<Vertex> vertices = new ArrayList<>();
|
||||||
|
|
||||||
|
public VertexBuilder addVertex(
|
||||||
|
float x, float y, float z,
|
||||||
|
float r, float g, float b,
|
||||||
|
float tx, float ty
|
||||||
|
) {
|
||||||
|
vertices.add(new Vertex(
|
||||||
|
new Vec3(x, y, z),
|
||||||
|
new Vec3(r, g, b),
|
||||||
|
new Vec2(tx, ty)
|
||||||
|
));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VertexBuilder addVertex(
|
||||||
|
Vec3 position,
|
||||||
|
Vec3 colorMultiplier,
|
||||||
|
Vec2 textureCoords
|
||||||
|
) {
|
||||||
|
vertices.add(new Vertex(
|
||||||
|
new Vec3(position),
|
||||||
|
new Vec3(colorMultiplier),
|
||||||
|
new Vec2(textureCoords)
|
||||||
|
));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer assemble() {
|
||||||
|
ByteBuffer result = BufferUtils.createByteBuffer(
|
||||||
|
DEFAULT_BYTES_PER_VERTEX * vertices.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
for (Vertex v : vertices) {
|
||||||
|
result
|
||||||
|
.putFloat(v.position.x)
|
||||||
|
.putFloat(v.position.y)
|
||||||
|
.putFloat(v.position.z)
|
||||||
|
.putFloat(v.colorMultiplier.x)
|
||||||
|
.putFloat(v.colorMultiplier.y)
|
||||||
|
.putFloat(v.colorMultiplier.z)
|
||||||
|
.putFloat(v.textureCoords.x)
|
||||||
|
.putFloat(v.textureCoords.y)
|
||||||
|
.putFloat(Float.NaN)
|
||||||
|
.putFloat(Float.NaN)
|
||||||
|
.putFloat(Float.NaN);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.flip();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,218 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.Usage;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
|
||||||
|
public class Shapes {
|
||||||
|
|
||||||
|
public static Shape createParallelepiped( // Try saying that 10 times fast
|
||||||
|
Vec3 origin,
|
||||||
|
|
||||||
|
Vec3 width,
|
||||||
|
Vec3 height,
|
||||||
|
Vec3 depth,
|
||||||
|
|
||||||
|
Vec3 colorMultiplier,
|
||||||
|
|
||||||
|
Texture topTexture,
|
||||||
|
Texture bottomTexture,
|
||||||
|
Texture northTexture,
|
||||||
|
Texture southTexture,
|
||||||
|
Texture eastTexture,
|
||||||
|
Texture westTexture
|
||||||
|
) {
|
||||||
|
|
||||||
|
Vec3 faceOrigin = new Vec3();
|
||||||
|
Vec3 faceWidth = new Vec3();
|
||||||
|
|
||||||
|
Face top = Faces.createRectangle(
|
||||||
|
topTexture, colorMultiplier,
|
||||||
|
faceOrigin.set(origin).add(height).add(width),
|
||||||
|
faceWidth.set(width).negate(),
|
||||||
|
depth
|
||||||
|
);
|
||||||
|
|
||||||
|
Face bottom = Faces.createRectangle(
|
||||||
|
bottomTexture, colorMultiplier,
|
||||||
|
origin,
|
||||||
|
width,
|
||||||
|
depth
|
||||||
|
);
|
||||||
|
|
||||||
|
Face north = Faces.createRectangle(
|
||||||
|
northTexture, colorMultiplier,
|
||||||
|
faceOrigin.set(origin).add(depth),
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
|
||||||
|
Face south = Faces.createRectangle(
|
||||||
|
southTexture, colorMultiplier,
|
||||||
|
faceOrigin.set(origin).add(width),
|
||||||
|
faceWidth.set(width).negate(),
|
||||||
|
height
|
||||||
|
);
|
||||||
|
|
||||||
|
Face east = Faces.createRectangle(
|
||||||
|
eastTexture, colorMultiplier,
|
||||||
|
origin,
|
||||||
|
depth,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
|
||||||
|
Face west = Faces.createRectangle(
|
||||||
|
westTexture, colorMultiplier,
|
||||||
|
faceOrigin.set(origin).add(width).add(depth),
|
||||||
|
faceWidth.set(depth).negate(),
|
||||||
|
height
|
||||||
|
);
|
||||||
|
|
||||||
|
Shape result = new Shape(
|
||||||
|
Usage.STATIC,
|
||||||
|
top, bottom, north, south, east, west
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PppBuilder {
|
||||||
|
|
||||||
|
private final Vec3 origin = new Vec3(-0.5f, -0.5f, -0.5f);
|
||||||
|
|
||||||
|
private final Vec3 depth = new Vec3(1, 0, 0);
|
||||||
|
private final Vec3 width = new Vec3(0, 1, 0);
|
||||||
|
private final Vec3 height = new Vec3(0, 0, 1);
|
||||||
|
|
||||||
|
private final Vec3 colorMultiplier = new Vec3(1, 1, 1);
|
||||||
|
|
||||||
|
private final Texture topTexture;
|
||||||
|
private final Texture bottomTexture;
|
||||||
|
private final Texture northTexture;
|
||||||
|
private final Texture southTexture;
|
||||||
|
private final Texture eastTexture;
|
||||||
|
private final Texture westTexture;
|
||||||
|
|
||||||
|
public PppBuilder(
|
||||||
|
Texture top,
|
||||||
|
Texture bottom,
|
||||||
|
Texture north,
|
||||||
|
Texture south,
|
||||||
|
Texture east,
|
||||||
|
Texture west
|
||||||
|
) {
|
||||||
|
this.topTexture = top;
|
||||||
|
this.bottomTexture = bottom;
|
||||||
|
this.northTexture = north;
|
||||||
|
this.southTexture = south;
|
||||||
|
this.eastTexture = east;
|
||||||
|
this.westTexture = west;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder(Texture texture) {
|
||||||
|
this(texture, texture, texture, texture, texture, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setOrigin(Vec3 origin) {
|
||||||
|
this.origin.set(origin);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setOrigin(float x, float y, float z) {
|
||||||
|
this.origin.set(x, y, z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setColorMultiplier(Vec3 colorMultiplier) {
|
||||||
|
this.colorMultiplier.set(colorMultiplier);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setColorMultiplier(float r, float g, float b) {
|
||||||
|
this.colorMultiplier.set(r, g, b);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setDepth(Vec3 vector) {
|
||||||
|
this.depth.set(vector);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setDepth(float x, float y, float z) {
|
||||||
|
this.depth.set(x, y, z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setDepth(float x) {
|
||||||
|
this.depth.set(x, 0, 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setWidth(Vec3 vector) {
|
||||||
|
this.width.set(vector);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setWidth(float x, float y, float z) {
|
||||||
|
this.width.set(x, y, z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setWidth(float y) {
|
||||||
|
this.width.set(0, y, 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setHeight(Vec3 vector) {
|
||||||
|
this.height.set(vector);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setHeight(float x, float y, float z) {
|
||||||
|
this.height.set(x, y, z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setHeight(float z) {
|
||||||
|
this.height.set(0, 0, z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder setSize(float x, float y, float z) {
|
||||||
|
return this.setWidth(x).setDepth(y).setHeight(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape create() {
|
||||||
|
return createParallelepiped(
|
||||||
|
origin,
|
||||||
|
width, height, depth,
|
||||||
|
colorMultiplier,
|
||||||
|
topTexture,
|
||||||
|
bottomTexture,
|
||||||
|
northTexture,
|
||||||
|
southTexture,
|
||||||
|
eastTexture,
|
||||||
|
westTexture
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
|
||||||
|
public class StaticModel extends Model {
|
||||||
|
|
||||||
|
private static final Mat4 IDENTITY = new Mat4();
|
||||||
|
|
||||||
|
private final Mat4[] transforms;
|
||||||
|
|
||||||
|
public StaticModel(
|
||||||
|
WorldRenderable[] parts,
|
||||||
|
Mat4[] transforms
|
||||||
|
) {
|
||||||
|
super(parts);
|
||||||
|
this.transforms = transforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StaticModel(Builder builder) {
|
||||||
|
this(builder.getParts(), builder.getTransforms());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Mat4 getTransform(int partIndex) {
|
||||||
|
return transforms[partIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private final List<WorldRenderable> parts = new ArrayList<>();
|
||||||
|
private final List<Mat4> transforms = new ArrayList<>();
|
||||||
|
|
||||||
|
protected Builder() {}
|
||||||
|
|
||||||
|
public Builder addPart(
|
||||||
|
WorldRenderable part,
|
||||||
|
Mat4 transform
|
||||||
|
) {
|
||||||
|
parts.add(Objects.requireNonNull(part, "part"));
|
||||||
|
transforms.add(Objects.requireNonNull(transform, "transform"));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addPart(
|
||||||
|
WorldRenderable part
|
||||||
|
) {
|
||||||
|
return addPart(part, IDENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorldRenderable[] getParts() {
|
||||||
|
return parts.toArray(new WorldRenderable[parts.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mat4[] getTransforms() {
|
||||||
|
return transforms.toArray(new Mat4[transforms.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.model;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
|
||||||
|
public interface WorldRenderable {
|
||||||
|
|
||||||
|
void render(WorldRenderer renderer);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.texture;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
import static org.lwjgl.opengl.GL12.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
class Pixels {
|
||||||
|
|
||||||
|
private final ByteBuffer data;
|
||||||
|
|
||||||
|
private final int bufferWidth;
|
||||||
|
private final int bufferHeight;
|
||||||
|
|
||||||
|
private final boolean filtered;
|
||||||
|
|
||||||
|
public Pixels(
|
||||||
|
ByteBuffer data,
|
||||||
|
int bufferWidth, int bufferHeight,
|
||||||
|
boolean filtered
|
||||||
|
) {
|
||||||
|
this.data = data;
|
||||||
|
this.bufferWidth = bufferWidth;
|
||||||
|
this.bufferHeight = bufferHeight;
|
||||||
|
this.filtered = filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int load() {
|
||||||
|
int handle = glGenTextures();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, handle);
|
||||||
|
|
||||||
|
if (filtered) {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
} else {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D, // Load 2D image
|
||||||
|
0, // Not mipmapped
|
||||||
|
GL_RGBA, // Use RGBA
|
||||||
|
bufferWidth, // Width
|
||||||
|
bufferHeight, // Height
|
||||||
|
0, // No border
|
||||||
|
GL_RGBA, // Use RGBA (required)
|
||||||
|
GL_UNSIGNED_BYTE, // Use unsigned bytes
|
||||||
|
data // Data buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.texture;
|
||||||
|
|
||||||
|
public class SimpleTexture extends Texture {
|
||||||
|
|
||||||
|
private final Sprite sprite;
|
||||||
|
|
||||||
|
public SimpleTexture(Sprite sprite) {
|
||||||
|
this.sprite = sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Sprite getSprite() {
|
||||||
|
return sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.texture;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import glm.vec._2.Vec2;
|
||||||
|
|
||||||
|
public class Sprite {
|
||||||
|
|
||||||
|
private static final Vec2 ORIGIN = new Vec2(0, 0);
|
||||||
|
private static final Vec2 FULL_PRIMITIVE = new Vec2(1, 1);
|
||||||
|
|
||||||
|
private final TexturePrimitive primitive;
|
||||||
|
|
||||||
|
private final Vec2 start;
|
||||||
|
private final Vec2 size;
|
||||||
|
|
||||||
|
public Sprite(TexturePrimitive primitive, Vec2 start, Vec2 size) {
|
||||||
|
this.primitive = Objects.requireNonNull(primitive, "primitive");
|
||||||
|
this.start = Objects.requireNonNull(start, "start");
|
||||||
|
this.size = Objects.requireNonNull(size, "size");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite(TexturePrimitive primitive) {
|
||||||
|
this(primitive, ORIGIN, FULL_PRIMITIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TexturePrimitive getPrimitive() {
|
||||||
|
return primitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec2 getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec2 getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.texture;
|
||||||
|
|
||||||
|
public abstract class Texture {
|
||||||
|
|
||||||
|
public abstract Sprite getSprite();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.texture;
|
||||||
|
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.color.ColorSpace;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.ComponentColorModel;
|
||||||
|
import java.awt.image.DataBuffer;
|
||||||
|
import java.awt.image.DataBufferByte;
|
||||||
|
import java.awt.image.Raster;
|
||||||
|
import java.awt.image.WritableRaster;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.RenderTaskQueue;
|
||||||
|
import ru.windcorp.optica.common.resource.Resource;
|
||||||
|
import ru.windcorp.optica.common.resource.ResourceManager;
|
||||||
|
|
||||||
|
public class TextureManager {
|
||||||
|
|
||||||
|
private static final ColorModel COLOR_MODEL = new ComponentColorModel(
|
||||||
|
ColorSpace.getInstance(ColorSpace.CS_sRGB), // Use RGB
|
||||||
|
new int[] {8, 8, 8, 8}, // Use every bit
|
||||||
|
true, // Has alpha
|
||||||
|
false, // Not premultiplied
|
||||||
|
ComponentColorModel.TRANSLUCENT, // Can have any alpha
|
||||||
|
DataBuffer.TYPE_BYTE // Alpha is one byte
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final Hashtable<?, ?> CANVAS_PROPERTIES = new Hashtable<>();
|
||||||
|
private static final java.awt.Color CANVAS_BACKGROUND =
|
||||||
|
new java.awt.Color(0, 0, 0, 0);
|
||||||
|
|
||||||
|
private static final String TEXTURE_ASSETS_PREFIX = "assets/textures/";
|
||||||
|
|
||||||
|
private static Resource getResource(String textureName) {
|
||||||
|
return ResourceManager.getResource(
|
||||||
|
TEXTURE_ASSETS_PREFIX + textureName + ".png"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TexturePrimitive load(String textureName, boolean filtered) {
|
||||||
|
TexturePrimitive result = loadToByteBuffer(textureName, filtered);
|
||||||
|
RenderTaskQueue.invokeLater(result::load);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TexturePrimitive loadToByteBuffer(
|
||||||
|
String textureName, boolean filter
|
||||||
|
) {
|
||||||
|
Resource resource = getResource(textureName);
|
||||||
|
|
||||||
|
BufferedImage source = readImage(resource);
|
||||||
|
|
||||||
|
int bufferWidth = toPowerOf2(source.getWidth()),
|
||||||
|
bufferHeight = toPowerOf2(source.getHeight());
|
||||||
|
|
||||||
|
WritableRaster raster = Raster.createInterleavedRaster(
|
||||||
|
DataBuffer.TYPE_BYTE, // Storage model
|
||||||
|
bufferWidth, // Buffer width
|
||||||
|
bufferHeight, // Buffer height
|
||||||
|
4, // RGBA
|
||||||
|
null // Location (here (0; 0))
|
||||||
|
);
|
||||||
|
|
||||||
|
BufferedImage canvas = new BufferedImage(
|
||||||
|
COLOR_MODEL, // Color model
|
||||||
|
raster, // Backing raster
|
||||||
|
false, // Raster is not premultipied
|
||||||
|
CANVAS_PROPERTIES // Properties
|
||||||
|
);
|
||||||
|
|
||||||
|
Graphics g = canvas.createGraphics();
|
||||||
|
g.setColor(CANVAS_BACKGROUND);
|
||||||
|
g.fillRect(0, 0, source.getWidth(), source.getHeight());
|
||||||
|
g.drawImage(
|
||||||
|
source,
|
||||||
|
0, 0, source.getWidth(), source.getHeight(),
|
||||||
|
0, source.getHeight(), source.getWidth(), 0, // Flip the image
|
||||||
|
null
|
||||||
|
);
|
||||||
|
g.dispose();
|
||||||
|
|
||||||
|
byte[] data = (
|
||||||
|
(DataBufferByte) canvas.getRaster().getDataBuffer()
|
||||||
|
).getData();
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(data.length);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer.put(data);
|
||||||
|
buffer.flip();
|
||||||
|
|
||||||
|
Pixels pixels = new Pixels(buffer, bufferWidth, bufferHeight, filter);
|
||||||
|
|
||||||
|
TexturePrimitive result = new TexturePrimitive(
|
||||||
|
pixels,
|
||||||
|
source.getWidth(),
|
||||||
|
source.getHeight(),
|
||||||
|
bufferWidth,
|
||||||
|
bufferHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BufferedImage readImage(Resource resource) {
|
||||||
|
try {
|
||||||
|
return ImageIO.read(resource.getInputStream());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("too bad. refresh project u stupid. must be " + resource.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int toPowerOf2(int i) {
|
||||||
|
|
||||||
|
// TODO optimize
|
||||||
|
|
||||||
|
int result = 1;
|
||||||
|
do {
|
||||||
|
result *= 2;
|
||||||
|
} while (result < i);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.texture;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.OpenGLObjectTracker;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
|
|
||||||
|
public class TexturePrimitive implements OpenGLDeletable {
|
||||||
|
|
||||||
|
private static final int NOT_LOADED = -1;
|
||||||
|
|
||||||
|
private int handle = NOT_LOADED;
|
||||||
|
private Pixels pixelsToLoad;
|
||||||
|
|
||||||
|
private final int width;
|
||||||
|
private final int height;
|
||||||
|
private final int bufferWidth;
|
||||||
|
private final int bufferHeight;
|
||||||
|
|
||||||
|
protected TexturePrimitive(
|
||||||
|
Pixels pixels,
|
||||||
|
int width, int height,
|
||||||
|
int bufferWidth, int bufferHeight
|
||||||
|
) {
|
||||||
|
this.pixelsToLoad = pixels;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.bufferWidth = bufferWidth;
|
||||||
|
this.bufferHeight = bufferHeight;
|
||||||
|
|
||||||
|
OpenGLObjectTracker.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBufferWidth() {
|
||||||
|
return bufferWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBufferHeight() {
|
||||||
|
return bufferHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLoaded() {
|
||||||
|
return handle != NOT_LOADED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(int slot) {
|
||||||
|
if (!isLoaded()) {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
int code = GL_TEXTURE0 + slot;
|
||||||
|
|
||||||
|
glActiveTexture(code);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void load() {
|
||||||
|
if (isLoaded()) return;
|
||||||
|
|
||||||
|
handle = pixelsToLoad.load();
|
||||||
|
|
||||||
|
if (handle < 0) {
|
||||||
|
throw new RuntimeException("oops");
|
||||||
|
}
|
||||||
|
|
||||||
|
pixelsToLoad = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
if (isLoaded())
|
||||||
|
glDeleteTextures(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.world;
|
||||||
|
|
||||||
|
import static java.lang.Math.*;
|
||||||
|
|
||||||
|
import glm.Glm;
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.GraphicsInterface;
|
||||||
|
|
||||||
|
public class Camera {
|
||||||
|
|
||||||
|
private final Vec3 position = new Vec3();
|
||||||
|
|
||||||
|
private float pitch;
|
||||||
|
private float yaw;
|
||||||
|
|
||||||
|
private float fieldOfView;
|
||||||
|
|
||||||
|
public Camera(Vec3 position, float pitch, float yaw, float fieldOfView) {
|
||||||
|
teleport(position);
|
||||||
|
setPitch(pitch);
|
||||||
|
setYaw(yaw);
|
||||||
|
setFieldOfView(fieldOfView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Camera() {}
|
||||||
|
|
||||||
|
public void apply(WorldRenderer renderer) {
|
||||||
|
Mat4 previous = renderer.getViewTransform();
|
||||||
|
Glm.perspective(
|
||||||
|
computeFovY(),
|
||||||
|
GraphicsInterface.getAspectRatio(),
|
||||||
|
0.01f, 10000.0f,
|
||||||
|
renderer.pushViewTransform()
|
||||||
|
).mul(previous);
|
||||||
|
|
||||||
|
renderer.pushViewTransform().rotateX(pitch).rotateY(yaw);
|
||||||
|
|
||||||
|
renderer.pushViewTransform().translate(position.negate());
|
||||||
|
position.negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private float computeFovY() {
|
||||||
|
float widthOverHeight = GraphicsInterface.getAspectRatio();
|
||||||
|
|
||||||
|
if (widthOverHeight >= 1) {
|
||||||
|
return fieldOfView;
|
||||||
|
} else {
|
||||||
|
return (float) (2 * atan(
|
||||||
|
1 / widthOverHeight
|
||||||
|
*
|
||||||
|
tan(fieldOfView / 2)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3 getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void teleport(Vec3 pos) {
|
||||||
|
position.set(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move(Vec3 pos) {
|
||||||
|
position.add(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPitch() {
|
||||||
|
return pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPitch(float pitch) {
|
||||||
|
final float maxPitch = (float) (Math.PI / 2);
|
||||||
|
this.pitch = Glm.clamp(pitch, -maxPitch, +maxPitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getYaw() {
|
||||||
|
return yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYaw(float yaw) {
|
||||||
|
this.yaw = Glm.mod(yaw, 2 * (float) PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirection(float pitch, float yaw) {
|
||||||
|
setPitch(pitch);
|
||||||
|
setYaw(yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turn(float pitchChange, float yawChange) {
|
||||||
|
setPitch(getPitch() + pitchChange);
|
||||||
|
setYaw(getYaw() + yawChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFieldOfView() {
|
||||||
|
return fieldOfView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldOfView(float fieldOfView) {
|
||||||
|
this.fieldOfView = fieldOfView;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.world;
|
||||||
|
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
|
||||||
|
import glm.mat._3.Mat3;
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.optica.client.graphics.Layer;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.GraphicsBackend;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.GraphicsInterface;
|
||||||
|
import ru.windcorp.optica.client.graphics.input.CursorMoveEvent;
|
||||||
|
import ru.windcorp.optica.client.graphics.input.KeyEvent;
|
||||||
|
import ru.windcorp.optica.client.world.WorldRender;
|
||||||
|
import ru.windcorp.optica.common.world.WorldData;
|
||||||
|
|
||||||
|
public class LayerWorld extends Layer {
|
||||||
|
|
||||||
|
private final Camera camera = new Camera(
|
||||||
|
new Vec3(8, 8, 8),
|
||||||
|
0, 0,
|
||||||
|
(float) Math.toRadians(70)
|
||||||
|
);
|
||||||
|
|
||||||
|
private final Vec3 velocity = new Vec3();
|
||||||
|
private final Vec3 tmp = new Vec3();
|
||||||
|
|
||||||
|
private final Mat3 angMat = new Mat3();
|
||||||
|
|
||||||
|
private int movementX = 0;
|
||||||
|
private int movementY = 0;
|
||||||
|
private int movementZ = 0;
|
||||||
|
|
||||||
|
private final WorldRenderer renderer = new WorldRenderer();
|
||||||
|
|
||||||
|
private final WorldRender world = new WorldRender(new WorldData());
|
||||||
|
|
||||||
|
public LayerWorld() {
|
||||||
|
super("World");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initialize() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
GraphicsInterface.subscribeToInputEvents(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doRender() {
|
||||||
|
camera.apply(renderer);
|
||||||
|
renderWorld();
|
||||||
|
renderer.reset();
|
||||||
|
|
||||||
|
angMat.set().rotateY(-camera.getYaw());
|
||||||
|
|
||||||
|
tmp.set(movementX, 0, movementZ);
|
||||||
|
angMat.mul_(tmp); // bug in jglm
|
||||||
|
tmp.y = movementY;
|
||||||
|
tmp.mul(0.1f);
|
||||||
|
tmp.sub(velocity);
|
||||||
|
tmp.mul(0.1f);
|
||||||
|
velocity.add(tmp);
|
||||||
|
tmp.set(velocity);
|
||||||
|
tmp.mul((float) (GraphicsInterface.getFrameLength() * 60));
|
||||||
|
camera.move(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderWorld() {
|
||||||
|
world.render(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Camera getCamera() {
|
||||||
|
return camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean flag = true;
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onKeyEvent(KeyEvent event) {
|
||||||
|
if (event.isRepeat()) return;
|
||||||
|
|
||||||
|
int multiplier = event.isPress() ? 1 : -1;
|
||||||
|
|
||||||
|
switch (event.getKey()) {
|
||||||
|
case GLFW.GLFW_KEY_W:
|
||||||
|
movementZ += -1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_S:
|
||||||
|
movementZ += +1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_A:
|
||||||
|
movementX += -1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_D:
|
||||||
|
movementX += +1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_SPACE:
|
||||||
|
movementY += +1 * multiplier;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_LEFT_SHIFT:
|
||||||
|
movementY += -1 * multiplier;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW.GLFW_KEY_ESCAPE:
|
||||||
|
if (!event.isPress()) return;
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL);
|
||||||
|
} else {
|
||||||
|
GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = !flag;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onMouseMoved(CursorMoveEvent event) {
|
||||||
|
if (!flag) return;
|
||||||
|
|
||||||
|
final float yawScale = 0.002f;
|
||||||
|
final float pitchScale = yawScale;
|
||||||
|
|
||||||
|
camera.turn(
|
||||||
|
(float) (event.getChangeY() * pitchScale),
|
||||||
|
(float) (event.getChangeX() * yawScale)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.graphics.world;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
import ru.windcorp.optica.common.util.StashingStack;
|
||||||
|
|
||||||
|
public class WorldRenderer {
|
||||||
|
|
||||||
|
private static final int TRANSFORM_STACK_SIZE = 64;
|
||||||
|
|
||||||
|
private final StashingStack<Mat4> worldTransformStack = new StashingStack<>(
|
||||||
|
TRANSFORM_STACK_SIZE, Mat4::new
|
||||||
|
);
|
||||||
|
|
||||||
|
private final StashingStack<Mat4> viewTransformStack = new StashingStack<>(
|
||||||
|
TRANSFORM_STACK_SIZE, Mat4::new
|
||||||
|
);
|
||||||
|
|
||||||
|
private final Mat4 finalTransform = new Mat4();
|
||||||
|
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mat4 pushWorldTransform() {
|
||||||
|
Mat4 previous = worldTransformStack.getHead();
|
||||||
|
return worldTransformStack.push().set(previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void popWorldTransform() {
|
||||||
|
worldTransformStack.removeHead();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mat4 getWorldTransform() {
|
||||||
|
return worldTransformStack.getHead();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mat4 pushViewTransform() {
|
||||||
|
Mat4 previous = viewTransformStack.getHead();
|
||||||
|
return viewTransformStack.push().set(previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void popViewTransform() {
|
||||||
|
viewTransformStack.removeHead();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mat4 getViewTransform() {
|
||||||
|
return viewTransformStack.getHead();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mat4 getFinalTransform() {
|
||||||
|
return finalTransform.set(getViewTransform()).mul(getWorldTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
worldTransformStack.removeAll();
|
||||||
|
worldTransformStack.push().identity();
|
||||||
|
viewTransformStack.removeAll();
|
||||||
|
viewTransformStack.push().identity();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
169
src/main/java/ru/windcorp/optica/client/world/ChunkRender.java
Normal file
169
src/main/java/ru/windcorp/optica/client/world/ChunkRender.java
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Model;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Shape;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.StaticModel;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.StaticModel.Builder;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.WorldRenderable;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
import ru.windcorp.optica.client.world.renders.BlockRender;
|
||||||
|
import ru.windcorp.optica.client.world.renders.BlockRenderNone;
|
||||||
|
import ru.windcorp.optica.client.world.renders.BlockRenders;
|
||||||
|
import ru.windcorp.optica.client.world.renders.bro.BlockRenderOptimizer;
|
||||||
|
import ru.windcorp.optica.client.world.renders.bro.BlockRenderOptimizerGenerator;
|
||||||
|
import ru.windcorp.optica.client.world.renders.bro.BlockRenderOptimizerGenerators;
|
||||||
|
import ru.windcorp.optica.common.world.ChunkData;
|
||||||
|
|
||||||
|
public class ChunkRender {
|
||||||
|
|
||||||
|
private final WorldRender world;
|
||||||
|
private final ChunkData data;
|
||||||
|
|
||||||
|
private Model model = null;
|
||||||
|
|
||||||
|
public ChunkRender(WorldRender world, ChunkData data) {
|
||||||
|
this.world = world;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldRender getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkData getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockRender getBlock(int xInChunk, int yInChunk, int zInChunk) {
|
||||||
|
return BlockRenders.get(
|
||||||
|
getData().getBlock(xInChunk, yInChunk, zInChunk).getId()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(WorldRenderer renderer) {
|
||||||
|
if (model == null) {
|
||||||
|
buildModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.pushWorldTransform().translate(
|
||||||
|
data.getX() * ChunkData.BLOCKS_PER_CHUNK,
|
||||||
|
data.getY() * ChunkData.BLOCKS_PER_CHUNK,
|
||||||
|
data.getZ() * ChunkData.BLOCKS_PER_CHUNK
|
||||||
|
);
|
||||||
|
|
||||||
|
model.render(renderer);
|
||||||
|
|
||||||
|
renderer.popWorldTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildModel() {
|
||||||
|
Map<String, BlockRenderOptimizer> optimizers = new HashMap<>();
|
||||||
|
|
||||||
|
for (
|
||||||
|
BlockRenderOptimizerGenerator generator :
|
||||||
|
BlockRenderOptimizerGenerators.getAll()
|
||||||
|
) {
|
||||||
|
BlockRenderOptimizer optimizer = generator.createOptimizer();
|
||||||
|
optimizers.put(generator.getId(), optimizer);
|
||||||
|
optimizer.startRender(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticModel.Builder builder = StaticModel.builder();
|
||||||
|
|
||||||
|
for (int x = 0; x < ChunkData.BLOCKS_PER_CHUNK; ++x) {
|
||||||
|
for (int y = 0; y < ChunkData.BLOCKS_PER_CHUNK; ++y) {
|
||||||
|
for (int z = 0; z < ChunkData.BLOCKS_PER_CHUNK; ++z) {
|
||||||
|
|
||||||
|
BlockRender block = getBlock(x, y, z);
|
||||||
|
|
||||||
|
if (block instanceof BlockRenderNone) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tryToForwardToOptimizers(block, x, y, z, optimizers)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tryToCreateRenderable(block, x, y, z, builder)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addRenderAsRenderable(block, x, y, z, builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BlockRenderOptimizer optimizer : optimizers.values()) {
|
||||||
|
Shape result = optimizer.endRender();
|
||||||
|
if (result != null) {
|
||||||
|
builder.addPart(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model = new StaticModel(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tryToForwardToOptimizers(
|
||||||
|
BlockRender block, int x, int y, int z,
|
||||||
|
Map<String, BlockRenderOptimizer> optimizers
|
||||||
|
) {
|
||||||
|
if (!block.isOptimized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BlockRenderOptimizer optimizer = optimizers.get(block.getOptimizer());
|
||||||
|
|
||||||
|
if (optimizer == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
optimizer.processBlock(block, x, y, z);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tryToCreateRenderable(
|
||||||
|
BlockRender block, int x, int y, int z,
|
||||||
|
Builder builder
|
||||||
|
) {
|
||||||
|
WorldRenderable renderable = block.createRenderable();
|
||||||
|
|
||||||
|
if (renderable == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.addPart(renderable, new Mat4().identity().translate(x, y, z));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRenderAsRenderable(
|
||||||
|
BlockRender block, int x, int y, int z,
|
||||||
|
Builder builder
|
||||||
|
) {
|
||||||
|
builder.addPart(
|
||||||
|
block::render,
|
||||||
|
new Mat4().identity().translate(x, y, z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
import ru.windcorp.optica.common.world.ChunkData;
|
||||||
|
import ru.windcorp.optica.common.world.WorldData;
|
||||||
|
|
||||||
|
public class WorldRender {
|
||||||
|
|
||||||
|
private final WorldData data;
|
||||||
|
|
||||||
|
private final Collection<ChunkRender> chunks = new ArrayList<>();
|
||||||
|
|
||||||
|
public WorldRender(WorldData data) {
|
||||||
|
this.data = data;
|
||||||
|
|
||||||
|
for (ChunkData chunkData : data.getChunks()) {
|
||||||
|
chunks.add(new ChunkRender(this, chunkData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldData getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(WorldRenderer renderer) {
|
||||||
|
renderer.pushWorldTransform().rotateX(-Math.PI / 2);
|
||||||
|
|
||||||
|
for (ChunkRender chunk : chunks) {
|
||||||
|
chunk.render(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.model.WorldRenderable;
|
||||||
|
import ru.windcorp.optica.client.graphics.world.WorldRenderer;
|
||||||
|
import ru.windcorp.optica.common.util.Namespaced;
|
||||||
|
|
||||||
|
public abstract class BlockRender extends Namespaced {
|
||||||
|
|
||||||
|
private String optimizer = null;
|
||||||
|
|
||||||
|
public BlockRender(String namespace, String name) {
|
||||||
|
super(namespace, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOptimizer() {
|
||||||
|
return optimizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOptimized() {
|
||||||
|
return getOptimizer() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptimizer(String optimizer) {
|
||||||
|
this.optimizer = optimizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(WorldRenderer renderer) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"BlockRender.render() not implemented"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldRenderable createRenderable() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.model.EmptyModel;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.WorldRenderable;
|
||||||
|
|
||||||
|
public class BlockRenderNone extends BlockRender {
|
||||||
|
|
||||||
|
public BlockRenderNone(String namespace, String name) {
|
||||||
|
super(namespace, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldRenderable createRenderable() {
|
||||||
|
return EmptyModel.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders;
|
||||||
|
|
||||||
|
import static ru.windcorp.optica.common.block.BlockFace.*;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Shapes;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.WorldRenderable;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.optica.common.block.BlockFace;
|
||||||
|
|
||||||
|
public abstract class BlockRenderTexturedCube extends BlockRender {
|
||||||
|
|
||||||
|
private final EnumMap<BlockFace, Texture> textures =
|
||||||
|
new EnumMap<>(BlockFace.class);
|
||||||
|
|
||||||
|
public BlockRenderTexturedCube(
|
||||||
|
String namespace, String name,
|
||||||
|
Texture topTexture, Texture bottomTexture,
|
||||||
|
Texture northTexture, Texture southTexture,
|
||||||
|
Texture eastTexture, Texture westTexture
|
||||||
|
) {
|
||||||
|
super(namespace, name);
|
||||||
|
|
||||||
|
textures.put(TOP, topTexture);
|
||||||
|
textures.put(BOTTOM, bottomTexture);
|
||||||
|
textures.put(NORTH, northTexture);
|
||||||
|
textures.put(SOUTH, southTexture);
|
||||||
|
textures.put(EAST, eastTexture);
|
||||||
|
textures.put(WEST, westTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Texture getTexture(BlockFace face) {
|
||||||
|
return textures.get(face);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldRenderable createRenderable() {
|
||||||
|
return new Shapes.PppBuilder(
|
||||||
|
getTexture(TOP), getTexture(BOTTOM),
|
||||||
|
getTexture(NORTH), getTexture(SOUTH),
|
||||||
|
getTexture(EAST), getTexture(WEST)
|
||||||
|
).create();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
|
||||||
|
public class BlockRenderTransparentCube extends BlockRenderTexturedCube {
|
||||||
|
|
||||||
|
public BlockRenderTransparentCube(
|
||||||
|
String namespace, String name,
|
||||||
|
Texture topTexture, Texture bottomTexture,
|
||||||
|
Texture northTexture, Texture southTexture,
|
||||||
|
Texture eastTexture, Texture westTexture
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
namespace, name,
|
||||||
|
topTexture, bottomTexture,
|
||||||
|
northTexture, southTexture,
|
||||||
|
eastTexture, westTexture
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.SimpleTexture;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Sprite;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.TextureManager;
|
||||||
|
import ru.windcorp.optica.client.world.renders.bro.BlockRenderOpaqueCube;
|
||||||
|
|
||||||
|
public class BlockRenders {
|
||||||
|
|
||||||
|
private static Texture grassTop = qtex("grass_top");
|
||||||
|
private static Texture grassSide = qtex("grass_side");
|
||||||
|
private static Texture dirtT = qtex("grass_bottom");
|
||||||
|
private static Texture stoneT = qtex("stone");
|
||||||
|
private static Texture glassT = qtex("glass_clear");
|
||||||
|
|
||||||
|
private static final Map<String, BlockRender> BLOCK_RENDERS =
|
||||||
|
new HashMap<>();
|
||||||
|
|
||||||
|
private BlockRenders() {}
|
||||||
|
|
||||||
|
static {
|
||||||
|
register(new BlockRenderOpaqueCube("Grass", "Test", grassTop, dirtT, grassSide, grassSide, grassSide, grassSide));
|
||||||
|
register(new BlockRenderOpaqueCube("Dirt", "Test", dirtT, dirtT, dirtT, dirtT, dirtT, dirtT));
|
||||||
|
register(new BlockRenderOpaqueCube("Stone", "Test", stoneT, stoneT, stoneT, stoneT, stoneT, stoneT));
|
||||||
|
|
||||||
|
register(new BlockRenderOpaqueCube("Compass", "Test", qtex("compass"), qtex("compass"), qtex("side_north"), qtex("side_south"), qtex("side_east"), qtex("side_west")));
|
||||||
|
|
||||||
|
register(new BlockRenderNone("Air", "Test"));
|
||||||
|
register(new BlockRenderTransparentCube("Glass", "Test", glassT, glassT, glassT, glassT, glassT, glassT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockRender get(String name) {
|
||||||
|
return BLOCK_RENDERS.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(BlockRender blockRender) {
|
||||||
|
BLOCK_RENDERS.put(blockRender.getId(), blockRender);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Texture qtex(String name) {
|
||||||
|
return new SimpleTexture(new Sprite(TextureManager.load(name, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders.bro;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.optica.client.world.renders.BlockRenderTexturedCube;
|
||||||
|
|
||||||
|
public class BlockRenderOpaqueCube extends BlockRenderTexturedCube {
|
||||||
|
|
||||||
|
public BlockRenderOpaqueCube(
|
||||||
|
String namespace, String name,
|
||||||
|
Texture topTexture, Texture bottomTexture,
|
||||||
|
Texture northTexture, Texture southTexture,
|
||||||
|
Texture eastTexture, Texture westTexture
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
namespace, name,
|
||||||
|
topTexture, bottomTexture,
|
||||||
|
northTexture, southTexture,
|
||||||
|
eastTexture, westTexture
|
||||||
|
);
|
||||||
|
setOptimizer("Default:OpaqueCube");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,187 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders.bro;
|
||||||
|
|
||||||
|
import static ru.windcorp.optica.common.world.ChunkData.BLOCKS_PER_CHUNK;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.optica.client.graphics.backend.Usage;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Face;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Faces;
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Shape;
|
||||||
|
import ru.windcorp.optica.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.optica.client.world.ChunkRender;
|
||||||
|
import ru.windcorp.optica.client.world.renders.BlockRender;
|
||||||
|
import ru.windcorp.optica.common.block.BlockFace;
|
||||||
|
import ru.windcorp.optica.common.world.ChunkData;
|
||||||
|
|
||||||
|
public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer {
|
||||||
|
|
||||||
|
private static final int BLOCK_MASK = 1 << 7;
|
||||||
|
|
||||||
|
private static final BlockFace[] GOOD_FACES = new BlockFace[] {
|
||||||
|
BlockFace.TOP, BlockFace.NORTH, BlockFace.WEST
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Vec3 COLOR_MULTIPLIER = new Vec3(1, 1, 1);
|
||||||
|
|
||||||
|
private final byte[][][] data = new byte[BLOCKS_PER_CHUNK + 1]
|
||||||
|
[BLOCKS_PER_CHUNK + 1]
|
||||||
|
[BLOCKS_PER_CHUNK + 1];
|
||||||
|
|
||||||
|
private ChunkRender chunk;
|
||||||
|
|
||||||
|
private final Vec3 blockCenter = new Vec3();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startRender(ChunkRender chunk) {
|
||||||
|
this.chunk = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processBlock(BlockRender block, int x, int y, int z) {
|
||||||
|
addFace(x, y, z, BlockFace.TOP);
|
||||||
|
addFace(x, y, z, BlockFace.BOTTOM);
|
||||||
|
addFace(x, y, z, BlockFace.NORTH);
|
||||||
|
addFace(x, y, z, BlockFace.SOUTH);
|
||||||
|
addFace(x, y, z, BlockFace.EAST);
|
||||||
|
addFace(x, y, z, BlockFace.WEST);
|
||||||
|
addBlock(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addFace(int x, int y, int z, BlockFace face) {
|
||||||
|
switch (face) {
|
||||||
|
case BOTTOM:
|
||||||
|
z -= 1;
|
||||||
|
face = BlockFace.TOP;
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
x -= 1;
|
||||||
|
face = BlockFace.NORTH;
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
y -= 1;
|
||||||
|
face = BlockFace.WEST;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
data[x + 1][y + 1][z + 1] ^= 1 << face.ordinal();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addBlock(int x, int y, int z) {
|
||||||
|
data[x + 1][y + 1][z + 1] |= BLOCK_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasFace(int x, int y, int z, BlockFace face) {
|
||||||
|
switch (face) {
|
||||||
|
case BOTTOM:
|
||||||
|
z -= 1;
|
||||||
|
face = BlockFace.TOP;
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
x -= 1;
|
||||||
|
face = BlockFace.NORTH;
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
y -= 1;
|
||||||
|
face = BlockFace.WEST;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
return (data[x + 1][y + 1][z + 1] & 1 << face.ordinal()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasBlock(int x, int y, int z) {
|
||||||
|
return (data[x + 1][y + 1][z + 1] & BLOCK_MASK) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape endRender() {
|
||||||
|
|
||||||
|
Collection<Face> shapeFaces = new ArrayList<>(
|
||||||
|
BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * 3 +
|
||||||
|
BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * 3
|
||||||
|
);
|
||||||
|
|
||||||
|
for (int x = -1; x < ChunkData.BLOCKS_PER_CHUNK; ++x) {
|
||||||
|
for (int y = -1; y < ChunkData.BLOCKS_PER_CHUNK; ++y) {
|
||||||
|
for (int z = -1; z < ChunkData.BLOCKS_PER_CHUNK; ++z) {
|
||||||
|
for (BlockFace face : GOOD_FACES) {
|
||||||
|
|
||||||
|
if (!hasFace(x, y, z, face)) continue;
|
||||||
|
|
||||||
|
Face shapeFace = null;
|
||||||
|
|
||||||
|
if (!hasBlock(x, y, z)) {
|
||||||
|
switch (face) {
|
||||||
|
case TOP:
|
||||||
|
shapeFace = createFace(
|
||||||
|
x, y, z + 1,
|
||||||
|
BlockFace.BOTTOM
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case NORTH:
|
||||||
|
shapeFace = createFace(
|
||||||
|
x + 1, y, z,
|
||||||
|
BlockFace.SOUTH
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
shapeFace = createFace(
|
||||||
|
x, y + 1, z,
|
||||||
|
BlockFace.EAST
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shapeFace = createFace(x, y, z, face);
|
||||||
|
}
|
||||||
|
|
||||||
|
shapeFaces.add(shapeFace);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Shape(
|
||||||
|
Usage.STATIC,
|
||||||
|
shapeFaces.toArray(new Face[shapeFaces.size()])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Face createFace(int x, int y, int z, BlockFace face) {
|
||||||
|
BlockRenderOpaqueCube blockRender =
|
||||||
|
(BlockRenderOpaqueCube) chunk.getBlock(x, y, z);
|
||||||
|
Texture texture = blockRender.getTexture(face);
|
||||||
|
|
||||||
|
return Faces.createBlockFace(
|
||||||
|
texture,
|
||||||
|
COLOR_MULTIPLIER,
|
||||||
|
blockCenter.set(x, y, z),
|
||||||
|
face
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders.bro;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.client.graphics.model.Shape;
|
||||||
|
import ru.windcorp.optica.client.world.ChunkRender;
|
||||||
|
import ru.windcorp.optica.client.world.renders.BlockRender;
|
||||||
|
|
||||||
|
public abstract class BlockRenderOptimizer {
|
||||||
|
|
||||||
|
public abstract void startRender(ChunkRender chunk);
|
||||||
|
|
||||||
|
public abstract void processBlock(BlockRender block, int x, int y, int z);
|
||||||
|
|
||||||
|
public abstract Shape endRender();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders.bro;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.common.util.Namespaced;
|
||||||
|
|
||||||
|
public abstract class BlockRenderOptimizerGenerator extends Namespaced {
|
||||||
|
|
||||||
|
public BlockRenderOptimizerGenerator(String namespace, String name) {
|
||||||
|
super(namespace, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract BlockRenderOptimizer createOptimizer();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.client.world.renders.bro;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BlockRenderOptimizerGenerators {
|
||||||
|
|
||||||
|
private BlockRenderOptimizerGenerators() {}
|
||||||
|
|
||||||
|
private static final Map<String, BlockRenderOptimizerGenerator> GENERATORS =
|
||||||
|
new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
register(new BlockRenderOptimizerGenerator("Default", "OpaqueCube") {
|
||||||
|
@Override
|
||||||
|
public BlockRenderOptimizer createOptimizer() {
|
||||||
|
return new BlockRenderOpaqueCubeOptimizer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockRenderOptimizerGenerator get(String id) {
|
||||||
|
return GENERATORS.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(BlockRenderOptimizerGenerator generator) {
|
||||||
|
GENERATORS.put(generator.getId(), generator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<BlockRenderOptimizerGenerator> getAll() {
|
||||||
|
return GENERATORS.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/main/java/ru/windcorp/optica/common/block/BlockData.java
Normal file
28
src/main/java/ru/windcorp/optica/common/block/BlockData.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.block;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.common.util.Namespaced;
|
||||||
|
|
||||||
|
public class BlockData extends Namespaced {
|
||||||
|
|
||||||
|
public BlockData(String namespace, String name) {
|
||||||
|
super(namespace, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.block;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BlockDataRegistry {
|
||||||
|
|
||||||
|
private static final Map<String, BlockData> REGISTRY = new HashMap<>();
|
||||||
|
|
||||||
|
public static BlockData get(String name) {
|
||||||
|
return REGISTRY.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(BlockData blockData) {
|
||||||
|
REGISTRY.put(blockData.getId(), blockData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
src/main/java/ru/windcorp/optica/common/block/BlockFace.java
Normal file
24
src/main/java/ru/windcorp/optica/common/block/BlockFace.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.block;
|
||||||
|
|
||||||
|
public enum BlockFace {
|
||||||
|
|
||||||
|
TOP, BOTTOM, NORTH, SOUTH, EAST, WEST;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.resource;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
|
||||||
|
import com.google.common.io.CharStreams;
|
||||||
|
|
||||||
|
import ru.windcorp.optica.Optica;
|
||||||
|
|
||||||
|
public class Resource {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Resource(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
// TODO Do proper resource lookup
|
||||||
|
return Optica.class.getClassLoader().getResourceAsStream(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reader getReader() {
|
||||||
|
return new InputStreamReader(getInputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readAsString() {
|
||||||
|
try (Reader reader = getReader()) {
|
||||||
|
return CharStreams.toString(reader);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e); // TODO handle gracefully
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.resource;
|
||||||
|
|
||||||
|
public class ResourceManager {
|
||||||
|
|
||||||
|
public static Resource getResource(String name) {
|
||||||
|
return new Resource(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.util;
|
||||||
|
|
||||||
|
public class CoordinatePacker {
|
||||||
|
|
||||||
|
private static final int BITS_3_INTS_INTO_LONG;
|
||||||
|
private static final long MASK_3_INTS_INTO_LONG;
|
||||||
|
|
||||||
|
static {
|
||||||
|
BITS_3_INTS_INTO_LONG = 64 / 3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* What happens below:
|
||||||
|
*
|
||||||
|
* 1. 1 << BITS_3_INTS_INTO_LONG:
|
||||||
|
* 0000 ... 00100 ... 0000
|
||||||
|
* \_________/ - BITS_3_INTS_INTO_LONG zeros
|
||||||
|
*
|
||||||
|
* 2. (1 << BITS_3_INTS_INTO_LONG) - 1:
|
||||||
|
* 0000 ... 00011 ... 1111
|
||||||
|
* \_________/ - BITS_3_INTS_INTO_LONG ones - WIN
|
||||||
|
*/
|
||||||
|
|
||||||
|
MASK_3_INTS_INTO_LONG = (1 << BITS_3_INTS_INTO_LONG) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long pack3IntsIntoLong(int a, int b, int c) {
|
||||||
|
return
|
||||||
|
((a & MASK_3_INTS_INTO_LONG) << (2 * BITS_3_INTS_INTO_LONG)) |
|
||||||
|
((b & MASK_3_INTS_INTO_LONG) << (1 * BITS_3_INTS_INTO_LONG)) |
|
||||||
|
((c & MASK_3_INTS_INTO_LONG) << (0 * BITS_3_INTS_INTO_LONG));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int unpack3IntsFromLong(long packed, int index) {
|
||||||
|
if (index < 0 || index >= 3) {
|
||||||
|
throw new IllegalArgumentException("Invalid index " + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = (int) (
|
||||||
|
(packed >>> ((2 - index) * BITS_3_INTS_INTO_LONG))
|
||||||
|
& MASK_3_INTS_INTO_LONG
|
||||||
|
);
|
||||||
|
|
||||||
|
final long signMask = ((MASK_3_INTS_INTO_LONG + 1) >> 1);
|
||||||
|
|
||||||
|
if ((result & signMask) != 0) {
|
||||||
|
result |= ~MASK_3_INTS_INTO_LONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
61
src/main/java/ru/windcorp/optica/common/util/Named.java
Normal file
61
src/main/java/ru/windcorp/optica/common/util/Named.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.util;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public abstract class Named {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Named(String name) {
|
||||||
|
this.name = Objects.requireNonNull(name, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName() + " " + getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return name.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Named other = (Named) obj;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
91
src/main/java/ru/windcorp/optica/common/util/Namespaced.java
Normal file
91
src/main/java/ru/windcorp/optica/common/util/Namespaced.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.util;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public abstract class Namespaced extends Named {
|
||||||
|
|
||||||
|
private static final char SEPARATOR = ':';
|
||||||
|
|
||||||
|
private static final String PART_REGEX = "^[A-Z][a-zA-Z0-9]{2,}$";
|
||||||
|
|
||||||
|
private static final Predicate<String> PART_CHECKER =
|
||||||
|
Pattern.compile(PART_REGEX).asPredicate();
|
||||||
|
|
||||||
|
private final String namespace;
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
public Namespaced(String namespace, String name) {
|
||||||
|
super(name);
|
||||||
|
this.namespace = Objects.requireNonNull(namespace, "namespace");
|
||||||
|
this.id = namespace + SEPARATOR + name;
|
||||||
|
|
||||||
|
if (!PART_CHECKER.test(name)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Name \"" + name + "\" is invalid. "
|
||||||
|
+ "Allowed is: " + PART_REGEX
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PART_CHECKER.test(namespace)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Namespace \"" + namespace + "\" is invalid. "
|
||||||
|
+ "Allowed is: " + PART_REGEX
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespace() {
|
||||||
|
return namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (!super.equals(obj))
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Namespaced other = (Namespaced) obj;
|
||||||
|
if (id == null) {
|
||||||
|
if (other.id != null)
|
||||||
|
return false;
|
||||||
|
} else if (!id.equals(other.id))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
227
src/main/java/ru/windcorp/optica/common/util/StashingStack.java
Normal file
227
src/main/java/ru/windcorp/optica/common/util/StashingStack.java
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A low-overhead, fixed-capacity stack that does not dispose of popped elements
|
||||||
|
* but rather <i>stashes</i> them for later pushing. This allows the stack to
|
||||||
|
* operate without creating new objects.
|
||||||
|
* <p>
|
||||||
|
* This object always contains references to {@link #getCapacity()} elements, of
|
||||||
|
* which first {@link #getSize()} elements are present in the stack proper and
|
||||||
|
* accessable, and the rest are <i>stashed</i>. When an element is popped, is
|
||||||
|
* becomes stashed. When an element is pushed, it ceases to be stashed.
|
||||||
|
* <p>
|
||||||
|
* Stashed elements can be replaced with {@link #push(Object)}.
|
||||||
|
*
|
||||||
|
* @author Javapony
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public class StashingStack<T> implements Iterable<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores all elements. Elements with indices
|
||||||
|
* <tt>[0; {@link #head}]</tt>
|
||||||
|
* are present in the stack, elements with indices
|
||||||
|
* <tt>({@link #head}; contents.length]</tt> are stashed.
|
||||||
|
*/
|
||||||
|
private final Object[] contents;
|
||||||
|
|
||||||
|
private transient List<T> contentsAsList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index of the head of the stack in the {@link #contents} array, or
|
||||||
|
* <tt>-1</tt>, if the stack is empty.
|
||||||
|
*/
|
||||||
|
private int head = -1;
|
||||||
|
|
||||||
|
protected StashingStack(Object[] stash, int dummy) {
|
||||||
|
this.contents = stash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new stack. Its stash is filled with {@code null}s.
|
||||||
|
* @param capacity stack's capacity
|
||||||
|
*/
|
||||||
|
public StashingStack(int capacity) {
|
||||||
|
this((T[]) new Object[capacity], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new stack with the supplied stash.
|
||||||
|
* @param contents elements that are put in the stash initially.
|
||||||
|
*/
|
||||||
|
public StashingStack(T[] contents) {
|
||||||
|
this(contents.clone(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new stack with the supplied stash.
|
||||||
|
* @param contents elements that are put in the stash initially.
|
||||||
|
*/
|
||||||
|
public StashingStack(Iterable<T> contents) {
|
||||||
|
this(Iterables.toArray(contents, Object.class), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new stack. Its stash is filled with objects provided by
|
||||||
|
* {@code generator}. The generator's {@link Supplier#get() get()} method
|
||||||
|
* will only be invoked {@code capacity} times from within this constructor.
|
||||||
|
* @param capacity stack's capacity
|
||||||
|
* @param generator a supplier of objects for the stash
|
||||||
|
*/
|
||||||
|
public StashingStack(int capacity, Supplier<T> generator) {
|
||||||
|
this(capacity);
|
||||||
|
|
||||||
|
for (int i = 0; i < contents.length; ++i) {
|
||||||
|
contents[i] = generator.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the amount of elements this stack can store.
|
||||||
|
* @return the capacity
|
||||||
|
*/
|
||||||
|
public int getCapacity() {
|
||||||
|
return contents.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of elements that are currently in the stack.
|
||||||
|
* @return the size
|
||||||
|
*/
|
||||||
|
public int getSize() {
|
||||||
|
return head + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this stack does not contain any elements.
|
||||||
|
* @return {@code true} is this stack is empty
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return getSize() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this stack is full.
|
||||||
|
* @return {@code true} is this stack is full
|
||||||
|
*/
|
||||||
|
public boolean isFull() {
|
||||||
|
return getSize() == getCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns, but does not remove, the head of this stack. If the stack is
|
||||||
|
* empty returns {@code null}.
|
||||||
|
* @return head of this stack or {@code null}
|
||||||
|
* @see #getHead()
|
||||||
|
*/
|
||||||
|
public T peek() {
|
||||||
|
if (head < 0) return null;
|
||||||
|
return (T) contents[head];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns, but does not remove, the head of this stack. If the stack is
|
||||||
|
* empty throws a {@link NoSuchElementException}.
|
||||||
|
* @return head of this stack
|
||||||
|
* @throws NoSuchElementException is the stack is empty
|
||||||
|
* @see #peek()
|
||||||
|
*/
|
||||||
|
public T getHead() {
|
||||||
|
if (head < 0) throw new NoSuchElementException();
|
||||||
|
return (T) contents[head];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and removes the head of this stack. If the stack is
|
||||||
|
* empty returns {@code null}.
|
||||||
|
* @return head of this stack or {@code null}
|
||||||
|
* @see #removeHead()
|
||||||
|
*/
|
||||||
|
public T pop() {
|
||||||
|
if (head < 0) return null;
|
||||||
|
return (T) contents[head--];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and removes the head of this stack. If the stack is
|
||||||
|
* empty throws a {@link NoSuchElementException}.
|
||||||
|
* @return head of this stack
|
||||||
|
* @throws NoSuchElementException is the stack is empty
|
||||||
|
* @see #pop()
|
||||||
|
*/
|
||||||
|
public T removeHead() {
|
||||||
|
if (head < 0) throw new NoSuchElementException();
|
||||||
|
return (T) contents[head--];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes a new element from the stash onto the stack. If the stack is
|
||||||
|
* already full throws an {@link IllegalStateException}. The state of the
|
||||||
|
* new element is not specified.
|
||||||
|
* @return the new head
|
||||||
|
*/
|
||||||
|
public T push() {
|
||||||
|
if (head == contents.length - 1) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (T) contents[++head];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes the specified element onto the stack. A stashed element is
|
||||||
|
* removed. If the stack is already full throws an
|
||||||
|
* {@link IllegalStateException}.
|
||||||
|
* @param newElement the element to push
|
||||||
|
* @return the new head
|
||||||
|
*/
|
||||||
|
public T push(T newElement) {
|
||||||
|
if (head == contents.length - 1) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
contents[++head] = newElement;
|
||||||
|
return newElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all elements from the stack.
|
||||||
|
*/
|
||||||
|
public void removeAll() {
|
||||||
|
head = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
if (contentsAsList == null) {
|
||||||
|
contentsAsList = Arrays.asList((T[]) contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentsAsList.subList(0, getSize()).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.util;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ThrowingRunnable<T extends Throwable> {
|
||||||
|
|
||||||
|
void run() throws T;
|
||||||
|
|
||||||
|
default Runnable withCatcher(
|
||||||
|
Consumer<T> catcher,
|
||||||
|
Class<T> throwableClass
|
||||||
|
) {
|
||||||
|
return () -> {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ThrowingRunnable.this.run();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
if (t.getClass() == throwableClass) {
|
||||||
|
catcher.accept(throwableClass.cast(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
Throwables.throwIfUnchecked(t);
|
||||||
|
|
||||||
|
// This should never happen
|
||||||
|
throw new AssertionError("This should not have been thrown", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default Runnable withCatcher(
|
||||||
|
Consumer<Throwable> catcher
|
||||||
|
) {
|
||||||
|
return () -> {
|
||||||
|
try {
|
||||||
|
ThrowingRunnable.this.run();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
catcher.accept(t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
114
src/main/java/ru/windcorp/optica/common/world/ChunkData.java
Normal file
114
src/main/java/ru/windcorp/optica/common/world/ChunkData.java
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.world;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.optica.common.block.BlockData;
|
||||||
|
|
||||||
|
public class ChunkData {
|
||||||
|
|
||||||
|
public static final int BLOCKS_PER_CHUNK = 16;
|
||||||
|
|
||||||
|
private final int x;
|
||||||
|
private final int y;
|
||||||
|
private final int z;
|
||||||
|
|
||||||
|
private final BlockData[][][] blocks = new BlockData[BLOCKS_PER_CHUNK]
|
||||||
|
[BLOCKS_PER_CHUNK]
|
||||||
|
[BLOCKS_PER_CHUNK];
|
||||||
|
|
||||||
|
private final BlockData grass = new BlockData("Grass", "Test");
|
||||||
|
private final BlockData dirt = new BlockData("Dirt", "Test");
|
||||||
|
private final BlockData stone = new BlockData("Stone", "Test");
|
||||||
|
private final BlockData air = new BlockData("Air", "Test");
|
||||||
|
// private final BlockData glass = new BlockData("Glass", "Test");
|
||||||
|
// private final BlockData compass = new BlockData("Compass", "Test");
|
||||||
|
|
||||||
|
public ChunkData(int x, int y, int z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
|
||||||
|
tmp_generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tmp_generate() {
|
||||||
|
Vec3i aPoint = new Vec3i(5, 0, BLOCKS_PER_CHUNK + BLOCKS_PER_CHUNK/2);
|
||||||
|
Vec3i pos = new Vec3i();
|
||||||
|
|
||||||
|
for (int x = 0; x < BLOCKS_PER_CHUNK; ++x) {
|
||||||
|
for (int y = 0; y < BLOCKS_PER_CHUNK; ++y) {
|
||||||
|
for (int z = 0; z < BLOCKS_PER_CHUNK; ++z) {
|
||||||
|
|
||||||
|
pos.set(x, y, z);
|
||||||
|
|
||||||
|
float f = aPoint.sub(pos, pos).length();
|
||||||
|
|
||||||
|
if (f > 17) {
|
||||||
|
blocks[x][y][z] = stone;
|
||||||
|
} else if (f > 14) {
|
||||||
|
blocks[x][y][z] = dirt;
|
||||||
|
} else {
|
||||||
|
blocks[x][y][z] = air;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < BLOCKS_PER_CHUNK; ++x) {
|
||||||
|
for (int y = 0; y < BLOCKS_PER_CHUNK; ++y) {
|
||||||
|
int z;
|
||||||
|
for (z = BLOCKS_PER_CHUNK - 1; z >= 0 && blocks[x][y][z] == air; --z);
|
||||||
|
|
||||||
|
blocks[x][y][z] = grass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockData getBlock(int xInChunk, int yInChunk, int zInChunk) {
|
||||||
|
if (!isInBounds(xInChunk, yInChunk, zInChunk)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Coordinates (" + x + "; " + y + "; " + z + ") "
|
||||||
|
+ "are not legal chunk coordinates"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks[xInChunk][yInChunk][zInChunk];
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInBounds(int xInChunk, int yInChunk, int zInChunk) {
|
||||||
|
return
|
||||||
|
xInChunk >= 0 && xInChunk < BLOCKS_PER_CHUNK ||
|
||||||
|
yInChunk >= 0 && yInChunk < BLOCKS_PER_CHUNK ||
|
||||||
|
zInChunk >= 0 && zInChunk < BLOCKS_PER_CHUNK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
50
src/main/java/ru/windcorp/optica/common/world/WorldData.java
Normal file
50
src/main/java/ru/windcorp/optica/common/world/WorldData.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Optica
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*******************************************************************************/
|
||||||
|
package ru.windcorp.optica.common.world;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import gnu.trove.map.TLongObjectMap;
|
||||||
|
import gnu.trove.map.hash.TLongObjectHashMap;
|
||||||
|
import ru.windcorp.optica.common.util.CoordinatePacker;
|
||||||
|
|
||||||
|
public class WorldData {
|
||||||
|
|
||||||
|
private final TLongObjectMap<ChunkData> chunks = new TLongObjectHashMap<>();
|
||||||
|
|
||||||
|
public WorldData() {
|
||||||
|
final int size = 1;
|
||||||
|
|
||||||
|
for (int x = -(size / 2); x <= (size / 2); ++x) {
|
||||||
|
for (int y = -(size / 2); y <= (size / 2); ++y) {
|
||||||
|
chunks.put(CoordinatePacker.pack3IntsIntoLong(x, y, 0), new ChunkData(x, y, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkData getChunk(int x, int y, int z) {
|
||||||
|
long key = CoordinatePacker.pack3IntsIntoLong(x, y, z);
|
||||||
|
return chunks.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ChunkData> getChunks() {
|
||||||
|
return Collections.unmodifiableCollection(chunks.valueCollection());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
src/main/resources/assets/shaders/Shape.fragment.glsl
Normal file
53
src/main/resources/assets/shaders/Shape.fragment.glsl
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
varying vec3 varyingColorMultiplier;
|
||||||
|
varying vec2 varyingTextureCoords;
|
||||||
|
varying vec3 varyingNormals;
|
||||||
|
|
||||||
|
uniform sampler2D textureSlot;
|
||||||
|
uniform vec2 textureStart;
|
||||||
|
uniform vec2 textureSize;
|
||||||
|
|
||||||
|
void applyTexture() {
|
||||||
|
gl_FragColor = texture2D(
|
||||||
|
textureSlot,
|
||||||
|
vec2(
|
||||||
|
varyingTextureCoords[0] * textureSize[0] + textureStart[0],
|
||||||
|
varyingTextureCoords[1] * textureSize[1] + textureStart[1]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void multiply(inout vec4 vector, float scalar) {
|
||||||
|
vector.x *= scalar;
|
||||||
|
vector.y *= scalar;
|
||||||
|
vector.z *= scalar;
|
||||||
|
vector.w *= scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linearMultiply(inout vec4 vector, vec4 scalars) {
|
||||||
|
vector.x *= scalars.x;
|
||||||
|
vector.y *= scalars.y;
|
||||||
|
vector.z *= scalars.z;
|
||||||
|
vector.w *= scalars.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyColorMultiplier() {
|
||||||
|
linearMultiply(gl_FragColor, vec4(varyingColorMultiplier, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyShading() {
|
||||||
|
vec3 light = normalize(vec3(0.5, 1.0, 0.2));
|
||||||
|
vec3 normal = varyingNormals;
|
||||||
|
|
||||||
|
float angleCos = dot(normal, light);
|
||||||
|
float lightness = (angleCos + 1.5) / 2;
|
||||||
|
|
||||||
|
linearMultiply(gl_FragColor, vec4(lightness.xxx, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyAlpha() {
|
||||||
|
if (gl_FragColor.w < 0.01) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
}
|
27
src/main/resources/assets/shaders/Shape.vertex.glsl
Normal file
27
src/main/resources/assets/shaders/Shape.vertex.glsl
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
attribute vec3 inputPositions;
|
||||||
|
|
||||||
|
attribute vec3 inputColorMultiplier;
|
||||||
|
varying vec3 varyingColorMultiplier;
|
||||||
|
|
||||||
|
attribute vec2 inputTextureCoords;
|
||||||
|
varying vec2 varyingTextureCoords;
|
||||||
|
|
||||||
|
attribute vec3 inputNormals;
|
||||||
|
varying vec3 varyingNormals;
|
||||||
|
|
||||||
|
uniform mat4 worldTransform;
|
||||||
|
uniform mat4 finalTransform;
|
||||||
|
|
||||||
|
vec4 applyFinalTransform(vec4 vector) {
|
||||||
|
return finalTransform * vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
void transferToFragment() {
|
||||||
|
varyingColorMultiplier = inputColorMultiplier;
|
||||||
|
varyingTextureCoords = inputTextureCoords;
|
||||||
|
|
||||||
|
mat3 worldRotation = mat3(worldTransform);
|
||||||
|
varyingNormals = normalize(worldRotation * inputNormals);
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
applyTexture();
|
||||||
|
applyColorMultiplier();
|
||||||
|
applyShading();
|
||||||
|
applyAlpha();
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_Position = applyFinalTransform(vec4(inputPositions, 1.0));
|
||||||
|
transferToFragment();
|
||||||
|
}
|
BIN
src/main/resources/assets/textures/compass.png
Normal file
BIN
src/main/resources/assets/textures/compass.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 256 B |
BIN
src/main/resources/assets/textures/glass.png
Normal file
BIN
src/main/resources/assets/textures/glass.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 644 B |
BIN
src/main/resources/assets/textures/glass_clear.png
Normal file
BIN
src/main/resources/assets/textures/glass_clear.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
src/main/resources/assets/textures/grass_bottom.png
Normal file
BIN
src/main/resources/assets/textures/grass_bottom.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 816 B |
BIN
src/main/resources/assets/textures/grass_side.png
Normal file
BIN
src/main/resources/assets/textures/grass_side.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 752 B |
BIN
src/main/resources/assets/textures/grass_top.png
Normal file
BIN
src/main/resources/assets/textures/grass_top.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 792 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user