Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
181132e092 | ||
|
|
6fe10eacfc | ||
|
|
9e692c9ec3 | ||
|
|
785b96ce82 | ||
|
|
a8ded217df | ||
|
|
3e8dba36a4 | ||
|
|
84a5e888a0 | ||
|
|
86a9f38c3b | ||
|
|
24aa7007bb | ||
|
|
59b5bea540 | ||
|
|
9da3cc4401 | ||
|
|
4a542fd6c8 | ||
|
|
a06cb77a66 | ||
|
|
3c2c06ca40 | ||
|
|
928600acd4 | ||
|
|
7ccda081b0 | ||
|
|
41f370f2ee | ||
|
|
4af20c65e6 | ||
|
|
ac551122d9 | ||
|
|
8528b4dc90 | ||
|
|
c35e093cc5 | ||
|
|
a8c76dee3c | ||
|
|
e84a094ad9 | ||
|
|
b0b7391939 | ||
|
|
3e2632c5b5 | ||
|
|
70ef730e86 | ||
|
|
92b288d978 | ||
|
|
cca1d0ece2 | ||
|
|
8effdd5dfa | ||
|
|
e78429b600 | ||
|
|
05a13a40e7 | ||
|
|
ef7617701e | ||
|
|
2f50dc1522 | ||
|
|
9eafcd27fb | ||
|
|
3879eb1d75 | ||
|
|
78046e5e2d | ||
|
|
26233f934f | ||
|
|
167c04b107 | ||
|
|
5fcb1d1234 | ||
|
|
70a617b688 | ||
|
|
bb0f584bf6 | ||
|
|
6b4b549b3c | ||
|
|
ffbecbbcde | ||
|
|
2728ca9646 | ||
|
|
7e5aa22fee | ||
|
|
c20e82634a | ||
|
|
9f82e7a2e6 | ||
|
|
7418bbbe27 | ||
|
|
be2aa76f8b | ||
|
|
e8f1786a2a | ||
|
|
e30f8a4c70 | ||
|
|
f8642efa23 | ||
|
|
5da5a754fe | ||
|
|
fb1b0a1c2e | ||
|
|
74c2f786a1 | ||
|
|
5216965496 | ||
|
|
ad7294ceea | ||
|
|
3893038d9a | ||
|
|
cb2e8318e7 | ||
|
|
5cca2413fe | ||
|
|
db4254e205 | ||
|
|
fa3a4c66c9 | ||
|
|
84006380db | ||
|
|
f6cc30a30c | ||
|
|
d883b58260 | ||
|
|
b59a10b7e6 | ||
|
|
5b57696acf | ||
|
|
1265d87bc5 | ||
|
|
46d7a2a25d | ||
|
|
0babfff28b | ||
|
|
ed6e1bacc7 | ||
|
|
9c39782729 | ||
|
|
efad2dde3e | ||
|
|
84d8ee7eee | ||
|
|
7693237aa5 | ||
|
|
528c94e921 | ||
|
|
a8700af1d0 | ||
|
|
9793c5bf06 | ||
|
|
b56fafa0e0 | ||
|
|
22ee99418d | ||
|
|
4eda57b4e4 | ||
|
|
2ffd8124f2 | ||
|
|
210c191d41 | ||
|
|
251a59ddbe | ||
|
|
5df2216da6 | ||
|
|
2c1c077611 | ||
|
|
629c9ba7b1 | ||
|
|
a59bcc0c4b | ||
|
|
cf1ec1e76f | ||
|
|
8a374a4231 | ||
|
|
da2b6e5577 | ||
|
|
aa9590e2f4 | ||
|
|
a1d54b01b0 | ||
|
|
65a2066727 | ||
|
|
c49c4626d0 | ||
|
|
ec156bd679 | ||
|
|
7b1d9363a0 | ||
|
|
82ca994fac | ||
|
|
0d2f705d42 | ||
|
|
e799b4ec79 | ||
|
|
c8076b6018 | ||
|
|
88f68b20ea | ||
|
|
d249f17d22 | ||
|
|
bee3545196 | ||
|
|
e050d7d0ec | ||
|
|
e18484ea62 | ||
|
|
204b79bf06 | ||
|
|
50232c0816 | ||
|
|
e8fb14b809 | ||
|
|
d425167dce | ||
|
|
f41228acf8 | ||
|
|
cacc18dc7e | ||
|
|
96d879076a | ||
|
|
8f3528f9a1 | ||
|
|
67c0696061 | ||
|
|
1a7e424085 | ||
|
|
6aff22ec53 | ||
|
|
579f4886d1 | ||
|
|
64385ba15c | ||
|
|
3c55b59c8d | ||
|
|
e0a60dcd6f | ||
|
|
f967807296 | ||
|
|
fbc420e894 | ||
|
|
ff95163bcd | ||
|
|
e0453db063 | ||
|
|
0f415b6ed6 | ||
|
|
1348efb5fe | ||
|
|
ea26d6fb23 | ||
|
|
52a52ef960 | ||
|
|
90ad3392cb | ||
|
|
dc5c76f888 | ||
|
|
483757f8ca | ||
|
|
bdce619e68 | ||
|
|
dca38c986d | ||
|
|
13af968a04 | ||
|
|
4cc6971542 | ||
|
|
8d58e41459 | ||
|
|
dffbc6029d | ||
|
|
988e0fefa8 | ||
|
|
f0ad32476e | ||
|
|
deedec7833 | ||
|
|
cda1c0de20 | ||
|
|
ec30cbe810 | ||
|
|
d610f1dea1 | ||
|
|
c347545d0e | ||
|
|
a08ee412a6 | ||
|
|
528e7ae5a6 | ||
|
|
8089bcc0f3 | ||
|
|
d1cab1f3b3 | ||
|
|
9fc0adf210 | ||
|
|
197423b572 | ||
|
|
112684b40a | ||
|
|
648acf8938 | ||
|
|
b055faf882 | ||
|
|
723b973c7f | ||
|
|
6961152d34 | ||
|
|
34fee1005a | ||
|
|
8168734fbb | ||
|
|
144978bfa2 | ||
|
|
9bfe2bef89 | ||
|
|
c553780b6e | ||
|
|
570c96a628 | ||
|
|
c9178cff3a | ||
|
|
2b40c13c9d | ||
|
|
592e008914 | ||
|
|
0a5a3b653d | ||
|
|
ff3946a019 | ||
|
|
f197dfcf02 | ||
|
|
1af829bf49 | ||
|
|
7287f4b619 | ||
|
|
14b43239b5 | ||
|
|
d57112be35 | ||
|
|
7fc46d36a1 | ||
|
|
bee2fff538 | ||
|
|
29834d528a | ||
|
|
068c319890 | ||
|
|
53ea1f768c | ||
|
|
b369c52270 | ||
|
|
01d362615f | ||
|
|
e690d0f8e2 | ||
|
|
854a425d85 | ||
|
|
0464bed4cf | ||
|
|
7c272a2ee6 | ||
|
|
db25abc305 | ||
|
|
57ff27b0f6 | ||
|
|
a91d7c04e8 | ||
|
|
16ba536481 | ||
|
|
7a1961b5d1 | ||
|
|
af550f56a7 | ||
|
|
27fb7a448c | ||
|
|
2b6af91992 | ||
|
|
4afb9d6f4f | ||
|
|
fe361885c0 | ||
|
|
3887208b8d | ||
|
|
4c837eff0a | ||
|
|
8f9a18d960 | ||
|
|
bc49540a95 | ||
|
|
d2605d9108 | ||
|
|
115cbbb7fa | ||
|
|
ae1ca71a20 | ||
|
|
c02273d29d | ||
|
|
fec7e08c2b | ||
|
|
0f937e2e02 | ||
|
|
b855cff0e6 | ||
|
|
b768b27d49 | ||
|
|
c5044d42de | ||
|
|
88bc764f08 | ||
|
|
72a2b4c47c | ||
|
|
38f4f6b7fc | ||
|
|
af00e77dc2 | ||
|
|
0322098efa | ||
|
|
2b19a3eaba | ||
|
|
69941dd86d | ||
|
|
0843ee4fa4 | ||
|
|
05bf63d447 | ||
|
|
b45d9300bd | ||
|
|
fb4e2e2491 | ||
|
|
c088080be5 | ||
|
|
52592bea16 | ||
|
|
933c1ec10e | ||
|
|
02443c7974 | ||
|
|
dd0381a007 | ||
|
|
60b71317ce | ||
|
|
946c5d784b | ||
|
|
a4d2b732aa | ||
|
|
17d3b0ce2c | ||
|
|
f37c0ee9e6 | ||
|
|
2797b9fd3a | ||
|
|
a8689e8b58 | ||
|
|
4e9275fa88 | ||
|
|
2f9ab72258 | ||
|
|
8e82e716c7 | ||
|
|
da7805ce0c | ||
|
|
f77a3fa4ad | ||
|
|
5db648a99f | ||
|
|
1938d987f9 | ||
|
|
56fee07553 | ||
|
|
24762e4d16 | ||
|
|
4dd60fb61e | ||
|
|
4e1d5859e2 | ||
|
|
1632549b48 | ||
|
|
b092ceaf14 | ||
|
|
a43b6ee04a | ||
|
|
4aa7545a7f | ||
|
|
4afecc431c | ||
|
|
0db76cb793 | ||
|
|
6784a29086 | ||
|
|
7faccda488 | ||
|
|
940d5d4339 | ||
|
|
19c2f62ba9 | ||
|
|
df9615e42a | ||
|
|
6298761311 | ||
|
|
7c9e75b629 | ||
|
|
5e7c274645 | ||
|
|
112be9bb0c | ||
|
|
7951e6ab80 | ||
|
|
3453c9780e | ||
|
|
0e862e7a61 | ||
|
|
644983408e | ||
|
|
f7c9c0c31f | ||
|
|
2e257e8abe | ||
|
|
f93a8586ae | ||
|
|
c153f2fe61 | ||
|
|
07364460c3 | ||
|
|
86523fa5bb | ||
|
|
5c0b7f9761 | ||
|
|
7fa4a74ef0 | ||
|
|
31353179e5 | ||
|
|
80d003e9b2 | ||
|
|
146644b3db | ||
|
|
271ceadd66 | ||
|
|
15db2b3006 | ||
|
|
836e58f634 | ||
|
|
d0c49843af | ||
|
|
b9bd0648ab | ||
|
|
cac687a2d2 | ||
|
|
928b87cb6e | ||
|
|
5f5fe2ade5 | ||
|
|
d062bf472c | ||
|
|
1e030e9d3a | ||
|
|
d6c01368d7 | ||
|
|
c39c9e8a35 | ||
|
|
e89c70eddd | ||
|
|
7c5ef50f9b | ||
|
|
bbd29ea310 | ||
|
|
0ec18bac20 | ||
|
|
6b9b670373 | ||
|
|
ebe58e5488 | ||
|
|
b065669583 | ||
|
|
45334c77f7 | ||
|
|
895a947a60 | ||
|
|
de2ffec17d | ||
|
|
2d21324743 | ||
|
|
73eee0525c | ||
|
|
8d61db9558 | ||
|
|
6a4fb6390a | ||
|
|
769854ac84 | ||
|
|
82307f56e4 | ||
|
|
f972b840a6 | ||
|
|
24eecbec3b | ||
|
|
2e73c41519 | ||
|
|
29f4a43f09 | ||
|
|
6c576510b7 | ||
|
|
32b2acf739 | ||
|
|
e91bf4b35f | ||
|
|
1bb131ecd2 | ||
|
|
87caae43cc | ||
|
|
650927498c | ||
|
|
b51ef1f983 | ||
|
|
6d38a9e914 | ||
|
|
5ebc68043e | ||
|
|
2a9149c746 | ||
|
|
f7de370212 | ||
|
|
cc38d52f6c | ||
|
|
526efb217e | ||
|
|
e8e4dc9b28 | ||
|
|
a3075433f0 | ||
|
|
c39eac4241 | ||
|
|
fe5d8c2f47 | ||
|
|
4f2741765b | ||
|
|
ede7597acb | ||
|
|
5c571578dd | ||
|
|
91e9a3a3a8 | ||
|
|
0aff255379 | ||
|
|
ebf292d993 | ||
|
|
a580afb8b9 | ||
|
|
9012986f9d | ||
|
|
cc5401201d | ||
|
|
ed11b23d24 | ||
|
|
60b610d111 | ||
|
|
daf0991f0b | ||
|
|
01e6b0e355 | ||
|
|
b3efd62229 | ||
|
|
c281070ff6 | ||
|
|
1229e61702 | ||
|
|
568384658e | ||
|
|
c31139fdec | ||
|
|
54d0af8afb | ||
|
|
322d83de9d | ||
|
|
4e070d3d04 | ||
|
|
383b34f5d6 | ||
|
|
a568d3d0da | ||
|
|
cfc96f645e | ||
|
|
512e912471 | ||
|
|
7e448812e2 | ||
|
|
2ae62fbc07 | ||
|
|
f8b25e581b | ||
|
|
103c43eba1 | ||
|
|
aa84fa0823 | ||
|
|
9f75e3ad60 | ||
|
|
0fc6b483d1 | ||
|
|
d414505d15 | ||
|
|
1ac4c51a5d | ||
|
|
a6a275a934 | ||
|
|
4ff416757f | ||
|
|
37f0a6aa08 | ||
|
|
929c5aade1 | ||
|
|
ebc63e6663 | ||
|
|
d35547560e | ||
|
|
70f30b8b3a | ||
|
|
bdf721ac15 | ||
|
|
a15b74e7a9 | ||
|
|
980b8133a8 | ||
|
|
527315e976 | ||
|
|
d79a684868 | ||
|
|
6fd0fc5868 | ||
|
|
fe88d27632 | ||
|
|
87032466ac | ||
|
|
aac2e84ad6 | ||
|
|
b94bebdf0d | ||
|
|
fa520b5df8 | ||
|
|
8657301da0 | ||
|
|
f816b5ada8 | ||
|
|
6ea9276495 | ||
|
|
8b07b6cc3f | ||
|
|
ac31c3bbf5 | ||
|
|
a8a3b04b09 | ||
|
|
15697ebe67 | ||
|
|
2c26c5c0b5 | ||
|
|
8e5e96e3ee | ||
|
|
6c25d1f06b | ||
|
|
d84e7904e6 | ||
|
|
dc01bdf12e | ||
|
|
064d446aea | ||
|
|
4fd09212dd | ||
|
|
784da51a3f | ||
|
|
d46e5da520 | ||
|
|
b7f8a0f67a | ||
|
|
1e3be66495 | ||
|
|
eb0bae44aa | ||
|
|
aef61e19b4 | ||
|
|
a4aea4163a | ||
|
|
7616435e00 | ||
|
|
37e2c489a8 | ||
|
|
378c9c6d6d | ||
|
|
22ad0ebf98 | ||
|
|
5d31d8421f | ||
|
|
06cc639bb7 | ||
|
|
74a2dc78a6 | ||
|
|
68b31cb197 | ||
|
|
2a16970cde | ||
|
|
243dd61209 | ||
|
|
1bf6d3f0b1 | ||
|
|
5221b3a689 | ||
|
|
2d0c7ec166 | ||
|
|
4c397eb3d0 | ||
|
|
4271ef556d | ||
|
|
55133bbd87 | ||
|
|
51a1cc742c | ||
|
|
60380ee733 | ||
|
|
b1954fd334 | ||
|
|
641efaf582 | ||
|
|
dbffcf5f04 | ||
|
|
b6684f7929 | ||
|
|
0c431f9c08 | ||
|
|
e2af375aa0 | ||
|
|
666bfc1b37 | ||
|
|
436cf015a1 | ||
|
|
b27b4adab3 | ||
|
|
613d809b43 | ||
|
|
880caecd97 | ||
|
|
7dd2816409 | ||
|
|
a8ab5015b9 | ||
|
|
27ecda3124 | ||
|
|
43dd93a802 | ||
|
|
bed5ae7a40 | ||
|
|
b5877a488d | ||
|
|
3fa844ddb9 | ||
|
|
7249f30b71 | ||
|
|
d9038fee44 | ||
|
|
098f2b4005 | ||
|
|
69a03cf524 | ||
|
|
c6b8a52c6d | ||
|
|
f5cf579115 | ||
|
|
64ec35415c | ||
|
|
4a784036bd | ||
|
|
f5940c729c | ||
|
|
fa0a369357 | ||
|
|
8d8843cb11 | ||
|
|
0fd42529c7 | ||
|
|
0a37ba49c3 | ||
|
|
b9e88547e6 | ||
|
|
dfa5786f24 | ||
|
|
407db412c7 | ||
|
|
4d2d35e34e | ||
|
|
329f1b1663 | ||
|
|
e130c2ba7f | ||
|
|
3c40d3c20d | ||
|
|
476a1e23f7 | ||
|
|
21301652ce | ||
|
|
c792e50f1b | ||
|
|
2876446ec8 | ||
|
|
826f8cbb23 | ||
|
|
0cc3dce9a8 | ||
|
|
48510c3aa6 | ||
|
|
7517b5f336 | ||
|
|
1500a7456d | ||
|
|
c8e8903ef2 | ||
|
|
cb9f6c6932 | ||
|
|
3bfac34979 | ||
|
|
7dda6d6ffb |
No files matched your search
@@ -0,0 +1,3 @@
|
||||
*.bmp filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -1,62 +1,407 @@
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
*.aab
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
.vscode/
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
.idea/
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
.........................................................................
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# CMake build files
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
*.cmake
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# Android Studio
|
||||
*.iml
|
||||
.idea/
|
||||
.cxx/
|
||||
.gradle/
|
||||
.DS_Store
|
||||
/captures/
|
||||
.externalNativeBuild/
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NDK
|
||||
.obj/
|
||||
*.o
|
||||
*.so
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# SDL2 (если используешь)
|
||||
libs/
|
||||
obj/
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Временные файлы
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.thumbs.db
|
||||
desktop.ini
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# Проектные специфичные
|
||||
app/build/
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
app/jni/libpng
|
||||
app/jni/SDL
|
||||
app/jni/zlib
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Nuget personal access tokens and Credentials
|
||||
nuget.config
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
|
||||
|
||||
sdl_app
|
||||
|
||||
*.sln.iml
|
||||
|
||||
images.zip
|
||||
script.py
|
||||
|
||||
jumpingbird.*
|
||||
jumpingbird.data
|
||||
build
|
||||
build-emcmake
|
||||
thirdparty
|
||||
|
||||
proj-web/build
|
||||
proj-windows/build
|
||||
public
|
||||
@@ -0,0 +1,175 @@
|
||||
# Windows
|
||||
|
||||
download from https://cmake.org/download/
|
||||
|
||||
|
||||
Windows x64 Installer: cmake-4.2.0-windows-x86_64.msi
|
||||
|
||||
|
||||
download from https://github.com/libsdl-org/SDL/releases/tag/release-2.32.10
|
||||
|
||||
SDL2-2.32.10-win32-x64.zip
|
||||
|
||||
SDL2-2.32.10:
|
||||
|
||||
```
|
||||
cd C:\..\SDL-realese-2.32.10
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "Visual Studio 18 2026" -DCMAKE_INSTALL_PREFIX=install ..
|
||||
cmake --build . --config Debug
|
||||
cmake --install . --config Debug
|
||||
```
|
||||
|
||||
download from https://www.zlib.net/
|
||||
|
||||
zlib source code, version 1.3.1, zipfile format (1616K, SHA-256 hash 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17):
|
||||
US (zlib.net)
|
||||
|
||||
zlib-1.3.1:
|
||||
|
||||
```
|
||||
cd C:\..\zlib-1.3.1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "Visual Studio 18 2026" -DCMAKE_INSTALL_PREFIX=install ..
|
||||
cmake --build . --config Debug
|
||||
cmake --install . --config Debug
|
||||
```
|
||||
|
||||
download from https://github.com/pnggroup/libpng/releases/tag/v1.6.51
|
||||
|
||||
Source code (zip)
|
||||
|
||||
libpng-1.6.51:
|
||||
|
||||
```
|
||||
cd C:\..\libpng-1.6.51
|
||||
mkdir build
|
||||
cd build
|
||||
```
|
||||
|
||||
To build libpng, you need to specify the path to the zlib installation directory as follows:
|
||||
|
||||
```
|
||||
cmake -DCMAKE_PREFIX_PATH="../zlib-1.3.1/build/install" -DCMAKE_INSTALL_PREFIX=install -G "Visual Studio 18 2026" ..
|
||||
cmake --build . --config Debug
|
||||
cmake --install . --config Debug
|
||||
```
|
||||
|
||||
Настройка проекта в Visual Studio:
|
||||
|
||||
Перейдите в Project Properties (правый клик на проект, "Properties").
|
||||
|
||||
C/C++ - ОБЩИЕ; Дополнительные каталоги включаемых файлов, проверить чтобы был добавлен путь к папке include:(пример)
|
||||
|
||||
..\SDL-release-2.32.10\include;..\libpng-1.6.51\build\install\include;C:\Work\OpenAL 1.1 SDK\include;..\Projects\libogg\include;..\vorbis\include
|
||||
|
||||
|
||||
Компоновщик - ОБЩИЕ; Доподнительные каталоги библиотек (пример)
|
||||
|
||||
..\SDL-release-2.32.10\build\install\lib;..\libpng-1.6.51\build\install\lib;..\zlib-1.3.1\build\install\lib
|
||||
|
||||
Компоновщик - ВВОД; Дополнительные зависимости, добавить zlibstaticd.lib (пример)
|
||||
|
||||
zlibstaticd.lib;libpng16_staticd.lib;SDL2d.lib;SDL2maind.lib;opengl32.lib;glu32.lib;shell32.lib;opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib
|
||||
|
||||
|
||||
в папку ..\projectGAME01\x64\Debug добавить файл SDL2d.dll
|
||||
который можно скопировать из папки ..\SDL-release-2.32.10\build\Debug
|
||||
|
||||
|
||||
# Script to run:
|
||||
|
||||
```
|
||||
C:\Work\Projects\emsdk\emsdk.bat activate latest
|
||||
C:\Work\Projects\emsdk\emsdk_env.bat
|
||||
emcc main.cpp Game.cpp Math.cpp Physics.cpp Renderer.cpp ShaderManager.cpp TextureManager.cpp Utils.cpp OpenGlExtensions.cpp -O2 -std=c++14 -sTOTAL_MEMORY=33554432 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS="[""png""]" -sUSE_SDL=2 --preload-file background.bmp --preload-file bird.bmp32 --preload-file default.fragment --preload-file default.vertex --preload-file game_over.bmp32 --preload-file pipe.bmp32 -o space-game001.html
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
|
||||
zlib-1.3.1:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=install ..
|
||||
|
||||
then run ALL_BUILD and INSTALL in Visual Studio
|
||||
|
||||
lpng1645:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=install -DZLIB_ROOT=C:\Work\Projects\zlib-1.3.1\build\install ..
|
||||
|
||||
then run ALL_BUILD and INSTALL in Visual Studio
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
https://github.com/Bly7/OBJ-Loader/blob/master/Source/OBJ_Loader.h
|
||||
|
||||
|
||||
https://github.com/gametutorials/tutorials/blob/master/OpenGL/MD3%20Animation/Main.cpp
|
||||
|
||||
|
||||
|
||||
linux:
|
||||
```
|
||||
g++ Game.cpp main.cpp Math.cpp OpenGlExtensions.cpp Physics.cpp Renderer.cpp ShaderManager.cpp TextureManager.cpp Utils.cpp BoneAnimatedModel.cpp ObjLoader.cpp cmakeaudioplayer/src/AudioPlayer.cpp TextModel.cpp Inventory.cpp -o sdl_app -O2 -std=c++17 \
|
||||
-I cmakeaudioplayer/include \
|
||||
$(pkg-config --cflags --libs sdl2 gl) \
|
||||
$(pkg-config --cflags --libs vorbis vorbisfile ogg) \
|
||||
-lopenal
|
||||
```
|
||||
|
||||
# Emscripten new
|
||||
|
||||
```
|
||||
|
||||
cd build-emcmake/
|
||||
|
||||
emcmake cmake -DCMAKE_INSTALL_PREFIX=install ..
|
||||
cmake --build .
|
||||
|
||||
cmake --install .
|
||||
|
||||
|
||||
emcc main.cpp Game.cpp Environment.cpp GameObjectManager.cpp BoneAnimatedModel.cpp GameWorld.cpp InputManager.cpp Inventory.cpp ObjLoader.cpp QuestScripts.cpp RenderSystem.cpp Math.cpp Physics.cpp Renderer.cpp TextModel.cpp ShaderManager.cpp TextureManager.cpp Utils.cpp OpenGlExtensions.cpp -O2 -std=c++14 -IC:\Users\ASUS\Desktop\fishrungame2\ZeptoLabTest1\thirdparty\libzip-1.11.3\build-emcmake\install\include -LC:\Users\ASUS\Desktop\fishrungame2\ZeptoLabTest1\thirdparty\libzip-1.11.3\build-emcmake\install\lib -lzip -sTOTAL_MEMORY=33554432 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS="[""png""]" -sUSE_SDL=2 --preload-file background.bmp --preload-file bird.bmp32 --preload-file default.fragment --preload-file default.vertex --preload-file game_over.bmp32 --preload-file pipe.bmp32 -o jumpingbird.html
|
||||
|
||||
emcc main.cpp Game.cpp Environment.cpp GameObjectManager.cpp BoneAnimatedModel.cpp GameWorld.cpp InputManager.cpp Inventory.cpp ObjLoader.cpp QuestScripts.cpp RenderSystem.cpp Math.cpp Physics.cpp Renderer.cpp TextModel.cpp ShaderManager.cpp TextureManager.cpp Utils.cpp OpenGlExtensions.cpp -O2 -std=c++14 -pthread -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE=4 -sTOTAL_MEMORY=4294967296 -sINITIAL_MEMORY=3221225472 -sMAXIMUM_MEMORY=4294967296 -sALLOW_MEMORY_GROWTH=1 -I./thirdparty/libzip-1.11.3/build-emcmake/install/include -I./thirdparty/zlib-1.3.1/install/include -L./thirdparty/libzip-1.11.3/build-emcmake/install/lib -L./thirdparty/zlib-1.3.1/install/lib -lzip -lz -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS='["png"]' -sUSE_SDL=2 --preload-file data.zip -o jumpingbird.html
|
||||
|
||||
|
||||
# Windows:
|
||||
emcc --clear-cache
|
||||
embuilder build sdl2 sdl2_ttf sdl2_image sdl2_image_jpg sdl2_image_png
|
||||
|
||||
|
||||
|
||||
emcc main.cpp Game.cpp Environment.cpp BoneAnimatedModel.cpp ZLMath.cpp Renderer.cpp TextModel.cpp ShaderManager.cpp TextureManager.cpp Utils.cpp OpenGlExtensions.cpp -O2 -std=c++14 -pthread -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE=4 -sTOTAL_MEMORY=4294967296 -sINITIAL_MEMORY=3221225472 -sMAXIMUM_MEMORY=4294967296 -sALLOW_MEMORY_GROWTH=1 -I./thirdparty/libzip-1.11.3/build-emcmake/install/include -L./thirdparty/libzip-1.11.3/build-emcmake/install/lib -lzip -lz -sUSE_SDL_IMAGE=2 -sUSE_SDL=2 -sUSE_LIBPNG=1 --preload-file space-game001.zip -o space-game001.html
|
||||
|
||||
emrun --no_browser --port 8080 .
|
||||
```
|
||||
|
||||
|
||||
# Emscripten new
|
||||
```
|
||||
emcc src/main.cpp src/Game.cpp src/Environment.cpp src/BoneAnimatedModel.cpp src/TextModel.cpp src/Projectile.cpp src/SparkEmitter.cpp src/UiManager.cpp src/render/Renderer.cpp src/render/ShaderManager.cpp src/render/TextureManager.cpp src/render/FrameBuffer.cpp src/render/OpenGlExtensions.cpp src/utils/Utils.cpp src/utils/TaskManager.cpp src/utils/Perlin.cpp src/planet/PlanetData.cpp src/planet/PlanetObject.cpp src/planet/StoneObject.cpp -O2 -std=c++17 -pthread -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE=4 -sTOTAL_MEMORY=4294967296 -sINITIAL_MEMORY=3221225472 -sMAXIMUM_MEMORY=4294967296 -sALLOW_MEMORY_GROWTH=1 -fexceptions -I./thirdparty1/eigen-5.0.0 -I./src -I./thirdparty/libzip-1.11.3/build-emcmake/install/include -IC:/Boost/include/boost-1_84 -L./thirdparty/libzip-1.11.3/build-emcmake/install/lib -lzip -lz -sUSE_SDL_IMAGE=2 -sUSE_SDL=2 -sUSE_LIBPNG=1 --preload-file space-game001.zip -o space-game001.html
|
||||
```
|
||||
|
||||
# License
|
||||
Code: MIT
|
||||
|
||||
Art: CC-BY
|
||||
|
||||
# Cmake Run Linux
|
||||
Run using cmakelist
|
||||
make -j$(nproc) -C build #Компилируем
|
||||
./build/sdl_app #Запускаем
|
||||
|
||||
Для постройки без звука
|
||||
rm -rf build #Очищаем build папку
|
||||
cmake -B build -DAUDIO=1 #Пересоздаём конфигурацию CMake
|
||||
@@ -1,41 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
project(GAME)
|
||||
|
||||
if(POLICY CMP0079)
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
endif()
|
||||
|
||||
# Копируем pnglibconf.h.prebuilt
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libpng/scripts/pnglibconf.h.prebuilt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libpng/pnglibconf.h
|
||||
)
|
||||
|
||||
# Сначала zlib
|
||||
add_subdirectory(zlib)
|
||||
|
||||
# ВАЖНО: Установите опции ДО add_subdirectory(libpng)
|
||||
# Libpng создает ДВЕ цели: png_shared (shared) и png_static (static)
|
||||
# Мы хотим статическую библиотеку для Android
|
||||
set(PNG_STATIC ON CACHE BOOL "Build static library" FORCE)
|
||||
set(PNG_SHARED OFF CACHE BOOL "Don't build shared library" FORCE)
|
||||
set(PNG_TESTS OFF CACHE BOOL "Disable tests" FORCE)
|
||||
set(PNG_TOOLS OFF CACHE BOOL "Disable tools" FORCE)
|
||||
set(PNG_EXECUTABLES OFF CACHE BOOL "Disable executables" FORCE)
|
||||
set(PNG_DEBUG OFF CACHE BOOL "Disable debug" FORCE)
|
||||
set(SKIP_INSTALL_ALL ON CACHE BOOL "Skip installation" FORCE)
|
||||
|
||||
# Для Android отключаем оптимизации
|
||||
set(PNG_HARDWARE_OPTIMIZATIONS OFF CACHE BOOL "Disable hardware optimizations" FORCE)
|
||||
set(PNG_ARM_NEON "off" CACHE STRING "Disable ARM NEON" FORCE)
|
||||
|
||||
# Добавляем libpng
|
||||
add_subdirectory(libpng)
|
||||
|
||||
# Затем SDL
|
||||
add_subdirectory(SDL)
|
||||
|
||||
# И ваш код
|
||||
add_subdirectory(src)
|
||||
@@ -1,62 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
project(MY_APP CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_library(main SHARED
|
||||
SDL_android_main.c
|
||||
main.cpp
|
||||
|
||||
Utils.h
|
||||
Utils.cpp
|
||||
TextureManager.h
|
||||
TextureManager.cpp
|
||||
TextModel.h
|
||||
TextModel.cpp
|
||||
ShaderManager.h
|
||||
ShaderManager.cpp
|
||||
Renderer.h
|
||||
Renderer.cpp
|
||||
Math.h
|
||||
Math.cpp
|
||||
Environment.h
|
||||
Environment.cpp
|
||||
BoneAnimatedModel.h
|
||||
BoneAnimatedModel.cpp
|
||||
AnimatedModel.h
|
||||
Game.h
|
||||
Game.cpp
|
||||
)
|
||||
|
||||
# Подключаем заголовки
|
||||
target_include_directories(main PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../SDL/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../zlib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../libpng
|
||||
)
|
||||
|
||||
# ВАЖНО: Линкуемся с png_static (статика) или png_shared (динамика)
|
||||
# Так как мы установили PNG_STATIC=ON и PNG_SHARED=OFF,
|
||||
# должна создаться цель png_static
|
||||
target_link_libraries(main
|
||||
png_static # ← ЭТО ПРАВИЛЬНОЕ ИМЯ ЦЕЛИ!
|
||||
z
|
||||
SDL2
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
# OpenGL ES 2.0 или 3.0 для Android
|
||||
find_library(OPENGLES2_LIB GLESv2)
|
||||
find_library(OPENGLES1_LIB GLESv1_CM)
|
||||
|
||||
target_link_libraries(main
|
||||
${OPENGLES2_LIB} # OpenGL ES 2.0/3.0
|
||||
${OPENGLES1_LIB} # OpenGL ES 1.x (если нужно)
|
||||
log
|
||||
android
|
||||
OpenSLES
|
||||
dl
|
||||
)
|
||||
endif()
|
||||
@@ -1,35 +0,0 @@
|
||||
#include "Environment.h"
|
||||
|
||||
#include "Utils.h"
|
||||
//#include <GL/gl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
namespace ZL {
|
||||
|
||||
int Environment::windowHeaderHeight = 0;
|
||||
int Environment::width = 0;
|
||||
int Environment::height = 0;
|
||||
float Environment::zoom = 20.f;
|
||||
|
||||
bool Environment::leftPressed = false;
|
||||
bool Environment::rightPressed = false;
|
||||
bool Environment::upPressed = false;
|
||||
bool Environment::downPressed = false;
|
||||
|
||||
Vector3f Environment::cameraShift = {0, 0, 0};
|
||||
Vector3f Environment::characterPos = {0, 0, 0};
|
||||
|
||||
float Environment::cameraPhi = 0.f;
|
||||
float Environment::cameraAlpha = 0.3*M_PI / 2.0;
|
||||
|
||||
bool Environment::settings_inverseVertical = false;
|
||||
|
||||
SDL_Window* Environment::window = nullptr;
|
||||
|
||||
bool Environment::showMouse = false;
|
||||
|
||||
bool Environment::exitGameLoop = false;
|
||||
|
||||
|
||||
|
||||
} // namespace ZL
|
||||
@@ -1,40 +0,0 @@
|
||||
#pragma once
|
||||
#include "Math.h"
|
||||
#ifdef __linux__
|
||||
#include <SDL2/SDL.h>
|
||||
#endif
|
||||
//#include "OpenGlExtensions.h"
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
namespace ZL {
|
||||
|
||||
class Environment {
|
||||
public:
|
||||
static int windowHeaderHeight;
|
||||
static int width;
|
||||
static int height;
|
||||
static float zoom;
|
||||
|
||||
static bool leftPressed;
|
||||
static bool rightPressed;
|
||||
static bool upPressed;
|
||||
static bool downPressed;
|
||||
|
||||
static Vector3f cameraShift;
|
||||
static Vector3f characterPos;
|
||||
static float cameraPhi;
|
||||
static float cameraAlpha;
|
||||
|
||||
|
||||
|
||||
static bool settings_inverseVertical;
|
||||
|
||||
static SDL_Window* window;
|
||||
|
||||
static bool showMouse;
|
||||
static bool exitGameLoop;
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace ZL
|
||||
@@ -1,248 +0,0 @@
|
||||
#include "Game.h"
|
||||
#include "AnimatedModel.h"
|
||||
#include "BoneAnimatedModel.h"
|
||||
#include "Utils.h"
|
||||
#include <iostream>
|
||||
#include "TextureManager.h"
|
||||
#include "TextModel.h"
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
namespace ZL {
|
||||
const char *CONST_ZIP_FILE = "";
|
||||
|
||||
Game::Game()
|
||||
: window(nullptr), glContext(nullptr), newTickCount(0), lastTickCount(0),
|
||||
resourcesLoaded(false), modelLoaded(false) {
|
||||
}
|
||||
|
||||
Game::~Game() {
|
||||
if (glContext) {
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
}
|
||||
if (window) {
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void Game::setup() {
|
||||
glContext = SDL_GL_CreateContext(ZL::Environment::window);
|
||||
|
||||
// Initialize renderer
|
||||
renderer.InitOpenGL();
|
||||
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Start for Android");
|
||||
|
||||
const char* testFiles[] = {
|
||||
"resources/spaceship004.txt",
|
||||
"shaders/default.vertex",
|
||||
"shaders/default_android.fragment",
|
||||
"shaders/defaultColor.vertex",
|
||||
"shaders/defaultColor_android.fragment",
|
||||
"resources/sship001x.bmp",
|
||||
nullptr
|
||||
};
|
||||
|
||||
for (int i = 0; testFiles[i] != nullptr; i++) {
|
||||
SDL_RWops* file = SDL_RWFromFile(testFiles[i], "rb");
|
||||
if (file) {
|
||||
Sint64 size = SDL_RWsize(file);
|
||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Found: %s (size: %lld)", testFiles[i], size);
|
||||
SDL_RWclose(file);
|
||||
} else {
|
||||
__android_log_print(ANDROID_LOG_WARN, "Game", "Not found: %s (SDL error: %s)",
|
||||
testFiles[i], SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Shaders...");
|
||||
|
||||
renderer.shaderManager.AddShaderFromFiles("default",
|
||||
"shaders/default.vertex",
|
||||
"shaders/default_android.fragment",
|
||||
CONST_ZIP_FILE);
|
||||
|
||||
renderer.shaderManager.AddShaderFromFiles("defaultColor",
|
||||
"shaders/defaultColor.vertex",
|
||||
"shaders/defaultColor_android.fragment",
|
||||
CONST_ZIP_FILE);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Textures...");
|
||||
try {
|
||||
spaceshipTexture = std::make_shared<Texture>(
|
||||
CreateTextureDataFromBmp32("resources/sship001x.bmp")
|
||||
);
|
||||
} catch (const std::exception& e) {
|
||||
spaceshipTexture = nullptr;
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Model...");
|
||||
|
||||
std::string modelPaths[] = {
|
||||
"resources/spaceship004.txt",
|
||||
""
|
||||
};
|
||||
|
||||
bool modelLoadSuccess = false;
|
||||
for (int i = 0; !modelLoadSuccess && !modelPaths[i].empty(); i++) {
|
||||
try {
|
||||
spaceshipBase = LoadFromTextFile02(modelPaths[i]);
|
||||
spaceshipBase.RotateByMatrix(QuatToMatrix(QuatFromRotateAroundY(M_PI / 2.0)));
|
||||
spaceship.AssignFrom(spaceshipBase);
|
||||
spaceship.RefreshVBO();
|
||||
modelLoaded = true;
|
||||
modelLoadSuccess = true;
|
||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Model loaded successfully from: %s", modelPaths[i].c_str());
|
||||
} catch (const std::exception& e) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "Game", "Failed to load model from %s: %s",
|
||||
modelPaths[i].c_str(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
resourcesLoaded = (spaceshipTexture != nullptr && modelLoaded);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "Setup failed: %s", e.what());
|
||||
resourcesLoaded = false;
|
||||
}
|
||||
#else
|
||||
// Десктопная версия
|
||||
renderer.shaderManager.AddShaderFromFiles("default",
|
||||
"./shaders/default.vertex",
|
||||
"./shaders/default_desktop.fragment",
|
||||
CONST_ZIP_FILE);
|
||||
renderer.shaderManager.AddShaderFromFiles("defaultColor",
|
||||
"./shaders/defaultColor.vertex",
|
||||
"./shaders/defaultColor_desktop.fragment",
|
||||
CONST_ZIP_FILE);
|
||||
|
||||
//Load texture
|
||||
spaceshipTexture = std::make_shared<Texture>(
|
||||
CreateTextureDataFromPng("./resources/sship001x.png"));
|
||||
spaceshipBase = LoadFromTextFile02("./resources/spaceship004.txt");
|
||||
spaceshipBase.RotateByMatrix(QuatToMatrix(QuatFromRotateAroundY(M_PI / 2.0)));
|
||||
spaceship.AssignFrom(spaceshipBase);
|
||||
spaceship.RefreshVBO();
|
||||
resourcesLoaded = true;
|
||||
modelLoaded = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Game::drawScene() {
|
||||
static const std::string defaultShaderName = "default";
|
||||
static const std::string vPositionName = "vPosition";
|
||||
static const std::string vTexCoordName = "vTexCoord";
|
||||
static const std::string textureUniformName = "Texture";
|
||||
|
||||
glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glViewport(0, 0, Environment::width, Environment::height);
|
||||
|
||||
if (!resourcesLoaded) {
|
||||
glClearColor(0.2f, 0.3f, 0.8f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.shaderManager.PushShader(defaultShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
renderer.EnableVertexAttribArray(vPositionName);
|
||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
||||
|
||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||
static_cast<float>(Environment::width) /
|
||||
static_cast<float>(Environment::height),
|
||||
1, 1000);
|
||||
renderer.PushMatrix();
|
||||
|
||||
renderer.LoadIdentity();
|
||||
renderer.TranslateMatrix({0, 0, -1.0f * Environment::zoom});
|
||||
renderer.RotateMatrix(QuatFromRotateAroundX(M_PI / 6.0));
|
||||
//renderer.RotateMatrix(QuatFromRotateAroundX(Environment::cameraAlpha));
|
||||
|
||||
if (spaceshipTexture) {
|
||||
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
||||
renderer.DrawVertexRenderStruct(spaceship);
|
||||
} else {
|
||||
renderer.DrawVertexRenderStruct(spaceship);
|
||||
}
|
||||
|
||||
renderer.PopMatrix();
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.DisableVertexAttribArray(vPositionName);
|
||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
|
||||
void Game::processTickCount() {
|
||||
|
||||
if (lastTickCount == 0) {
|
||||
lastTickCount = SDL_GetTicks64();
|
||||
return;
|
||||
}
|
||||
|
||||
newTickCount = SDL_GetTicks64();
|
||||
if (newTickCount - lastTickCount > CONST_TIMER_INTERVAL) {
|
||||
size_t delta = (newTickCount - lastTickCount > CONST_MAX_TIME_INTERVAL) ?
|
||||
CONST_MAX_TIME_INTERVAL : newTickCount - lastTickCount;
|
||||
|
||||
//gameObjects.updateScene(delta);
|
||||
|
||||
Environment::cameraAlpha = Environment::cameraAlpha + delta * M_PI / 10000.f;
|
||||
|
||||
lastTickCount = newTickCount;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::render() {
|
||||
SDL_GL_MakeCurrent(ZL::Environment::window, glContext);
|
||||
|
||||
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
drawScene();
|
||||
processTickCount();
|
||||
|
||||
SDL_GL_SwapWindow(ZL::Environment::window);
|
||||
}
|
||||
|
||||
void Game::update() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
Environment::exitGameLoop = true;
|
||||
|
||||
} else if (event.type == SDL_MOUSEWHEEL) {
|
||||
static const float zoomstep = 2.0f;
|
||||
if (event.wheel.y > 0) {
|
||||
Environment::zoom -= zoomstep;
|
||||
} else if (event.wheel.y < 0) {
|
||||
Environment::zoom += zoomstep;
|
||||
}
|
||||
if (Environment::zoom < zoomstep) {
|
||||
Environment::zoom = zoomstep;
|
||||
}
|
||||
/*if (Environment::zoom > 4) {
|
||||
Environment::zoom = 4;
|
||||
}*/
|
||||
|
||||
//this->modelMeshRender.data.Scale(0.5);
|
||||
//this->modelMeshRender.RefreshVBO();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
} // namespace ZL
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "Environment.h"
|
||||
#include "TextureManager.h"
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
class Game {
|
||||
public:
|
||||
Game();
|
||||
|
||||
~Game();
|
||||
|
||||
void setup();
|
||||
|
||||
void update();
|
||||
|
||||
void render();
|
||||
|
||||
bool shouldExit() const { return Environment::exitGameLoop; }
|
||||
|
||||
private:
|
||||
void processTickCount();
|
||||
|
||||
void drawScene();
|
||||
|
||||
SDL_Window *window;
|
||||
SDL_GLContext glContext;
|
||||
Renderer renderer;
|
||||
|
||||
size_t newTickCount;
|
||||
size_t lastTickCount;
|
||||
|
||||
bool resourcesLoaded;
|
||||
bool modelLoaded;
|
||||
|
||||
static const size_t CONST_TIMER_INTERVAL = 10;
|
||||
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
||||
|
||||
std::shared_ptr <Texture> spaceshipTexture;
|
||||
VertexDataStruct spaceshipBase;
|
||||
VertexRenderStruct spaceship;
|
||||
};
|
||||
|
||||
} // namespace ZL
|
||||
@@ -1,734 +0,0 @@
|
||||
#include "Math.h"
|
||||
|
||||
#include <exception>
|
||||
#include <cmath>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
Vector2f operator+(const Vector2f& x, const Vector2f& y)
|
||||
{
|
||||
Vector2f result;
|
||||
|
||||
result.v[0] = x.v[0] + y.v[0];
|
||||
result.v[1] = x.v[1] + y.v[1];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector2f operator-(const Vector2f& x, const Vector2f& y)
|
||||
{
|
||||
Vector2f result;
|
||||
|
||||
result.v[0] = x.v[0] - y.v[0];
|
||||
result.v[1] = x.v[1] - y.v[1];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3f operator+(const Vector3f& x, const Vector3f& y)
|
||||
{
|
||||
Vector3f result;
|
||||
|
||||
result.v[0] = x.v[0] + y.v[0];
|
||||
result.v[1] = x.v[1] + y.v[1];
|
||||
result.v[2] = x.v[2] + y.v[2];
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3f operator-(const Vector3f& x, const Vector3f& y)
|
||||
{
|
||||
Vector3f result;
|
||||
|
||||
result.v[0] = x.v[0] - y.v[0];
|
||||
result.v[1] = x.v[1] - y.v[1];
|
||||
result.v[2] = x.v[2] - y.v[2];
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector4f operator+(const Vector4f& x, const Vector4f& y)
|
||||
{
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = x.v[0] + y.v[0];
|
||||
result.v[1] = x.v[1] + y.v[1];
|
||||
result.v[2] = x.v[2] + y.v[2];
|
||||
result.v[3] = x.v[3] + y.v[3];
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector4f operator-(const Vector4f& x, const Vector4f& y)
|
||||
{
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = x.v[0] - y.v[0];
|
||||
result.v[1] = x.v[1] - y.v[1];
|
||||
result.v[2] = x.v[2] - y.v[2];
|
||||
result.v[3] = x.v[3] - y.v[3];
|
||||
return result;
|
||||
}
|
||||
|
||||
Matrix3f Matrix3f::Identity()
|
||||
{
|
||||
Matrix3f r;
|
||||
|
||||
r.m[0] = 1.f;
|
||||
r.m[1] = 0.f;
|
||||
r.m[2] = 0.f;
|
||||
|
||||
r.m[3] = 0.f;
|
||||
r.m[4] = 1.f;
|
||||
r.m[5] = 0.f;
|
||||
|
||||
r.m[6] = 0.f;
|
||||
r.m[7] = 0.f;
|
||||
r.m[8] = 1.f;
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
Matrix4f Matrix4f::Identity()
|
||||
{
|
||||
Matrix4f r;
|
||||
|
||||
r.m[0] = 1.f;
|
||||
r.m[1] = 0.f;
|
||||
r.m[2] = 0.f;
|
||||
r.m[3] = 0.f;
|
||||
|
||||
r.m[4] = 0.f;
|
||||
r.m[5] = 1.f;
|
||||
r.m[6] = 0.f;
|
||||
r.m[7] = 0.f;
|
||||
|
||||
r.m[8] = 0.f;
|
||||
r.m[9] = 0.f;
|
||||
r.m[10] = 1.f;
|
||||
r.m[11] = 0.f;
|
||||
|
||||
r.m[12] = 0.f;
|
||||
r.m[13] = 0.f;
|
||||
r.m[14] = 0.f;
|
||||
r.m[15] = 1.f;
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
Matrix4f operator*(const Matrix4f& m1, const Matrix4f& m2)
|
||||
{
|
||||
Matrix4f r;
|
||||
|
||||
r.m[0] = m1.m[0] * m2.m[0] + m1.m[4] * m2.m[1] + m1.m[8] * m2.m[2] + m1.m[12] * m2.m[3];
|
||||
r.m[1] = m1.m[1] * m2.m[0] + m1.m[5] * m2.m[1] + m1.m[9] * m2.m[2] + m1.m[13] * m2.m[3];
|
||||
r.m[2] = m1.m[2] * m2.m[0] + m1.m[6] * m2.m[1] + m1.m[10] * m2.m[2] + m1.m[14] * m2.m[3];
|
||||
r.m[3] = m1.m[3] * m2.m[0] + m1.m[7] * m2.m[1] + m1.m[11] * m2.m[2] + m1.m[15] * m2.m[3];
|
||||
|
||||
r.m[4] = m1.m[0] * m2.m[4] + m1.m[4] * m2.m[5] + m1.m[8] * m2.m[6] + m1.m[12] * m2.m[7];
|
||||
r.m[5] = m1.m[1] * m2.m[4] + m1.m[5] * m2.m[5] + m1.m[9] * m2.m[6] + m1.m[13] * m2.m[7];
|
||||
r.m[6] = m1.m[2] * m2.m[4] + m1.m[6] * m2.m[5] + m1.m[10] * m2.m[6] + m1.m[14] * m2.m[7];
|
||||
r.m[7] = m1.m[3] * m2.m[4] + m1.m[7] * m2.m[5] + m1.m[11] * m2.m[6] + m1.m[15] * m2.m[7];
|
||||
|
||||
|
||||
r.m[8] = m1.m[0] * m2.m[8] + m1.m[4] * m2.m[9] + m1.m[8] * m2.m[10] + m1.m[12] * m2.m[11];
|
||||
r.m[9] = m1.m[1] * m2.m[8] + m1.m[5] * m2.m[9] + m1.m[9] * m2.m[10] + m1.m[13] * m2.m[11];
|
||||
r.m[10] = m1.m[2] * m2.m[8] + m1.m[6] * m2.m[9] + m1.m[10] * m2.m[10] + m1.m[14] * m2.m[11];
|
||||
r.m[11] = m1.m[3] * m2.m[8] + m1.m[7] * m2.m[9] + m1.m[11] * m2.m[10] + m1.m[15] * m2.m[11];
|
||||
|
||||
r.m[12] = m1.m[0] * m2.m[12] + m1.m[4] * m2.m[13] + m1.m[8] * m2.m[14] + m1.m[12] * m2.m[15];
|
||||
r.m[13] = m1.m[1] * m2.m[12] + m1.m[5] * m2.m[13] + m1.m[9] * m2.m[14] + m1.m[13] * m2.m[15];
|
||||
r.m[14] = m1.m[2] * m2.m[12] + m1.m[6] * m2.m[13] + m1.m[10] * m2.m[14] + m1.m[14] * m2.m[15];
|
||||
r.m[15] = m1.m[3] * m2.m[12] + m1.m[7] * m2.m[13] + m1.m[11] * m2.m[14] + m1.m[15] * m2.m[15];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix4f MakeOrthoMatrix(float width, float height, float zNear, float zFar)
|
||||
{
|
||||
float depthRange = zFar - zNear;
|
||||
|
||||
if (depthRange <= 0)
|
||||
{
|
||||
throw std::runtime_error("zFar must be greater than zNear");
|
||||
}
|
||||
|
||||
Matrix4f r;
|
||||
|
||||
r.m[0] = 2.f / width;
|
||||
r.m[1] = 0;
|
||||
r.m[2] = 0;
|
||||
r.m[3] = 0;
|
||||
|
||||
r.m[4] = 0;
|
||||
r.m[5] = 2.f / height;
|
||||
r.m[6] = 0;
|
||||
r.m[7] = 0;
|
||||
|
||||
r.m[8] = 0;
|
||||
r.m[9] = 0;
|
||||
r.m[10] = -1 / depthRange;
|
||||
r.m[11] = 0;
|
||||
|
||||
r.m[12] = -1;
|
||||
r.m[13] = -1;
|
||||
r.m[14] = zNear / depthRange;
|
||||
r.m[15] = 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix4f MakePerspectiveMatrix(float fovY, float aspectRatio, float zNear, float zFar)
|
||||
{
|
||||
float tanHalfFovy = tan(fovY / 2.f);
|
||||
Matrix4f r;
|
||||
|
||||
if (zNear >= zFar || aspectRatio == 0)
|
||||
{
|
||||
throw std::runtime_error("Invalid perspective parameters");
|
||||
}
|
||||
|
||||
r.m[0] = 1.f / (aspectRatio * tanHalfFovy);
|
||||
r.m[1] = 0;
|
||||
r.m[2] = 0;
|
||||
r.m[3] = 0;
|
||||
|
||||
r.m[4] = 0;
|
||||
r.m[5] = 1.f / (tanHalfFovy);
|
||||
r.m[6] = 0;
|
||||
r.m[7] = 0;
|
||||
|
||||
r.m[8] = 0;
|
||||
r.m[9] = 0;
|
||||
r.m[10] = -(zFar + zNear) / (zFar - zNear);
|
||||
r.m[11] = -1;
|
||||
|
||||
r.m[12] = 0;
|
||||
r.m[13] = 0;
|
||||
r.m[14] = -(2.f * zFar * zNear) / (zFar - zNear);
|
||||
r.m[15] = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix3f QuatToMatrix(const Vector4f& q)
|
||||
{
|
||||
Matrix3f m;
|
||||
|
||||
float wx, wy, wz, xx, yy, yz, xy, xz, zz, s, x2, y2, z2;
|
||||
|
||||
s = 2.0f / (q.v[0] * q.v[0] + q.v[1] * q.v[1] + q.v[2] * q.v[2] + q.v[3] * q.v[3]);
|
||||
|
||||
|
||||
x2 = q.v[0] * s;
|
||||
y2 = q.v[1] * s;
|
||||
z2 = q.v[2] * s;
|
||||
|
||||
wx = q.v[3] * x2; wy = q.v[3] * y2; wz = q.v[3] * z2;
|
||||
xx = q.v[0] * x2; xy = q.v[1] * x2; xz = q.v[2] * x2;
|
||||
yy = q.v[1] * y2; yz = q.v[2] * y2;
|
||||
zz = q.v[2] * z2;
|
||||
|
||||
m.m[0] = 1.0f - (yy + zz);
|
||||
m.m[1] = xy + wz;
|
||||
m.m[2] = xz - wy;
|
||||
|
||||
m.m[3] = xy - wz;
|
||||
m.m[4] = 1.0f - (xx + zz);
|
||||
m.m[5] = yz + wx;
|
||||
|
||||
m.m[6] = xz + wy;
|
||||
m.m[7] = yz - wx;
|
||||
m.m[8] = 1.0f - (xx + yy);
|
||||
|
||||
return m;
|
||||
|
||||
}
|
||||
|
||||
Vector4f MatrixToQuat(const Matrix3f& m)
|
||||
{
|
||||
Vector4f r;
|
||||
float trace = m.m[0] + m.m[4] + m.m[8];
|
||||
|
||||
if (trace > 0)
|
||||
{
|
||||
float s = 0.5f / sqrtf(trace + 1.0f);
|
||||
r.v[3] = 0.25f / s;
|
||||
r.v[0] = (m.m[5] - m.m[7]) * s;
|
||||
r.v[1] = (m.m[6] - m.m[2]) * s;
|
||||
r.v[2] = (m.m[1] - m.m[3]) * s;
|
||||
}
|
||||
else if (m.m[0] > m.m[4] && m.m[0] > m.m[8])
|
||||
{
|
||||
float s = 2.0f * sqrtf(1.0f + m.m[0] - m.m[4] - m.m[8]);
|
||||
r.v[3] = (m.m[5] - m.m[7]) / s;
|
||||
r.v[0] = 0.25f * s;
|
||||
r.v[1] = (m.m[1] + m.m[3]) / s;
|
||||
r.v[2] = (m.m[6] + m.m[2]) / s;
|
||||
}
|
||||
else if (m.m[4] > m.m[8])
|
||||
{
|
||||
float s = 2.0f * sqrtf(1.0f + m.m[4] - m.m[0] - m.m[8]);
|
||||
r.v[3] = (m.m[6] - m.m[2]) / s;
|
||||
r.v[0] = (m.m[1] + m.m[3]) / s;
|
||||
r.v[1] = 0.25f * s;
|
||||
r.v[2] = (m.m[5] + m.m[7]) / s;
|
||||
}
|
||||
else
|
||||
{
|
||||
float s = 2.0f * sqrtf(1.0f + m.m[8] - m.m[0] - m.m[4]);
|
||||
r.v[3] = (m.m[1] - m.m[3]) / s;
|
||||
r.v[0] = (m.m[6] + m.m[2]) / s;
|
||||
r.v[1] = (m.m[5] + m.m[7]) / s;
|
||||
r.v[2] = 0.25f * s;
|
||||
}
|
||||
|
||||
return r.normalized();
|
||||
}
|
||||
|
||||
Vector4f QuatFromRotateAroundX(float angle)
|
||||
{
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = sinf(angle * 0.5f);
|
||||
result.v[1] = 0.f;
|
||||
result.v[2] = 0.f;
|
||||
result.v[3] = cosf(angle * 0.5f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector4f QuatFromRotateAroundY(float angle)
|
||||
{
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = 0.f;
|
||||
result.v[1] = sinf(angle * 0.5f);
|
||||
result.v[2] = 0.f;
|
||||
result.v[3] = cosf(angle * 0.5f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector4f QuatFromRotateAroundZ(float angle)
|
||||
{
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = 0.f;
|
||||
result.v[1] = 0.f;
|
||||
result.v[2] = sinf(angle * 0.5f);
|
||||
result.v[3] = cosf(angle * 0.5f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Matrix3f TransposeMatrix(const Matrix3f& m)
|
||||
{
|
||||
Matrix3f r;
|
||||
r.m[0] = m.m[0];
|
||||
r.m[1] = m.m[3];
|
||||
r.m[2] = m.m[6];
|
||||
r.m[3] = m.m[1];
|
||||
r.m[4] = m.m[4];
|
||||
r.m[5] = m.m[7];
|
||||
r.m[6] = m.m[2];
|
||||
r.m[7] = m.m[5];
|
||||
r.m[8] = m.m[8];
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix3f InverseMatrix(const Matrix3f& m)
|
||||
{
|
||||
float d;
|
||||
Matrix3f r;
|
||||
|
||||
d = m.m[0] * (m.m[4] * m.m[8] - m.m[5] * m.m[7]);
|
||||
d -= m.m[1] * (m.m[3] * m.m[8] - m.m[6] * m.m[5]);
|
||||
d += m.m[2] * (m.m[3] * m.m[7] - m.m[6] * m.m[4]);
|
||||
|
||||
if (fabs(d) < 0.01f)
|
||||
{
|
||||
throw std::runtime_error("Error: matrix cannot be inversed!");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
r.m[0] = (m.m[4] * m.m[8] - m.m[5] * m.m[7]) / d;
|
||||
r.m[1] = -(m.m[1] * m.m[8] - m.m[2] * m.m[7]) / d;
|
||||
r.m[2] = (m.m[1] * m.m[5] - m.m[2] * m.m[4]) / d;
|
||||
|
||||
r.m[3] = -(m.m[3] * m.m[8] - m.m[5] * m.m[6]) / d;
|
||||
r.m[4] = (m.m[0] * m.m[8] - m.m[2] * m.m[6]) / d;
|
||||
r.m[5] = -(m.m[0] * m.m[5] - m.m[2] * m.m[3]) / d;
|
||||
|
||||
r.m[6] = (m.m[3] * m.m[7] - m.m[6] * m.m[4]) / d;
|
||||
r.m[7] = -(m.m[0] * m.m[7] - m.m[6] * m.m[1]) / d;
|
||||
r.m[8] = (m.m[0] * m.m[4] - m.m[1] * m.m[3]) / d;
|
||||
|
||||
};
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
Matrix4f InverseMatrix(const Matrix4f& mat)
|
||||
{
|
||||
Matrix4f inv;
|
||||
float det;
|
||||
|
||||
inv.m[0] = mat.m[5] * mat.m[10] * mat.m[15] -
|
||||
mat.m[5] * mat.m[11] * mat.m[14] -
|
||||
mat.m[9] * mat.m[6] * mat.m[15] +
|
||||
mat.m[9] * mat.m[7] * mat.m[14] +
|
||||
mat.m[13] * mat.m[6] * mat.m[11] -
|
||||
mat.m[13] * mat.m[7] * mat.m[10];
|
||||
|
||||
inv.m[4] = -mat.m[4] * mat.m[10] * mat.m[15] +
|
||||
mat.m[4] * mat.m[11] * mat.m[14] +
|
||||
mat.m[8] * mat.m[6] * mat.m[15] -
|
||||
mat.m[8] * mat.m[7] * mat.m[14] -
|
||||
mat.m[12] * mat.m[6] * mat.m[11] +
|
||||
mat.m[12] * mat.m[7] * mat.m[10];
|
||||
|
||||
inv.m[8] = mat.m[4] * mat.m[9] * mat.m[15] -
|
||||
mat.m[4] * mat.m[11] * mat.m[13] -
|
||||
mat.m[8] * mat.m[5] * mat.m[15] +
|
||||
mat.m[8] * mat.m[7] * mat.m[13] +
|
||||
mat.m[12] * mat.m[5] * mat.m[11] -
|
||||
mat.m[12] * mat.m[7] * mat.m[9];
|
||||
|
||||
inv.m[12] = -mat.m[4] * mat.m[9] * mat.m[14] +
|
||||
mat.m[4] * mat.m[10] * mat.m[13] +
|
||||
mat.m[8] * mat.m[5] * mat.m[14] -
|
||||
mat.m[8] * mat.m[6] * mat.m[13] -
|
||||
mat.m[12] * mat.m[5] * mat.m[10] +
|
||||
mat.m[12] * mat.m[6] * mat.m[9];
|
||||
|
||||
inv.m[1] = -mat.m[1] * mat.m[10] * mat.m[15] +
|
||||
mat.m[1] * mat.m[11] * mat.m[14] +
|
||||
mat.m[9] * mat.m[2] * mat.m[15] -
|
||||
mat.m[9] * mat.m[3] * mat.m[14] -
|
||||
mat.m[13] * mat.m[2] * mat.m[11] +
|
||||
mat.m[13] * mat.m[3] * mat.m[10];
|
||||
|
||||
inv.m[5] = mat.m[0] * mat.m[10] * mat.m[15] -
|
||||
mat.m[0] * mat.m[11] * mat.m[14] -
|
||||
mat.m[8] * mat.m[2] * mat.m[15] +
|
||||
mat.m[8] * mat.m[3] * mat.m[14] +
|
||||
mat.m[12] * mat.m[2] * mat.m[11] -
|
||||
mat.m[12] * mat.m[3] * mat.m[10];
|
||||
|
||||
inv.m[9] = -mat.m[0] * mat.m[9] * mat.m[15] +
|
||||
mat.m[0] * mat.m[11] * mat.m[13] +
|
||||
mat.m[8] * mat.m[1] * mat.m[15] -
|
||||
mat.m[8] * mat.m[3] * mat.m[13] -
|
||||
mat.m[12] * mat.m[1] * mat.m[11] +
|
||||
mat.m[12] * mat.m[3] * mat.m[9];
|
||||
|
||||
inv.m[13] = mat.m[0] * mat.m[9] * mat.m[14] -
|
||||
mat.m[0] * mat.m[10] * mat.m[13] -
|
||||
mat.m[8] * mat.m[1] * mat.m[14] +
|
||||
mat.m[8] * mat.m[2] * mat.m[13] +
|
||||
mat.m[12] * mat.m[1] * mat.m[10] -
|
||||
mat.m[12] * mat.m[2] * mat.m[9];
|
||||
|
||||
inv.m[2] = mat.m[1] * mat.m[6] * mat.m[15] -
|
||||
mat.m[1] * mat.m[7] * mat.m[14] -
|
||||
mat.m[5] * mat.m[2] * mat.m[15] +
|
||||
mat.m[5] * mat.m[3] * mat.m[14] +
|
||||
mat.m[13] * mat.m[2] * mat.m[7] -
|
||||
mat.m[13] * mat.m[3] * mat.m[6];
|
||||
|
||||
inv.m[6] = -mat.m[0] * mat.m[6] * mat.m[15] +
|
||||
mat.m[0] * mat.m[7] * mat.m[14] +
|
||||
mat.m[4] * mat.m[2] * mat.m[15] -
|
||||
mat.m[4] * mat.m[3] * mat.m[14] -
|
||||
mat.m[12] * mat.m[2] * mat.m[7] +
|
||||
mat.m[12] * mat.m[3] * mat.m[6];
|
||||
|
||||
inv.m[10] = mat.m[0] * mat.m[5] * mat.m[15] -
|
||||
mat.m[0] * mat.m[7] * mat.m[13] -
|
||||
mat.m[4] * mat.m[1] * mat.m[15] +
|
||||
mat.m[4] * mat.m[3] * mat.m[13] +
|
||||
mat.m[12] * mat.m[1] * mat.m[7] -
|
||||
mat.m[12] * mat.m[3] * mat.m[5];
|
||||
|
||||
inv.m[14] = -mat.m[0] * mat.m[5] * mat.m[14] +
|
||||
mat.m[0] * mat.m[6] * mat.m[13] +
|
||||
mat.m[4] * mat.m[1] * mat.m[14] -
|
||||
mat.m[4] * mat.m[2] * mat.m[13] -
|
||||
mat.m[12] * mat.m[1] * mat.m[6] +
|
||||
mat.m[12] * mat.m[2] * mat.m[5];
|
||||
|
||||
inv.m[3] = -mat.m[1] * mat.m[6] * mat.m[11] +
|
||||
mat.m[1] * mat.m[7] * mat.m[10] +
|
||||
mat.m[5] * mat.m[2] * mat.m[11] -
|
||||
mat.m[5] * mat.m[3] * mat.m[10] -
|
||||
mat.m[9] * mat.m[2] * mat.m[7] +
|
||||
mat.m[9] * mat.m[3] * mat.m[6];
|
||||
|
||||
inv.m[7] = mat.m[0] * mat.m[6] * mat.m[11] -
|
||||
mat.m[0] * mat.m[7] * mat.m[10] -
|
||||
mat.m[4] * mat.m[2] * mat.m[11] +
|
||||
mat.m[4] * mat.m[3] * mat.m[10] +
|
||||
mat.m[8] * mat.m[2] * mat.m[7] -
|
||||
mat.m[8] * mat.m[3] * mat.m[6];
|
||||
|
||||
inv.m[11] = -mat.m[0] * mat.m[5] * mat.m[11] +
|
||||
mat.m[0] * mat.m[7] * mat.m[9] +
|
||||
mat.m[4] * mat.m[1] * mat.m[11] -
|
||||
mat.m[4] * mat.m[3] * mat.m[9] -
|
||||
mat.m[8] * mat.m[1] * mat.m[7] +
|
||||
mat.m[8] * mat.m[3] * mat.m[5];
|
||||
|
||||
inv.m[15] = mat.m[0] * mat.m[5] * mat.m[10] -
|
||||
mat.m[0] * mat.m[6] * mat.m[9] -
|
||||
mat.m[4] * mat.m[1] * mat.m[10] +
|
||||
mat.m[4] * mat.m[2] * mat.m[9] +
|
||||
mat.m[8] * mat.m[1] * mat.m[6] -
|
||||
mat.m[8] * mat.m[2] * mat.m[5];
|
||||
|
||||
// ��������� �����������
|
||||
det = mat.m[0] * inv.m[0] + mat.m[1] * inv.m[4] + mat.m[2] * inv.m[8] + mat.m[3] * inv.m[12];
|
||||
|
||||
if (std::fabs(det) < 0.01f)
|
||||
{
|
||||
throw std::runtime_error("Error: matrix cannot be inversed!");
|
||||
}
|
||||
|
||||
// ����� ��� �������� �� �����������
|
||||
det = 1.0f / det;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
inv.m[i] *= det;
|
||||
}
|
||||
|
||||
return inv;
|
||||
}
|
||||
|
||||
Matrix3f CreateZRotationMatrix(float angle)
|
||||
{
|
||||
Matrix3f result = Matrix3f::Identity();
|
||||
|
||||
result.m[0] = cosf(angle);
|
||||
result.m[1] = -sinf(angle);
|
||||
result.m[3] = sinf(angle);
|
||||
result.m[4] = cosf(angle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Matrix4f MultMatrixMatrix(const Matrix4f& m1, const Matrix4f& m2)
|
||||
{
|
||||
Matrix4f rx;
|
||||
|
||||
rx.m[0] = m1.m[0] * m2.m[0] + m1.m[4] * m2.m[1] + m1.m[8] * m2.m[2] + m1.m[12] * m2.m[3];
|
||||
rx.m[1] = m1.m[1] * m2.m[0] + m1.m[5] * m2.m[1] + m1.m[9] * m2.m[2] + m1.m[13] * m2.m[3];
|
||||
rx.m[2] = m1.m[2] * m2.m[0] + m1.m[6] * m2.m[1] + m1.m[10] * m2.m[2] + m1.m[14] * m2.m[3];
|
||||
rx.m[3] = m1.m[3] * m2.m[0] + m1.m[7] * m2.m[1] + m1.m[11] * m2.m[2] + m1.m[15] * m2.m[3];
|
||||
|
||||
rx.m[4] = m1.m[0] * m2.m[4] + m1.m[4] * m2.m[5] + m1.m[8] * m2.m[6] + m1.m[12] * m2.m[7];
|
||||
rx.m[5] = m1.m[1] * m2.m[4] + m1.m[5] * m2.m[5] + m1.m[9] * m2.m[6] + m1.m[13] * m2.m[7];
|
||||
rx.m[6] = m1.m[2] * m2.m[4] + m1.m[6] * m2.m[5] + m1.m[10] * m2.m[6] + m1.m[14] * m2.m[7];
|
||||
rx.m[7] = m1.m[3] * m2.m[4] + m1.m[7] * m2.m[5] + m1.m[11] * m2.m[6] + m1.m[15] * m2.m[7];
|
||||
|
||||
|
||||
rx.m[8] = m1.m[0] * m2.m[8] + m1.m[4] * m2.m[9] + m1.m[8] * m2.m[10] + m1.m[12] * m2.m[11];
|
||||
rx.m[9] = m1.m[1] * m2.m[8] + m1.m[5] * m2.m[9] + m1.m[9] * m2.m[10] + m1.m[13] * m2.m[11];
|
||||
rx.m[10] = m1.m[2] * m2.m[8] + m1.m[6] * m2.m[9] + m1.m[10] * m2.m[10] + m1.m[14] * m2.m[11];
|
||||
rx.m[11] = m1.m[3] * m2.m[8] + m1.m[7] * m2.m[9] + m1.m[11] * m2.m[10] + m1.m[15] * m2.m[11];
|
||||
|
||||
rx.m[12] = m1.m[0] * m2.m[12] + m1.m[4] * m2.m[13] + m1.m[8] * m2.m[14] + m1.m[12] * m2.m[15];
|
||||
rx.m[13] = m1.m[1] * m2.m[12] + m1.m[5] * m2.m[13] + m1.m[9] * m2.m[14] + m1.m[13] * m2.m[15];
|
||||
rx.m[14] = m1.m[2] * m2.m[12] + m1.m[6] * m2.m[13] + m1.m[10] * m2.m[14] + m1.m[14] * m2.m[15];
|
||||
rx.m[15] = m1.m[3] * m2.m[12] + m1.m[7] * m2.m[13] + m1.m[11] * m2.m[14] + m1.m[15] * m2.m[15];
|
||||
|
||||
return rx;
|
||||
}
|
||||
|
||||
Matrix3f MultMatrixMatrix(const Matrix3f& m1, const Matrix3f& m2)
|
||||
{
|
||||
Matrix3f r;
|
||||
|
||||
r.m[0] = m1.m[0] * m2.m[0] + m1.m[3] * m2.m[1] + m1.m[6] * m2.m[2];
|
||||
r.m[1] = m1.m[1] * m2.m[0] + m1.m[4] * m2.m[1] + m1.m[7] * m2.m[2];
|
||||
r.m[2] = m1.m[2] * m2.m[0] + m1.m[5] * m2.m[1] + m1.m[8] * m2.m[2];
|
||||
|
||||
r.m[3] = m1.m[0] * m2.m[3] + m1.m[3] * m2.m[4] + m1.m[6] * m2.m[5];
|
||||
r.m[4] = m1.m[1] * m2.m[3] + m1.m[4] * m2.m[4] + m1.m[7] * m2.m[5];
|
||||
r.m[5] = m1.m[2] * m2.m[3] + m1.m[5] * m2.m[4] + m1.m[8] * m2.m[5];
|
||||
|
||||
r.m[6] = m1.m[0] * m2.m[6] + m1.m[3] * m2.m[7] + m1.m[6] * m2.m[8] ;
|
||||
r.m[7] = m1.m[1] * m2.m[6] + m1.m[4] * m2.m[7] + m1.m[7] * m2.m[8];
|
||||
r.m[8] = m1.m[2] * m2.m[6] + m1.m[5] * m2.m[7] + m1.m[8] * m2.m[8];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix3f MakeTranslationMatrix(const Vector3f& p)
|
||||
{
|
||||
Matrix3f r = Matrix3f::Identity();
|
||||
|
||||
r.m[12] = p.v[0];
|
||||
r.m[13] = p.v[1];
|
||||
r.m[14] = p.v[2];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix3f MakeScaleMatrix(float scale)
|
||||
{
|
||||
Matrix3f r = Matrix3f::Identity();
|
||||
|
||||
r.m[0] = scale;
|
||||
r.m[5] = scale;
|
||||
r.m[10] = scale;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix3f MakeRotationMatrix(const Vector3f& p)
|
||||
{
|
||||
Matrix3f r = Matrix3f::Identity();
|
||||
|
||||
r.m[12] = p.v[0];
|
||||
r.m[13] = p.v[1];
|
||||
r.m[14] = p.v[2];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector3f operator*(Vector3f v, float scale)
|
||||
{
|
||||
Vector3f r = v;
|
||||
|
||||
r.v[0] = v.v[0] * scale;
|
||||
r.v[1] = v.v[1] * scale;
|
||||
r.v[2] = v.v[2] * scale;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector4f operator*(Vector4f v, float scale)
|
||||
{
|
||||
Vector4f r = v;
|
||||
|
||||
r.v[0] = v.v[0] * scale;
|
||||
r.v[1] = v.v[1] * scale;
|
||||
r.v[2] = v.v[2] * scale;
|
||||
r.v[3] = v.v[3] * scale;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector3f MultVectorMatrix(Vector3f v, Matrix3f mt)
|
||||
{
|
||||
Vector3f r;
|
||||
|
||||
r.v[0] = v.v[0] * mt.m[0] + v.v[1] * mt.m[1] + v.v[2] * mt.m[2];
|
||||
r.v[1] = v.v[0] * mt.m[3] + v.v[1] * mt.m[4] + v.v[2] * mt.m[5];
|
||||
r.v[2] = v.v[0] * mt.m[6] + v.v[1] * mt.m[7] + v.v[2] * mt.m[8];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector4f MultVectorMatrix(Vector4f v, Matrix4f mt)
|
||||
{
|
||||
Vector4f r;
|
||||
|
||||
r.v[0] = v.v[0] * mt.m[0] + v.v[1] * mt.m[1] + v.v[2] * mt.m[2] + v.v[3] * mt.m[3];
|
||||
r.v[1] = v.v[0] * mt.m[4] + v.v[1] * mt.m[5] + v.v[2] * mt.m[6] + v.v[3] * mt.m[7];
|
||||
r.v[2] = v.v[0] * mt.m[8] + v.v[1] * mt.m[9] + v.v[2] * mt.m[10] + v.v[3] * mt.m[11];
|
||||
r.v[3] = v.v[0] * mt.m[12] + v.v[1] * mt.m[13] + v.v[2] * mt.m[14] + v.v[3] * mt.m[15];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector4f MultMatrixVector(Matrix4f mt, Vector4f v)
|
||||
{
|
||||
Vector4f r;
|
||||
|
||||
r.v[0] = v.v[0] * mt.m[0] + v.v[1] * mt.m[4] + v.v[2] * mt.m[8] + v.v[3] * mt.m[12];
|
||||
r.v[1] = v.v[0] * mt.m[1] + v.v[1] * mt.m[5] + v.v[2] * mt.m[9] + v.v[3] * mt.m[13];
|
||||
r.v[2] = v.v[0] * mt.m[2] + v.v[1] * mt.m[6] + v.v[2] * mt.m[10] + v.v[3] * mt.m[14];
|
||||
r.v[3] = v.v[0] * mt.m[3] + v.v[1] * mt.m[7] + v.v[2] * mt.m[11] + v.v[3] * mt.m[15];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector4f slerp(const Vector4f& q1, const Vector4f& q2, float t)
|
||||
{
|
||||
const float epsilon = 1e-6f;
|
||||
|
||||
// Нормализация входных кватернионов
|
||||
Vector4f q1_norm = q1.normalized();
|
||||
Vector4f q2_norm = q2.normalized();
|
||||
|
||||
float cosTheta = q1_norm.dot(q2_norm);
|
||||
|
||||
// Если q1 и q2 близки к противоположным направлениям, корректируем q2
|
||||
Vector4f q2_adjusted = q2_norm;
|
||||
if (cosTheta < 0.0f) {
|
||||
q2_adjusted.v[0] = -q2_adjusted.v[0];
|
||||
q2_adjusted.v[1] = -q2_adjusted.v[1];
|
||||
q2_adjusted.v[2] = -q2_adjusted.v[2];
|
||||
q2_adjusted.v[3] = -q2_adjusted.v[3];
|
||||
cosTheta = -cosTheta;
|
||||
}
|
||||
|
||||
// Если кватернионы близки, используем линейную интерполяцию
|
||||
if (cosTheta > 1.0f - epsilon) {
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = q1_norm.v[0] + t * (q2_adjusted.v[0] - q1_norm.v[0]);
|
||||
result.v[1] = q1_norm.v[1] + t * (q2_adjusted.v[1] - q1_norm.v[1]);
|
||||
result.v[2] = q1_norm.v[2] + t * (q2_adjusted.v[2] - q1_norm.v[2]);
|
||||
result.v[3] = q1_norm.v[3] + t * (q2_adjusted.v[3] - q1_norm.v[3]);
|
||||
|
||||
return result.normalized();
|
||||
}
|
||||
|
||||
// Иначе используем сферическую интерполяцию
|
||||
float theta = std::acos(cosTheta);
|
||||
float sinTheta = std::sin(theta);
|
||||
|
||||
float coeff1 = std::sin((1.0f - t) * theta) / sinTheta;
|
||||
float coeff2 = std::sin(t * theta) / sinTheta;
|
||||
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = coeff1 * q1_norm.v[0] + coeff2 * q2_adjusted.v[0];
|
||||
result.v[1] = coeff1 * q1_norm.v[1] + coeff2 * q2_adjusted.v[1];
|
||||
result.v[2] = coeff1 * q1_norm.v[2] + coeff2 * q2_adjusted.v[2];
|
||||
result.v[3] = coeff1 * q1_norm.v[3] + coeff2 * q2_adjusted.v[3];
|
||||
|
||||
return result.normalized();
|
||||
}
|
||||
|
||||
Matrix4f MakeMatrix4x4(const Matrix3f& m, const Vector3f pos)
|
||||
{
|
||||
Matrix4f r;
|
||||
|
||||
r.m[0] = m.m[0];
|
||||
r.m[1] = m.m[1];
|
||||
r.m[2] = m.m[2];
|
||||
r.m[3] = 0;
|
||||
|
||||
r.m[4] = m.m[3];
|
||||
r.m[5] = m.m[4];
|
||||
r.m[6] = m.m[5];
|
||||
r.m[7] = 0;
|
||||
|
||||
r.m[8] = m.m[6];
|
||||
r.m[9] = m.m[7];
|
||||
r.m[10] = m.m[8];
|
||||
r.m[11] = 0;
|
||||
|
||||
r.m[12] = pos.v[0];
|
||||
r.m[13] = pos.v[1];
|
||||
r.m[14] = pos.v[2];
|
||||
r.m[15] = 1.0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
@@ -1,110 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
struct Vector4f
|
||||
{
|
||||
std::array<float, 4> v = { 0.f, 0.f, 0.f, 0.f };
|
||||
|
||||
Vector4f normalized() const {
|
||||
double norm = std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
|
||||
Vector4f r;
|
||||
|
||||
r.v[0] = v[0] / norm;
|
||||
r.v[1] = v[1] / norm;
|
||||
r.v[2] = v[2] / norm;
|
||||
r.v[3] = v[3] / norm;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
double dot(const Vector4f& other) const {
|
||||
return v[0] * other.v[0] + v[1] * other.v[1] + v[2] * other.v[2] + v[3] * other.v[3];
|
||||
}
|
||||
};
|
||||
|
||||
struct Vector3f
|
||||
{
|
||||
std::array<float, 3> v = { 0.f, 0.f, 0.f };
|
||||
};
|
||||
|
||||
struct Vector2f
|
||||
{
|
||||
std::array<float, 2> v = {0.f, 0.f};
|
||||
};
|
||||
|
||||
Vector2f operator+(const Vector2f& x, const Vector2f& y);
|
||||
|
||||
Vector2f operator-(const Vector2f& x, const Vector2f& y);
|
||||
|
||||
Vector3f operator+(const Vector3f& x, const Vector3f& y);
|
||||
|
||||
Vector3f operator-(const Vector3f& x, const Vector3f& y);
|
||||
Vector4f operator+(const Vector4f& x, const Vector4f& y);
|
||||
|
||||
Vector4f operator-(const Vector4f& x, const Vector4f& y);
|
||||
|
||||
|
||||
struct Matrix3f
|
||||
{
|
||||
std::array<float, 9> m = { 0.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.f, };
|
||||
|
||||
static Matrix3f Identity();
|
||||
};
|
||||
|
||||
struct Matrix4f
|
||||
{
|
||||
std::array<float, 16> m = { 0.f, 0.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.f, 0.f };
|
||||
|
||||
static Matrix4f Identity();
|
||||
|
||||
float& operator()(int row, int col) {
|
||||
//return m[row * 4 + col]; //OpenGL specific
|
||||
return m[col * 4 + row];
|
||||
}
|
||||
|
||||
const float& operator()(int row, int col) const {
|
||||
//return m[row * 4 + col];
|
||||
return m[col * 4 + row];
|
||||
}
|
||||
};
|
||||
|
||||
Matrix4f operator*(const Matrix4f& m1, const Matrix4f& m2);
|
||||
|
||||
Matrix4f MakeOrthoMatrix(float width, float height, float zNear, float zFar);
|
||||
|
||||
Matrix4f MakePerspectiveMatrix(float fovY, float aspectRatio, float zNear, float zFar);
|
||||
|
||||
Matrix3f QuatToMatrix(const Vector4f& q);
|
||||
|
||||
Vector4f MatrixToQuat(const Matrix3f& m);
|
||||
|
||||
Vector4f QuatFromRotateAroundX(float angle);
|
||||
Vector4f QuatFromRotateAroundY(float angle);
|
||||
Vector4f QuatFromRotateAroundZ(float angle);
|
||||
|
||||
Vector3f operator*(Vector3f v, float scale);
|
||||
Vector4f operator*(Vector4f v, float scale);
|
||||
|
||||
Vector3f MultVectorMatrix(Vector3f v, Matrix3f mt);
|
||||
Vector4f MultVectorMatrix(Vector4f v, Matrix4f mt);
|
||||
Vector4f MultMatrixVector(Matrix4f mt, Vector4f v);
|
||||
|
||||
Vector4f slerp(const Vector4f& q1, const Vector4f& q2, float t);
|
||||
Matrix3f InverseMatrix(const Matrix3f& m);
|
||||
Matrix4f InverseMatrix(const Matrix4f& m);
|
||||
Matrix3f MultMatrixMatrix(const Matrix3f& m1, const Matrix3f& m2);
|
||||
Matrix4f MultMatrixMatrix(const Matrix4f& m1, const Matrix4f& m2);
|
||||
Matrix4f MakeMatrix4x4(const Matrix3f& m, const Vector3f pos);
|
||||
|
||||
};
|
||||
@@ -1,397 +0,0 @@
|
||||
#include "TextModel.h"
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
namespace ZL {
|
||||
|
||||
|
||||
VertexDataStruct LoadFromTextFile(const std::string &fileName, const std::string &ZIPFileName) {
|
||||
VertexDataStruct result;
|
||||
std::ifstream filestream;
|
||||
std::istringstream zipStream;
|
||||
|
||||
if (!ZIPFileName.empty()) {
|
||||
std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
|
||||
std::string fileContents(fileData.begin(), fileData.end());
|
||||
zipStream.str(fileContents);
|
||||
} else {
|
||||
filestream.open(fileName);
|
||||
}
|
||||
|
||||
// Создаем ссылку f на нужный поток – после этого код ниже остается без изменений
|
||||
std::istream &f = (!ZIPFileName.empty()) ? static_cast<std::istream &>(zipStream)
|
||||
: static_cast<std::istream &>(filestream);
|
||||
|
||||
|
||||
//Skip first 5 lines
|
||||
std::string tempLine;
|
||||
|
||||
std::getline(f, tempLine);
|
||||
|
||||
static const std::regex pattern_count(R"(\d+)");
|
||||
static const std::regex pattern_float(R"([-]?\d+\.\d+)");
|
||||
static const std::regex pattern_int(R"([-]?\d+)");
|
||||
|
||||
|
||||
std::smatch match;
|
||||
|
||||
int numberVertices;
|
||||
|
||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||
std::string number_str = match.str();
|
||||
numberVertices = std::stoi(number_str);
|
||||
} else {
|
||||
throw std::runtime_error("No number found in the input string.");
|
||||
}
|
||||
|
||||
std::vector <Vector3f> vertices;
|
||||
|
||||
vertices.resize(numberVertices);
|
||||
for (int i = 0; i < numberVertices; i++) {
|
||||
std::getline(f, tempLine);
|
||||
|
||||
std::vector<float> floatValues;
|
||||
|
||||
auto b = tempLine.cbegin();
|
||||
auto e = tempLine.cend();
|
||||
while (std::regex_search(b, e, match, pattern_float)) {
|
||||
floatValues.push_back(std::stof(match.str()));
|
||||
b = match.suffix().first;
|
||||
}
|
||||
|
||||
vertices[i] = Vector3f{floatValues[0], floatValues[1], floatValues[2]};
|
||||
}
|
||||
|
||||
std::cout << "UV Coordinates" << std::endl;
|
||||
|
||||
std::getline(f, tempLine); //===UV Coordinates:
|
||||
|
||||
std::getline(f, tempLine); //triangle count
|
||||
int numberTriangles;
|
||||
|
||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||
std::string number_str = match.str();
|
||||
numberTriangles = std::stoi(number_str);
|
||||
} else {
|
||||
throw std::runtime_error("No number found in the input string.");
|
||||
}
|
||||
|
||||
|
||||
// Now process UVs
|
||||
std::vector <std::array<Vector2f, 3>> uvCoords;
|
||||
|
||||
uvCoords.resize(numberTriangles);
|
||||
|
||||
for (int i = 0; i < numberTriangles; i++) {
|
||||
std::getline(f, tempLine); //Face 0
|
||||
|
||||
int uvCount;
|
||||
std::getline(f, tempLine);
|
||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||
std::string number_str = match.str();
|
||||
uvCount = std::stoi(number_str);
|
||||
} else {
|
||||
throw std::runtime_error("No number found in the input string.");
|
||||
}
|
||||
|
||||
if (uvCount != 3) {
|
||||
throw std::runtime_error("more than 3 uvs");
|
||||
}
|
||||
|
||||
std::vector<float> floatValues;
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
std::getline(f, tempLine); //UV <Vector (-0.3661, -1.1665)>
|
||||
|
||||
auto b = tempLine.cbegin();
|
||||
auto e = tempLine.cend();
|
||||
floatValues.clear();
|
||||
while (std::regex_search(b, e, match, pattern_float)) {
|
||||
floatValues.push_back(std::stof(match.str()));
|
||||
b = match.suffix().first;
|
||||
}
|
||||
|
||||
if (floatValues.size() != 2) {
|
||||
throw std::runtime_error("more than 2 uvs---");
|
||||
}
|
||||
|
||||
uvCoords[i][j] = Vector2f{floatValues[0], floatValues[1]};
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Normals go" << std::endl;
|
||||
|
||||
std::getline(f, tempLine); //===Normals:
|
||||
|
||||
|
||||
std::vector <Vector3f> normals;
|
||||
|
||||
normals.resize(numberVertices);
|
||||
for (int i = 0; i < numberVertices; i++) {
|
||||
std::getline(f, tempLine);
|
||||
|
||||
std::vector<float> floatValues;
|
||||
|
||||
auto b = tempLine.cbegin();
|
||||
auto e = tempLine.cend();
|
||||
while (std::regex_search(b, e, match, pattern_float)) {
|
||||
floatValues.push_back(std::stof(match.str()));
|
||||
b = match.suffix().first;
|
||||
}
|
||||
|
||||
normals[i] = Vector3f{floatValues[0], floatValues[1], floatValues[2]};
|
||||
}
|
||||
|
||||
std::cout << "Triangles go:" << std::endl;
|
||||
|
||||
std::getline(f, tempLine); //===Triangles: 3974
|
||||
|
||||
|
||||
std::vector <std::array<int, 3>> triangles;
|
||||
|
||||
triangles.resize(numberTriangles);
|
||||
for (int i = 0; i < numberTriangles; i++) {
|
||||
std::getline(f, tempLine);
|
||||
|
||||
std::vector<int> intValues;
|
||||
|
||||
auto b = tempLine.cbegin();
|
||||
auto e = tempLine.cend();
|
||||
while (std::regex_search(b, e, match, pattern_int)) {
|
||||
intValues.push_back(std::stoi(match.str()));
|
||||
b = match.suffix().first;
|
||||
}
|
||||
|
||||
triangles[i] = {intValues[0], intValues[1], intValues[2]};
|
||||
}
|
||||
|
||||
|
||||
std::cout << "Process vertices" << std::endl;
|
||||
|
||||
|
||||
|
||||
// Now let's process vertices
|
||||
|
||||
for (int i = 0; i < numberTriangles; i++) {
|
||||
|
||||
result.PositionData.push_back(vertices[triangles[i][0]]);
|
||||
result.PositionData.push_back(vertices[triangles[i][1]]);
|
||||
result.PositionData.push_back(vertices[triangles[i][2]]);
|
||||
|
||||
/*
|
||||
result.NormalData.push_back(normals[triangles[i][0]]);
|
||||
result.NormalData.push_back(normals[triangles[i][1]]);
|
||||
result.NormalData.push_back(normals[triangles[i][2]]);
|
||||
*/
|
||||
result.TexCoordData.push_back(uvCoords[i][0]);
|
||||
result.TexCoordData.push_back(uvCoords[i][1]);
|
||||
result.TexCoordData.push_back(uvCoords[i][2]);
|
||||
|
||||
}
|
||||
|
||||
//Swap from Blender format to OpenGL format
|
||||
for (int i = 0; i < result.PositionData.size(); i++) {
|
||||
Vector3f tempVec = result.PositionData[i];
|
||||
result.PositionData[i].v[0] = tempVec.v[1];
|
||||
result.PositionData[i].v[1] = tempVec.v[2];
|
||||
result.PositionData[i].v[2] = tempVec.v[0];
|
||||
|
||||
/*
|
||||
tempVec = result.NormalData[i];
|
||||
result.NormalData[i].v[0] = tempVec.v[1];
|
||||
result.NormalData[i].v[1] = tempVec.v[2];
|
||||
result.NormalData[i].v[2] = tempVec.v[0];*/
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
VertexDataStruct
|
||||
LoadFromTextFile02(const std::string &fileName, const std::string &ZIPFileName) {
|
||||
VertexDataStruct result;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Для Android используем SDL_RWops для чтения файлов
|
||||
__android_log_print(ANDROID_LOG_INFO, "TextModel",
|
||||
"LoadFromTextFile02 called for Android: %s", fileName.c_str());
|
||||
|
||||
// Читаем файл с помощью readTextFile
|
||||
std::string fileContent = readTextFile(fileName);
|
||||
if (fileContent.empty()) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "TextModel",
|
||||
"Failed to read file: %s", fileName.c_str());
|
||||
throw std::runtime_error("Failed to read file: " + fileName);
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "TextModel",
|
||||
"File read successfully, size: %zu", fileContent.size());
|
||||
|
||||
std::istringstream f(fileContent);
|
||||
#else
|
||||
// Оригинальный код для десктопа
|
||||
std::ifstream filestream;
|
||||
std::istringstream zipStream;
|
||||
|
||||
if (!ZIPFileName.empty()) {
|
||||
std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
|
||||
std::string fileContents(fileData.begin(), fileData.end());
|
||||
zipStream.str(fileContents);
|
||||
f = static_cast<std::istream &>(zipStream);
|
||||
} else {
|
||||
filestream.open(fileName);
|
||||
if (!filestream.is_open()) {
|
||||
throw std::runtime_error("Failed to open file: " + fileName);
|
||||
}
|
||||
f = static_cast<std::istream &>(filestream);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string tempLine;
|
||||
std::smatch match;
|
||||
|
||||
// Обновленные регулярки
|
||||
static const std::regex pattern_count(R"(\d+)");
|
||||
static const std::regex pattern_float(R"([-]?\d+(\.\d+)?)");
|
||||
static const std::regex pattern_int(R"([-]?\d+)");
|
||||
|
||||
// --- 2. Парсинг Вершин (Pos + Norm + UV) ---
|
||||
|
||||
// Ищем заголовок ===Vertices
|
||||
while (std::getline(f, tempLine)) {
|
||||
if (tempLine.find("===Vertices") != std::string::npos) break;
|
||||
}
|
||||
|
||||
int numberVertices = 0;
|
||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||
numberVertices = std::stoi(match.str());
|
||||
} else {
|
||||
throw std::runtime_error("Vertices header not found or invalid.");
|
||||
}
|
||||
|
||||
// Временные буферы для хранения "уникальных" вершин перед разверткой по индексам
|
||||
std::vector <Vector3f> tempPositions(numberVertices);
|
||||
std::vector <Vector3f> tempNormals(numberVertices);
|
||||
std::vector <Vector2f> tempUVs(numberVertices);
|
||||
|
||||
for (int i = 0; i < numberVertices; i++) {
|
||||
std::getline(f, tempLine);
|
||||
// Строка вида: V 0: Pos(x, y, z) Norm(x, y, z) UV(u, v)
|
||||
|
||||
std::vector<float> floatValues;
|
||||
floatValues.reserve(9); // ID + 3 pos + 3 norm + 2 uv
|
||||
|
||||
auto b = tempLine.cbegin();
|
||||
auto e = tempLine.cend();
|
||||
while (std::regex_search(b, e, match, pattern_float)) {
|
||||
floatValues.push_back(std::stof(match.str()));
|
||||
b = match.suffix().first;
|
||||
}
|
||||
|
||||
// Проверка, что у нас достаточно данных
|
||||
if (floatValues.size() < 9) {
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_WARN, "TextModel",
|
||||
"Warning: vertex line has only %zu values, expected 9",
|
||||
floatValues.size());
|
||||
#endif
|
||||
// Попробуем с меньшим количеством, возможно данные упрощенные
|
||||
if (floatValues.size() >= 8) {
|
||||
// Без ID
|
||||
tempPositions[i] = Vector3f{floatValues[0], floatValues[1], floatValues[2]};
|
||||
tempNormals[i] = Vector3f{floatValues[3], floatValues[4], floatValues[5]};
|
||||
tempUVs[i] = Vector2f{floatValues[6], floatValues[7]};
|
||||
continue;
|
||||
}
|
||||
throw std::runtime_error("Malformed vertex line at index " + std::to_string(i));
|
||||
}
|
||||
|
||||
// ID - floatValues[0]
|
||||
// Pos - [1], [2], [3]
|
||||
// Norm - [4], [5], [6]
|
||||
// UV - [7], [8]
|
||||
tempPositions[i] = Vector3f{floatValues[1], floatValues[2], floatValues[3]};
|
||||
tempNormals[i] = Vector3f{floatValues[4], floatValues[5], floatValues[6]};
|
||||
tempUVs[i] = Vector2f{floatValues[7], floatValues[8]};
|
||||
}
|
||||
|
||||
// --- 3. Парсинг Треугольников (Индексов) ---
|
||||
|
||||
// Пропускаем пустые строки до заголовка треугольников
|
||||
while (std::getline(f, tempLine)) {
|
||||
if (tempLine.find("===Triangles") != std::string::npos) break;
|
||||
}
|
||||
|
||||
int numberTriangles = 0;
|
||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||
numberTriangles = std::stoi(match.str());
|
||||
} else {
|
||||
throw std::runtime_error("Triangles header not found.");
|
||||
}
|
||||
|
||||
// Резервируем память в result, чтобы избежать лишних аллокаций
|
||||
result.PositionData.reserve(numberTriangles * 3);
|
||||
result.NormalData.reserve(numberTriangles * 3);
|
||||
result.TexCoordData.reserve(numberTriangles * 3);
|
||||
|
||||
for (int i = 0; i < numberTriangles; i++) {
|
||||
std::getline(f, tempLine);
|
||||
// Строка вида: Tri: 0 1 2
|
||||
|
||||
std::vector<int> indices;
|
||||
indices.reserve(3);
|
||||
|
||||
auto b = tempLine.cbegin();
|
||||
auto e = tempLine.cend();
|
||||
while (std::regex_search(b, e, match, pattern_int)) {
|
||||
indices.push_back(std::stoi(match.str()));
|
||||
b = match.suffix().first;
|
||||
}
|
||||
|
||||
if (indices.size() != 3) {
|
||||
throw std::runtime_error("Malformed triangle line at index " + std::to_string(i));
|
||||
}
|
||||
|
||||
// --- 4. Заполнение VertexDataStruct (Flattening) ---
|
||||
for (int k = 0; k < 3; k++) {
|
||||
int idx = indices[k];
|
||||
result.PositionData.push_back(tempPositions[idx]);
|
||||
result.NormalData.push_back(tempNormals[idx]);
|
||||
result.TexCoordData.push_back(tempUVs[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// --- 5. Конвертация координат (Blender -> OpenGL/Engine) ---
|
||||
for (size_t i = 0; i < result.PositionData.size(); i++) {
|
||||
Vector3f originalPos = result.PositionData[i];
|
||||
result.PositionData[i].v[0] = originalPos.v[1]; // New X = Old Y
|
||||
result.PositionData[i].v[1] = originalPos.v[2]; // New Y = Old Z
|
||||
result.PositionData[i].v[2] = originalPos.v[0]; // New Z = Old X
|
||||
|
||||
Vector3f originalNorm = result.NormalData[i];
|
||||
result.NormalData[i].v[0] = originalNorm.v[1];
|
||||
result.NormalData[i].v[1] = originalNorm.v[2];
|
||||
result.NormalData[i].v[2] = originalNorm.v[0];
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_INFO, "TextModel",
|
||||
"Model loaded successfully: %d verts, %d tris",
|
||||
numberVertices, numberTriangles);
|
||||
#else
|
||||
std::cout << "Model loaded: " << numberVertices << " verts, " << numberTriangles << " tris."
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Math.h"
|
||||
#include "Renderer.h"
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
namespace ZL {
|
||||
VertexDataStruct
|
||||
LoadFromTextFile(const std::string &fileName, const std::string &ZIPFileName = "");
|
||||
|
||||
VertexDataStruct
|
||||
LoadFromTextFile02(const std::string &fileName, const std::string &ZIPFileName = "");
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
#include "TextureManager.h"
|
||||
#ifdef PNG_ENABLED
|
||||
#include "png.h"
|
||||
#endif
|
||||
|
||||
namespace ZL
|
||||
{
|
||||
|
||||
Texture::Texture(const TextureDataStruct& texData)
|
||||
{
|
||||
|
||||
width = texData.width;
|
||||
height = texData.height;
|
||||
|
||||
glGenTextures(1, &texID);
|
||||
|
||||
if (texID == 0)
|
||||
{
|
||||
throw std::runtime_error("glGenTextures did not work");
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texID);
|
||||
|
||||
//CheckGlError();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
//CheckGlError();
|
||||
|
||||
//This should be only for Windows
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
|
||||
//CheckGlError();
|
||||
|
||||
if (texData.bitSize == TextureDataStruct::BS_24BIT)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, static_cast<GLsizei>(texData.width), static_cast<GLsizei>(texData.height), 0, GL_RGB, GL_UNSIGNED_BYTE, &texData.data[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(texData.width), static_cast<GLsizei>(texData.height), 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData.data[0]);
|
||||
}
|
||||
|
||||
//CheckGlError();
|
||||
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
glDeleteTextures(1, &texID);
|
||||
texID = 0;
|
||||
}
|
||||
|
||||
GLuint Texture::getTexID()
|
||||
{
|
||||
return texID;
|
||||
}
|
||||
|
||||
size_t Texture::getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
size_t Texture::getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TextureDataStruct CreateTextureDataFromBmp24(const std::string& fullFileName, const std::string& ZIPFileName)
|
||||
{
|
||||
|
||||
TextureDataStruct texData;
|
||||
std::vector<char> fileArr;
|
||||
|
||||
fileArr = !ZIPFileName.empty() ? readFileFromZIP(fullFileName, ZIPFileName) : readFile(fullFileName);
|
||||
|
||||
size_t fileSize = fileArr.size();
|
||||
|
||||
if (fileSize < 22)
|
||||
{
|
||||
throw std::runtime_error("File is too short or not correct!");
|
||||
}
|
||||
|
||||
//This refers to BITMAPV5HEADER
|
||||
texData.width = *reinterpret_cast<uint32_t*>(&fileArr[18]);
|
||||
texData.height = *reinterpret_cast<uint32_t*>(&fileArr[22]);
|
||||
|
||||
texData.bitSize = TextureDataStruct::BS_24BIT;
|
||||
|
||||
size_t dataSize = texData.width * texData.height * 3;
|
||||
|
||||
texData.data.resize(dataSize);
|
||||
|
||||
size_t pos = *reinterpret_cast<uint32_t*>(&fileArr[10]);
|
||||
size_t x = 0;
|
||||
|
||||
for (size_t i = 0; i < texData.width; i++)
|
||||
for (size_t j = 0; j < texData.height; j++)
|
||||
{
|
||||
|
||||
if (pos + 3 > fileSize)
|
||||
{
|
||||
throw std::runtime_error("File is too short!");
|
||||
}
|
||||
|
||||
|
||||
x = (i * texData.height + j) + (i * texData.height + j) + (i * texData.height + j);
|
||||
|
||||
texData.data[x + 2] = fileArr[pos++];
|
||||
texData.data[x + 1] = fileArr[pos++];
|
||||
texData.data[x + 0] = fileArr[pos++];
|
||||
|
||||
}
|
||||
|
||||
return texData;
|
||||
}
|
||||
|
||||
TextureDataStruct CreateTextureDataFromBmp32(const std::string& fullFileName, const std::string& ZIPFileName)
|
||||
{
|
||||
|
||||
TextureDataStruct texData;
|
||||
std::vector<char> fileArr;
|
||||
|
||||
fileArr = !ZIPFileName.empty() ? readFileFromZIP(fullFileName, ZIPFileName) : readFile(fullFileName);
|
||||
|
||||
size_t fileSize = fileArr.size();
|
||||
|
||||
if (fileSize < 22)
|
||||
{
|
||||
throw std::runtime_error("File is too short or not correct!");
|
||||
}
|
||||
|
||||
//This refers to BITMAPV5HEADER
|
||||
texData.width = *reinterpret_cast<uint32_t*>(&fileArr[18]);
|
||||
texData.height = *reinterpret_cast<uint32_t*>(&fileArr[22]);
|
||||
|
||||
texData.bitSize = TextureDataStruct::BS_32BIT;
|
||||
|
||||
size_t dataSize = texData.width * texData.height * 4;
|
||||
|
||||
texData.data.resize(dataSize);
|
||||
|
||||
size_t pos = *reinterpret_cast<uint32_t*>(&fileArr[10]);
|
||||
size_t x = 0;
|
||||
|
||||
for (size_t i = 0; i < texData.width; i++)
|
||||
for (size_t j = 0; j < texData.height; j++)
|
||||
{
|
||||
|
||||
if (pos + 4 > fileSize)
|
||||
{
|
||||
throw std::runtime_error("File is too short!");
|
||||
}
|
||||
|
||||
|
||||
x = (i * texData.height + j) + (i * texData.height + j) + (i * texData.height + j) + (i * texData.height + j);
|
||||
|
||||
texData.data[x + 2] = fileArr[pos++];
|
||||
texData.data[x + 1] = fileArr[pos++];
|
||||
texData.data[x + 0] = fileArr[pos++];
|
||||
texData.data[x + 3] = fileArr[pos++];
|
||||
|
||||
}
|
||||
|
||||
return texData;
|
||||
}
|
||||
|
||||
#ifdef PNG_ENABLED
|
||||
|
||||
TextureDataStruct CreateTextureDataFromPng(const std::string& fullFileName)
|
||||
{
|
||||
TextureDataStruct texData;
|
||||
|
||||
FILE* file = fopen(fullFileName.c_str(), "rb");
|
||||
if (!file) {
|
||||
fclose(file);
|
||||
throw std::runtime_error("Could not open file " + fullFileName);
|
||||
}
|
||||
|
||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png) {
|
||||
fclose(file);
|
||||
throw std::runtime_error("Could not create PNG read structure");
|
||||
}
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
if (!info) {
|
||||
fclose(file);
|
||||
png_destroy_read_struct(&png, nullptr, nullptr);
|
||||
throw std::runtime_error("Could not create PNG info structure");
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png))) {
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
fclose(file);
|
||||
throw std::runtime_error("Error during PNG read");
|
||||
}
|
||||
|
||||
png_init_io(png, file);
|
||||
png_read_info(png, info);
|
||||
|
||||
texData.width = png_get_image_width(png, info);
|
||||
texData.height = png_get_image_height(png, info);
|
||||
png_byte color_type = png_get_color_type(png, info);
|
||||
png_byte bit_depth = png_get_bit_depth(png, info);
|
||||
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
|
||||
if (png_get_valid(png, info, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png);
|
||||
|
||||
png_read_update_info(png, info);
|
||||
|
||||
|
||||
png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * texData.height);
|
||||
for (int y = 0; y < texData.height; y++) {
|
||||
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info));
|
||||
}
|
||||
|
||||
png_read_image(png, row_pointers);
|
||||
|
||||
fclose(file);
|
||||
|
||||
bool has_alpha = (color_type & PNG_COLOR_MASK_ALPHA) || (png_get_valid(png, info, PNG_INFO_tRNS));
|
||||
|
||||
size_t dataSize;
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
texData.bitSize = TextureDataStruct::BS_32BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
texData.bitSize = TextureDataStruct::BS_24BIT;
|
||||
}
|
||||
|
||||
int channels = has_alpha ? 4 : 3;
|
||||
|
||||
dataSize = texData.width * texData.height * channels;
|
||||
texData.data.resize(dataSize);
|
||||
|
||||
|
||||
//for (int y = 0; y < texData.height; y++) { //Go in reverse because of UV coord start point
|
||||
for (int y = texData.height-1; y >= 0; y--) {
|
||||
//png_bytep row = row_pointers[y];//Go in reverse because of UV coord start point
|
||||
png_bytep row = row_pointers[texData.height - 1 - y];
|
||||
for (int x = 0; x < texData.width; x++) {
|
||||
png_bytep px = &(row[x * 4]);
|
||||
texData.data[(y * texData.width + x) * channels + 0] = px[0]; // R
|
||||
texData.data[(y * texData.width + x) * channels + 1] = px[1]; // G
|
||||
texData.data[(y * texData.width + x) * channels + 2] = px[2]; // B
|
||||
if (has_alpha) {
|
||||
texData.data[(y * texData.width + x) * channels + 3] = px[3]; // A
|
||||
}
|
||||
}
|
||||
//free(row_pointers[y]);//Go in reverse because of UV coord start point
|
||||
free(row_pointers[texData.height - 1 - y]);//Go in reverse because of UV coord start point
|
||||
}
|
||||
free(row_pointers);
|
||||
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
|
||||
return texData;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
#include "Utils.h"
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
//#include <zip.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
namespace ZL {
|
||||
std::string readTextFile(const std::string &filename) {
|
||||
#ifdef __ANDROID__
|
||||
SDL_RWops* file = SDL_RWFromFile(filename.c_str(), "rb");
|
||||
if (!file) {
|
||||
#ifdef DEBUG
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Utils",
|
||||
"Failed to open: %s", filename.c_str());
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
Sint64 size = SDL_RWsize(file);
|
||||
if (size <= 0) {
|
||||
SDL_RWclose(file);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string content(size, '\0');
|
||||
if (SDL_RWread(file, &content[0], size, 1) != 1) {
|
||||
SDL_RWclose(file);
|
||||
return "";
|
||||
}
|
||||
|
||||
SDL_RWclose(file);
|
||||
return content;
|
||||
#else
|
||||
std::ifstream f(filename);
|
||||
if (!f.is_open()) {
|
||||
return "";
|
||||
}
|
||||
return std::string((std::istreambuf_iterator<char>(f)),
|
||||
std::istreambuf_iterator<char>());
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<char> readFile(const std::string &filename) {
|
||||
#ifdef __ANDROID__
|
||||
SDL_RWops* file = SDL_RWFromFile(filename.c_str(), "rb");
|
||||
if (!file) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Sint64 size = SDL_RWsize(file);
|
||||
if (size <= 0) {
|
||||
SDL_RWclose(file);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<char> data(size);
|
||||
if (SDL_RWread(file, data.data(), size, 1) != 1) {
|
||||
SDL_RWclose(file);
|
||||
return {};
|
||||
}
|
||||
|
||||
SDL_RWclose(file);
|
||||
return data;
|
||||
#else
|
||||
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
||||
if (!file) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::streamsize size = file.tellg();
|
||||
if (size <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
file.seekg(0, std::ios::beg);
|
||||
std::vector<char> buffer(size);
|
||||
|
||||
if (!file.read(buffer.data(), size)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<char> readFileFromZIP(const std::string &filename, const std::string &zipfilename) {
|
||||
/*const std::string zipPath = zipfilename;
|
||||
int zipErr;
|
||||
zip_t* archive = zip_open(zipPath.c_str(), ZIP_RDONLY, &zipErr);
|
||||
if (!archive) {
|
||||
throw std::runtime_error("Ошибка открытия ZIP: " + zipPath);
|
||||
}
|
||||
|
||||
std::string cleanFilename = filename;
|
||||
if (cleanFilename.rfind("./", 0) == 0) {
|
||||
cleanFilename = cleanFilename.substr(2);
|
||||
}
|
||||
|
||||
std::cout << "Ищем в ZIP: " << cleanFilename << std::endl;
|
||||
|
||||
zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0);
|
||||
if (!zipFile) {
|
||||
zip_close(archive);
|
||||
throw std::runtime_error("Файл не найден в ZIP: " + cleanFilename);
|
||||
}
|
||||
|
||||
zip_stat_t fileStat;
|
||||
if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0) {
|
||||
zip_fclose(zipFile);
|
||||
zip_close(archive);
|
||||
throw std::runtime_error("Ошибка чтения ZIP-статистики.");
|
||||
}
|
||||
|
||||
std::vector<char> fileData;
|
||||
fileData.resize(fileStat.size);
|
||||
|
||||
zip_fread(zipFile, fileData.data(), fileData.size());
|
||||
|
||||
zip_fclose(zipFile);
|
||||
zip_close(archive);
|
||||
|
||||
return fileData;*/
|
||||
return {};
|
||||
}
|
||||
|
||||
bool findString(const char *in, char *list) {
|
||||
size_t thisLength = strlen(in);
|
||||
while (*list != 0) {
|
||||
size_t length = strcspn(list, " ");
|
||||
if (thisLength == length && !strncmp(in, list, length))
|
||||
return true;
|
||||
list += length + 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -1,199 +0,0 @@
|
||||
#include "Game.h"
|
||||
#include "Environment.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
ZL::Game game;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
#else
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Инициализация SDL перед получением информации о дисплее
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL init failed: %s", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_DisplayMode displayMode;
|
||||
if (SDL_GetCurrentDisplayMode(0, &displayMode) != 0) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GetCurrentDisplayMode failed: %s", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
ZL::Environment::width = displayMode.w;
|
||||
ZL::Environment::height = displayMode.h;
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Display resolution: %dx%d",
|
||||
ZL::Environment::width, ZL::Environment::height);
|
||||
#else
|
||||
constexpr int CONST_WIDTH = 1280;
|
||||
constexpr int CONST_HEIGHT = 720;
|
||||
ZL::Environment::width = CONST_WIDTH;
|
||||
ZL::Environment::height = CONST_HEIGHT;
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
||||
SDL_Log("SDL init failed: %s", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
std::cerr << "SDL_Init failed: " << SDL_GetError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
|
||||
SDL_Window* win = SDL_CreateWindow("Space Ship Game",
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
ZL::Environment::width, ZL::Environment::height,
|
||||
SDL_WINDOW_OPENGL);
|
||||
|
||||
if (!win) {
|
||||
std::cerr << "SDL_CreateWindow failed: " << SDL_GetError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_GLContext glContext = SDL_GL_CreateContext(win);
|
||||
if (!glContext) {
|
||||
std::cerr << "SDL_GL_CreateContext failed: " << SDL_GetError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_GL_MakeCurrent(win, glContext);
|
||||
ZL::Environment::window = win;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __ANDROID__
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
|
||||
ZL::Environment::window = SDL_CreateWindow(
|
||||
"Space Ship Game",
|
||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
ZL::Environment::width, ZL::Environment::height,
|
||||
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
||||
);
|
||||
#else
|
||||
// Для десктопа
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
|
||||
ZL::Environment::window = SDL_CreateWindow(
|
||||
"Space Ship Game",
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
ZL::Environment::width, ZL::Environment::height,
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
||||
);
|
||||
#endif
|
||||
|
||||
if (!ZL::Environment::window) {
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "Failed to create window: %s", SDL_GetError());
|
||||
#else
|
||||
SDL_Log("Failed to create window: %s", SDL_GetError());
|
||||
#endif
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
#endif
|
||||
|
||||
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
||||
if (!ctx) {
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_CreateContext failed: %s", SDL_GetError());
|
||||
#else
|
||||
SDL_Log("SDL_GL_CreateContext failed: %s", SDL_GetError());
|
||||
#endif
|
||||
SDL_DestroyWindow(ZL::Environment::window);
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SDL_GL_MakeCurrent(ZL::Environment::window, ctx) != 0) {
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_MakeCurrent failed: %s", SDL_GetError());
|
||||
#else
|
||||
SDL_Log("SDL_GL_MakeCurrent failed: %s", SDL_GetError());
|
||||
#endif
|
||||
SDL_GL_DeleteContext(ctx);
|
||||
SDL_DestroyWindow(ZL::Environment::window);
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Настройка VSync
|
||||
if (SDL_GL_SetSwapInterval(1) < 0) {
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_WARN, "Game", "Unable to set VSync: %s", SDL_GetError());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Настройка игры
|
||||
try {
|
||||
game.setup();
|
||||
} catch (const std::exception &e) {
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "Game setup failed: %s", e.what());
|
||||
#else
|
||||
std::cerr << "Game setup failed: " << e.what() << std::endl;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
emscripten_set_main_loop(MainLoop, 0, 1);
|
||||
#else
|
||||
bool running = true;
|
||||
while (running && !game.shouldExit()) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
running = false;
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_AC_BACK) {
|
||||
running = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
game.update();
|
||||
|
||||
#ifdef __ANDROID__
|
||||
SDL_Delay(16);
|
||||
#else
|
||||
SDL_Delay(2);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 653 KiB |
|
Before Width: | Height: | Size: 4.0 MiB |
|
Before Width: | Height: | Size: 599 KiB |
@@ -1,7 +0,0 @@
|
||||
precision mediump float;
|
||||
varying vec3 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
precision mediump float;
|
||||
uniform sampler2D Texture;
|
||||
varying vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture2D(Texture, texCoord);
|
||||
gl_FragColor = color;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
//precision mediump float;
|
||||
uniform sampler2D Texture;
|
||||
varying vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture2D(Texture,texCoord).rgba;
|
||||
gl_FragColor = vec4(color.rgb*0.9 + vec3(0.1, 0.1, 0.1), 1.0);
|
||||
|
||||
//gl_FragColor = color;
|
||||
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,86 @@
|
||||
import bpy
|
||||
import bmesh
|
||||
|
||||
mesh_name = "chassis_low"
|
||||
output_path = "C:\\Work\\Projects\\space-game001\\blender scripts\\output\\spaceship005.txt"
|
||||
|
||||
mesh_obj = bpy.data.objects.get(mesh_name)
|
||||
|
||||
if mesh_obj and mesh_obj.type == 'MESH':
|
||||
# Обязательно применяем трансформации, чтобы координаты были актуальными
|
||||
# Но для чистоты эксперимента берем mesh data как есть
|
||||
|
||||
# Работаем с копией меша, чтобы применить триангуляцию (если нужно)
|
||||
# и не испортить сцену, но пока используем bmesh напрямую
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(mesh_obj.data)
|
||||
|
||||
# Получаем слой UV
|
||||
uv_layer = bm.loops.layers.uv.active
|
||||
|
||||
# Словарь для хранения уникальных вершин:
|
||||
# Ключ: (x, y, z, nx, ny, nz, u, v) -> Значение: новый_индекс
|
||||
unique_verts_map = {}
|
||||
final_vertices = [] # Список для записи в файл
|
||||
final_indices = [] # Список индексов треугольников
|
||||
|
||||
# Проходим по всем фейсам
|
||||
for face in bm.faces:
|
||||
face_indices = []
|
||||
|
||||
# Проходим по углам (loops) фейса
|
||||
for loop in face.loops:
|
||||
vert = loop.vert
|
||||
|
||||
# 1. Координаты (округляем для надежности сравнения float)
|
||||
co = (round(vert.co.x, 6), round(vert.co.y, 6), round(vert.co.z, 6))
|
||||
|
||||
# 2. Нормаль (если используете Smooth shading, берите vert.normal, если Flat - face.normal)
|
||||
# Для простоты берем нормаль вершины
|
||||
no = (round(vert.normal.x, 6), round(vert.normal.y, 6), round(vert.normal.z, 6))
|
||||
|
||||
# 3. UV координаты
|
||||
if uv_layer:
|
||||
raw_uv = loop[uv_layer].uv
|
||||
uv = (round(raw_uv.x, 6), round(raw_uv.y, 6))
|
||||
else:
|
||||
uv = (0.0, 0.0)
|
||||
|
||||
# Собираем уникальный ключ данных вершины
|
||||
vert_data_key = (co, no, uv)
|
||||
|
||||
# Проверяем, есть ли такая комбинация уже
|
||||
if vert_data_key in unique_verts_map:
|
||||
index = unique_verts_map[vert_data_key]
|
||||
else:
|
||||
index = len(final_vertices)
|
||||
unique_verts_map[vert_data_key] = index
|
||||
final_vertices.append(vert_data_key)
|
||||
|
||||
face_indices.append(index)
|
||||
|
||||
# Триангуляция "на лету" (если фейс - квадрат, делим на два треугольника)
|
||||
# Простейший метод fan (0, 1, 2), (0, 2, 3)...
|
||||
for i in range(1, len(face_indices) - 1):
|
||||
final_indices.append(face_indices[0])
|
||||
final_indices.append(face_indices[i])
|
||||
final_indices.append(face_indices[i+1])
|
||||
|
||||
# --- ЗАПИСЬ В ФАЙЛ ---
|
||||
with open(output_path, "w") as file:
|
||||
file.write(f"===Vertices (Split by UV/Normal): {len(final_vertices)}\n")
|
||||
# Формат строки: ID: X Y Z | NX NY NZ | U V
|
||||
for idx, v_data in enumerate(final_vertices):
|
||||
co, no, uv = v_data
|
||||
file.write(f"V {idx}: Pos({co[0]}, {co[1]}, {co[2]}) Norm({no[0]}, {no[1]}, {no[2]}) UV({uv[0]}, {uv[1]})\n")
|
||||
|
||||
file.write(f"\n===Triangles (Indices): {len(final_indices) // 3}\n")
|
||||
# Записываем тройками
|
||||
for i in range(0, len(final_indices), 3):
|
||||
file.write(f"Tri: {final_indices[i]} {final_indices[i+1]} {final_indices[i+2]}\n")
|
||||
|
||||
bm.free()
|
||||
print(f"Export done. Original verts: {len(mesh_obj.data.vertices)}, Split verts: {len(final_vertices)}")
|
||||
|
||||
else:
|
||||
print("Mesh not found")
|
||||
@@ -0,0 +1,49 @@
|
||||
# cmake/FetchDependencies.cmake
|
||||
|
||||
set(THIRDPARTY_DIR "${CMAKE_CURRENT_LIST_DIR}/../thirdparty")
|
||||
|
||||
if(NOT EXISTS "${THIRDPARTY_DIR}")
|
||||
file(MAKE_DIRECTORY "${THIRDPARTY_DIR}")
|
||||
endif()
|
||||
|
||||
macro(check_and_download URL ARCHIVE_NAME EXTRACTED_DIR_NAME CHECK_FILE)
|
||||
set(ARCHIVE_PATH "${THIRDPARTY_DIR}/${ARCHIVE_NAME}")
|
||||
set(SRC_PATH "${THIRDPARTY_DIR}/${EXTRACTED_DIR_NAME}")
|
||||
|
||||
if(NOT EXISTS "${ARCHIVE_PATH}")
|
||||
message(STATUS "Downloading ${ARCHIVE_NAME}...")
|
||||
file(DOWNLOAD "${URL}" "${ARCHIVE_PATH}" SHOW_PROGRESS)
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${SRC_PATH}/${CHECK_FILE}")
|
||||
message(STATUS "Extracting ${ARCHIVE_NAME}...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xvf "${ARCHIVE_PATH}"
|
||||
WORKING_DIRECTORY "${THIRDPARTY_DIR}"
|
||||
)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# 1) ZLIB (Нужна только для инклудов, если не используете emscripten порты)
|
||||
check_and_download("https://www.zlib.net/zlib131.zip" "zlib131.zip" "zlib-1.3.1" "CMakeLists.txt")
|
||||
|
||||
# 2) SDL2
|
||||
check_and_download("https://github.com/libsdl-org/SDL/archive/refs/tags/release-2.32.10.zip" "release-2.32.10.zip" "SDL-release-2.32.10" "CMakeLists.txt")
|
||||
|
||||
# 3) LibPNG
|
||||
check_and_download("https://github.com/pnggroup/libpng/archive/refs/tags/v1.6.51.zip" "v1.6.51.zip" "libpng-1.6.51" "CMakeLists.txt")
|
||||
|
||||
# 4) LibZip
|
||||
check_and_download("https://github.com/nih-at/libzip/archive/refs/tags/v1.11.4.zip" "v1.11.4.zip" "libzip-1.11.4" "CMakeLists.txt")
|
||||
|
||||
# 5) Eigen
|
||||
check_and_download("https://gitlab.com/libeigen/eigen/-/archive/5.0.0/eigen-5.0.0.zip" "eigen-5.0.0.zip" "eigen-5.0.0" "signature_of_eigen3_matrix_library")
|
||||
|
||||
# 6) Boost
|
||||
check_and_download("https://archives.boost.io/release/1.90.0/source/boost_1_90_0.zip" "boost_1_90_0.zip" "boost_1_90_0" "boost")
|
||||
|
||||
# 7) FreeType
|
||||
check_and_download("https://download.savannah.gnu.org/releases/freetype/freetype-2.14.1.tar.gz" "freetype-2.14.1.tar.gz" "freetype-2.14.1" "CMakeLists.txt")
|
||||
|
||||
# 8) SDL_ttf
|
||||
check_and_download("https://github.com/libsdl-org/SDL_ttf/archive/refs/tags/release-2.24.0.zip" "release-2.24.0.zip" "SDL_ttf-release-2.24.0" "CMakeLists.txt")
|
||||
@@ -0,0 +1,549 @@
|
||||
# cmake/ThirdParty.cmake
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/FetchDependencies.cmake")
|
||||
|
||||
macro(log msg)
|
||||
message(STATUS "[ThirdParty] ${msg}")
|
||||
endmacro()
|
||||
|
||||
set(BUILD_CONFIGS Debug Release)
|
||||
|
||||
|
||||
# ===========================================
|
||||
# 1) ZLIB (zlib131.zip → zlib-1.3.1) - без изменений
|
||||
# ===========================================
|
||||
set(ZLIB_SRC_DIR "${THIRDPARTY_DIR}/zlib-1.3.1")
|
||||
set(ZLIB_BUILD_DIR "${ZLIB_SRC_DIR}/build")
|
||||
set(ZLIB_INSTALL_DIR "${ZLIB_SRC_DIR}/install")
|
||||
|
||||
|
||||
file(MAKE_DIRECTORY "${ZLIB_BUILD_DIR}")
|
||||
|
||||
# проверяем, собран ли уже zlib
|
||||
set(_have_zlib FALSE)
|
||||
foreach(candidate
|
||||
"${ZLIB_INSTALL_DIR}/lib/zlibstatic.lib"
|
||||
)
|
||||
if(EXISTS "${candidate}")
|
||||
set(_have_zlib TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
|
||||
if(NOT _have_zlib)
|
||||
log("Configuring zlib ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
-S "${ZLIB_SRC_DIR}"
|
||||
-B "${ZLIB_BUILD_DIR}"
|
||||
-DCMAKE_INSTALL_PREFIX=${ZLIB_INSTALL_DIR}
|
||||
RESULT_VARIABLE _zlib_cfg_res
|
||||
)
|
||||
if(NOT _zlib_cfg_res EQUAL 0)
|
||||
message(FATAL_ERROR "zlib configure failed")
|
||||
endif()
|
||||
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
log("Building ZLIB (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--build "${ZLIB_BUILD_DIR}" --config ${cfg}
|
||||
RESULT_VARIABLE _zlib_build_res
|
||||
)
|
||||
if(NOT _zlib_build_res EQUAL 0)
|
||||
message(FATAL_ERROR "ZLIB build failed for configuration ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Installing ZLIB (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--install "${ZLIB_BUILD_DIR}" --config ${cfg}
|
||||
RESULT_VARIABLE _zlib_inst_res
|
||||
)
|
||||
if(NOT _zlib_inst_res EQUAL 0)
|
||||
message(FATAL_ERROR "ZLIB install failed for configuration ${cfg}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# ИСПРАВЛЕНИЕ: Используем свойства для конкретных конфигураций
|
||||
add_library(zlib_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(zlib_external_lib PROPERTIES
|
||||
# Динамическая линковка (если zlib.lib - это импорт-библиотека для zlibd.dll)
|
||||
#IMPORTED_LOCATION_DEBUG "${ZLIB_INSTALL_DIR}/lib/zlibd.lib"
|
||||
#IMPORTED_LOCATION_RELEASE "${ZLIB_INSTALL_DIR}/lib/zlib.lib"
|
||||
|
||||
# Можно также указать статические библиотеки, если вы хотите их использовать
|
||||
IMPORTED_LOCATION_DEBUG "${ZLIB_INSTALL_DIR}/lib/zlibstaticd.lib"
|
||||
IMPORTED_LOCATION_RELEASE "${ZLIB_INSTALL_DIR}/lib/zlibstatic.lib"
|
||||
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INSTALL_DIR}/include"
|
||||
)
|
||||
|
||||
# ===========================================
|
||||
# 2) SDL2 (release-2.32.10.zip → SDL-release-2.32.10) - без изменений
|
||||
# ===========================================
|
||||
set(SDL2_SRC_DIR "${THIRDPARTY_DIR}/SDL-release-2.32.10")
|
||||
set(SDL2_BUILD_DIR "${SDL2_SRC_DIR}/build")
|
||||
set(SDL2_INSTALL_DIR "${SDL2_SRC_DIR}/install")
|
||||
|
||||
file(MAKE_DIRECTORY "${SDL2_BUILD_DIR}")
|
||||
|
||||
set(_have_sdl2 FALSE)
|
||||
foreach(candidate
|
||||
"${SDL2_INSTALL_DIR}/lib/SDL2.lib"
|
||||
"${SDL2_INSTALL_DIR}/lib/SDL2-static.lib"
|
||||
"${SDL2_INSTALL_DIR}/lib/SDL2d.lib"
|
||||
)
|
||||
if(EXISTS "${candidate}")
|
||||
set(_have_sdl2 TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _have_sdl2)
|
||||
log("Configuring SDL2 ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
-S "${SDL2_SRC_DIR}"
|
||||
-B "${SDL2_BUILD_DIR}"
|
||||
-DCMAKE_INSTALL_PREFIX=${SDL2_INSTALL_DIR}
|
||||
-DCMAKE_PREFIX_PATH=${ZLIB_INSTALL_DIR} # путь к zlib для SDL2
|
||||
RESULT_VARIABLE _sdl_cfg_res
|
||||
)
|
||||
if(NOT _sdl_cfg_res EQUAL 0)
|
||||
message(FATAL_ERROR "SDL2 configure failed")
|
||||
endif()
|
||||
|
||||
# --- ИЗМЕНЕНИЕ: Цикл по конфигурациям Debug и Release ---
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
log("Building SDL2 (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--build "${SDL2_BUILD_DIR}" --config ${cfg}
|
||||
RESULT_VARIABLE _sdl_build_res
|
||||
)
|
||||
if(NOT _sdl_build_res EQUAL 0)
|
||||
message(FATAL_ERROR "SDL2 build failed for configuration ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Installing SDL2 (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--install "${SDL2_BUILD_DIR}" --config ${cfg}
|
||||
RESULT_VARIABLE _sdl_inst_res
|
||||
)
|
||||
if(NOT _sdl_inst_res EQUAL 0)
|
||||
message(FATAL_ERROR "SDL2 install failed for configuration ${cfg}")
|
||||
endif()
|
||||
endforeach()
|
||||
# ------------------------------------------------------
|
||||
endif()
|
||||
|
||||
|
||||
# ИСПРАВЛЕНИЕ: SDL2: Используем свойства для конкретных конфигураций
|
||||
add_library(SDL2_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(SDL2_external_lib PROPERTIES
|
||||
# Динамическая линковка SDL2
|
||||
IMPORTED_LOCATION_DEBUG "${SDL2_INSTALL_DIR}/lib/SDL2d.lib"
|
||||
IMPORTED_LOCATION_RELEASE "${SDL2_INSTALL_DIR}/lib/SDL2.lib"
|
||||
# Оба include-пути: и include, и include/SDL2
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INSTALL_DIR}/include;${SDL2_INSTALL_DIR}/include/SDL2"
|
||||
)
|
||||
|
||||
# SDL2main (обычно статическая)
|
||||
add_library(SDL2main_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(SDL2main_external_lib PROPERTIES
|
||||
# ИСПРАВЛЕНО: Указываем пути для Debug и Release, используя
|
||||
# соглашение, что Debug имеет суффикс 'd', а Release — нет.
|
||||
IMPORTED_LOCATION_DEBUG "${SDL2_INSTALL_DIR}/lib/SDL2maind.lib"
|
||||
IMPORTED_LOCATION_RELEASE "${SDL2_INSTALL_DIR}/lib/SDL2main.lib"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INSTALL_DIR}/include"
|
||||
)
|
||||
|
||||
log("-----${SDL2_INSTALL_DIR}/lib/SDL2maind.lib")
|
||||
|
||||
# ===========================================
|
||||
# 3) libpng (v1.6.51.zip → libpng-1.6.51) - без изменений
|
||||
# ===========================================
|
||||
set(LIBPNG_SRC_DIR "${THIRDPARTY_DIR}/libpng-1.6.51")
|
||||
set(LIBPNG_BUILD_DIR "${LIBPNG_SRC_DIR}/build")
|
||||
set(LIBPNG_INSTALL_DIR "${LIBPNG_SRC_DIR}/install") # на будущее
|
||||
|
||||
file(MAKE_DIRECTORY "${LIBPNG_BUILD_DIR}")
|
||||
|
||||
# Проверяем, есть ли уже .lib (build/Debug или install/lib)
|
||||
set(_libpng_candidates
|
||||
"${LIBPNG_BUILD_DIR}/Debug/libpng16_staticd.lib"
|
||||
"${LIBPNG_BUILD_DIR}/Release/libpng16_static.lib"
|
||||
)
|
||||
|
||||
set(_have_png FALSE)
|
||||
foreach(candidate IN LISTS _libpng_candidates)
|
||||
if(EXISTS "${candidate}")
|
||||
set(_have_png TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _have_png)
|
||||
log("Configuring libpng ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
-S "${LIBPNG_SRC_DIR}"
|
||||
-B "${LIBPNG_BUILD_DIR}"
|
||||
-DCMAKE_INSTALL_PREFIX=${LIBPNG_INSTALL_DIR}
|
||||
-DCMAKE_PREFIX_PATH=${ZLIB_INSTALL_DIR}
|
||||
-DZLIB_ROOT=${ZLIB_INSTALL_DIR}
|
||||
RESULT_VARIABLE _png_cfg_res
|
||||
)
|
||||
if(NOT _png_cfg_res EQUAL 0)
|
||||
message(FATAL_ERROR "libpng configure failed")
|
||||
endif()
|
||||
|
||||
# --- ИЗМЕНЕНИЕ: Цикл по конфигурациям Debug и Release ---
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
log("Building libpng (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--build "${LIBPNG_BUILD_DIR}" --config ${cfg}
|
||||
RESULT_VARIABLE _png_build_res
|
||||
)
|
||||
if(NOT _png_build_res EQUAL 0)
|
||||
message(FATAL_ERROR "libpng build failed for configuration ${cfg}")
|
||||
endif()
|
||||
|
||||
# Поскольку вы не используете "cmake --install" для libpng,
|
||||
# здесь нет необходимости в дополнительном шаге установки.
|
||||
# Файлы .lib будут сгенерированы в подкаталоге ${LIBPNG_BUILD_DIR}/${cfg} (например, build/Debug или build/Release).
|
||||
|
||||
endforeach()
|
||||
# ------------------------------------------------------
|
||||
endif()
|
||||
|
||||
add_library(libpng_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(libpng_external_lib PROPERTIES
|
||||
# Предполагая, что libpng использует статический вариант
|
||||
IMPORTED_LOCATION_DEBUG "${LIBPNG_BUILD_DIR}/Debug/libpng16_staticd.lib"
|
||||
IMPORTED_LOCATION_RELEASE "${LIBPNG_BUILD_DIR}/Release/libpng16_static.lib"
|
||||
|
||||
# png.h, pngconf.h – в SRC, pnglibconf.h – в BUILD
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LIBPNG_SRC_DIR};${LIBPNG_BUILD_DIR}"
|
||||
)
|
||||
|
||||
# ===========================================
|
||||
# 4) libzip (v1.11.4.zip → libzip-1.11.4) - НОВАЯ ЗАВИСИМОСТЬ
|
||||
# ===========================================
|
||||
set(LIBZIP_SRC_DIR "${THIRDPARTY_DIR}/libzip-1.11.4")
|
||||
set(LIBZIP_BUILD_DIR "${LIBZIP_SRC_DIR}/build")
|
||||
#set(LIBZIP_INSTALL_DIR "${LIBZIP_SRC_DIR}/install")
|
||||
set(LIBZIP_BASE_DIR "${LIBZIP_SRC_DIR}/install")
|
||||
|
||||
file(MAKE_DIRECTORY "${LIBZIP_BUILD_DIR}")
|
||||
|
||||
# Проверяем, собран ли уже libzip
|
||||
set(_have_zip FALSE)
|
||||
foreach(candidate
|
||||
"${LIBZIP_BASE_DIR}-Debug/lib/zip.lib"
|
||||
"${LIBZIP_BASE_DIR}-Release/lib/zip.lib"
|
||||
)
|
||||
if(EXISTS "${candidate}")
|
||||
set(_have_zip TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _have_zip)
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
log("Configuring libzip (${cfg})...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
-S "${LIBZIP_SRC_DIR}"
|
||||
-B "${LIBZIP_SRC_DIR}/build-${cfg}"
|
||||
-DCMAKE_INSTALL_PREFIX=${LIBZIP_BASE_DIR}-${cfg}
|
||||
-DCMAKE_PREFIX_PATH=${ZLIB_INSTALL_DIR}
|
||||
-DZLIB_ROOT=${ZLIB_INSTALL_DIR}
|
||||
-DENABLE_COMMONCRYPTO=OFF
|
||||
-DENABLE_GNUTLS=OFF
|
||||
-DENABLE_MBEDTLS=OFF
|
||||
-DENABLE_OPENSSL=OFF
|
||||
-DENABLE_WINDOWS_CRYPTO=OFF
|
||||
-DENABLE_FUZZ=OFF
|
||||
RESULT_VARIABLE _zip_cfg_res
|
||||
)
|
||||
if(NOT _zip_cfg_res EQUAL 0)
|
||||
message(FATAL_ERROR "libzip configure failed")
|
||||
endif()
|
||||
log("Building libzip (${cfg}) ...")
|
||||
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build "${LIBZIP_SRC_DIR}/build-${cfg}" --config ${cfg} -v
|
||||
RESULT_VARIABLE _zip_build_res
|
||||
)
|
||||
if(NOT _zip_build_res EQUAL 0)
|
||||
message(FATAL_ERROR "libzip build failed for configuration ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Installing libzip (${cfg}) ...")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --install "${LIBZIP_SRC_DIR}/build-${cfg}" --config ${cfg} -v
|
||||
RESULT_VARIABLE _zip_inst_res
|
||||
)
|
||||
if(NOT _zip_inst_res EQUAL 0)
|
||||
message(FATAL_ERROR "libzip install failed for configuration ${cfg}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
|
||||
add_library(libzip_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(libzip_external_lib PROPERTIES
|
||||
IMPORTED_LOCATION_DEBUG "${LIBZIP_BASE_DIR}-Debug/lib/zip.lib" # ИСПРАВЛЕНО
|
||||
IMPORTED_LOCATION_RELEASE "${LIBZIP_BASE_DIR}-Release/lib/zip.lib" # ИСПРАВЛЕНО
|
||||
|
||||
INTERFACE_INCLUDE_DIRECTORIES "$<IF:$<CONFIG:Debug>,${LIBZIP_BASE_DIR}-Debug/include,${LIBZIP_BASE_DIR}-Release/include>"
|
||||
# libzip требует zlib для линковки
|
||||
INTERFACE_LINK_LIBRARIES zlib_external_lib
|
||||
)
|
||||
|
||||
# ===========================================
|
||||
# 5) FreeType (2.14.1) - dependency for SDL_ttf
|
||||
# ===========================================
|
||||
set(FREETYPE_SRC_DIR "${THIRDPARTY_DIR}/freetype-2.14.1")
|
||||
set(FREETYPE_BASE_DIR "${FREETYPE_SRC_DIR}/install")
|
||||
|
||||
set(_have_freetype TRUE)
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
if(NOT EXISTS "${FREETYPE_BASE_DIR}-${cfg}/lib/freetype.lib" AND
|
||||
NOT EXISTS "${FREETYPE_BASE_DIR}-${cfg}/lib/freetyped.lib")
|
||||
set(_have_freetype FALSE)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _have_freetype)
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
log("Configuring FreeType (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
-S "${FREETYPE_SRC_DIR}"
|
||||
-B "${FREETYPE_SRC_DIR}/build-${cfg}"
|
||||
-DCMAKE_INSTALL_PREFIX=${FREETYPE_BASE_DIR}-${cfg}
|
||||
-DCMAKE_PREFIX_PATH="${ZLIB_INSTALL_DIR};${LIBPNG_INSTALL_DIR}"
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE
|
||||
-DFT_DISABLE_BROTLI=ON
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
RESULT_VARIABLE _ft_cfg_res
|
||||
)
|
||||
if(NOT _ft_cfg_res EQUAL 0)
|
||||
message(FATAL_ERROR "FreeType configure failed for ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Building FreeType (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--build "${FREETYPE_SRC_DIR}/build-${cfg}" --config ${cfg}
|
||||
RESULT_VARIABLE _ft_build_res
|
||||
)
|
||||
if(NOT _ft_build_res EQUAL 0)
|
||||
message(FATAL_ERROR "FreeType build failed for ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Installing FreeType (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--install "${FREETYPE_SRC_DIR}/build-${cfg}" --config ${cfg}
|
||||
RESULT_VARIABLE _ft_inst_res
|
||||
)
|
||||
if(NOT _ft_inst_res EQUAL 0)
|
||||
message(FATAL_ERROR "FreeType install failed for ${cfg}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(_ft_debug_lib "")
|
||||
foreach(cand
|
||||
"${FREETYPE_BASE_DIR}-Debug/lib/freetyped.lib"
|
||||
"${FREETYPE_BASE_DIR}-Debug/lib/freetype.lib"
|
||||
)
|
||||
if(EXISTS "${cand}")
|
||||
set(_ft_debug_lib "${cand}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(_ft_release_lib "")
|
||||
foreach(cand
|
||||
"${FREETYPE_BASE_DIR}-Release/lib/freetype.lib"
|
||||
)
|
||||
if(EXISTS "${cand}")
|
||||
set(_ft_release_lib "${cand}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(_ft_debug_lib STREQUAL "" OR _ft_release_lib STREQUAL "")
|
||||
message(FATAL_ERROR "FreeType libs not found in ${FREETYPE_BASE_DIR}-Debug/Release")
|
||||
endif()
|
||||
|
||||
add_library(freetype_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(freetype_external_lib PROPERTIES
|
||||
IMPORTED_LOCATION_DEBUG "${_ft_debug_lib}"
|
||||
IMPORTED_LOCATION_RELEASE "${_ft_release_lib}"
|
||||
)
|
||||
target_include_directories(freetype_external_lib INTERFACE
|
||||
"$<IF:$<CONFIG:Debug>,${FREETYPE_BASE_DIR}-Debug/include/freetype2,${FREETYPE_BASE_DIR}-Release/include/freetype2>"
|
||||
"$<IF:$<CONFIG:Debug>,${FREETYPE_BASE_DIR}-Debug/include,${FREETYPE_BASE_DIR}-Release/include>"
|
||||
)
|
||||
|
||||
# ===========================================
|
||||
# 6) SDL_ttf (2.24.0)
|
||||
# ===========================================
|
||||
set(SDL2TTF_SRC_DIR "${THIRDPARTY_DIR}/SDL_ttf-release-2.24.0")
|
||||
set(SDL2TTF_BASE_DIR "${SDL2TTF_SRC_DIR}/install")
|
||||
|
||||
set(_have_sdl2ttf TRUE)
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
if(NOT EXISTS "${SDL2TTF_BASE_DIR}-${cfg}/lib/SDL2_ttf.lib" AND
|
||||
NOT EXISTS "${SDL2TTF_BASE_DIR}-${cfg}/lib/SDL2_ttfd.lib")
|
||||
set(_have_sdl2ttf FALSE)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _have_sdl2ttf)
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
|
||||
if(cfg STREQUAL "Debug")
|
||||
set(_SDL2_LIB "${SDL2_INSTALL_DIR}/lib/SDL2d.lib")
|
||||
else()
|
||||
set(_SDL2_LIB "${SDL2_INSTALL_DIR}/lib/SDL2.lib")
|
||||
endif()
|
||||
|
||||
set(_FT_PREFIX "${FREETYPE_BASE_DIR}-${cfg}")
|
||||
|
||||
set(_FT_LIB "")
|
||||
foreach(cand
|
||||
"${_FT_PREFIX}/lib/freetyped.lib"
|
||||
"${_FT_PREFIX}/lib/freetype.lib"
|
||||
)
|
||||
if(EXISTS "${cand}")
|
||||
set(_FT_LIB "${cand}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(_FT_LIB STREQUAL "")
|
||||
message(FATAL_ERROR "FreeType library not found for ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Configuring SDL_ttf (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-G "${CMAKE_GENERATOR}"
|
||||
-S "${SDL2TTF_SRC_DIR}"
|
||||
-B "${SDL2TTF_SRC_DIR}/build-${cfg}"
|
||||
-DCMAKE_INSTALL_PREFIX=${SDL2TTF_BASE_DIR}-${cfg}
|
||||
-DCMAKE_PREFIX_PATH=${_FT_PREFIX};${SDL2_INSTALL_DIR}
|
||||
-DSDL2_LIBRARY=${_SDL2_LIB}
|
||||
-DSDL2_INCLUDE_DIR=${SDL2_INSTALL_DIR}/include/SDL2
|
||||
-DFREETYPE_LIBRARY=${_FT_LIB}
|
||||
-DFREETYPE_INCLUDE_DIR=${_FT_PREFIX}/include/freetype2
|
||||
-DFREETYPE_INCLUDE_DIRS=${_FT_PREFIX}/include/freetype2
|
||||
-DSDL2TTF_VENDORED=OFF
|
||||
-DSDL2TTF_SAMPLES=OFF
|
||||
RESULT_VARIABLE _ttf_cfg_res
|
||||
)
|
||||
if(NOT _ttf_cfg_res EQUAL 0)
|
||||
message(FATAL_ERROR "SDL_ttf configure failed for ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Building SDL_ttf (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--build "${SDL2TTF_SRC_DIR}/build-${cfg}" --config ${cfg}
|
||||
RESULT_VARIABLE _ttf_build_res
|
||||
)
|
||||
if(NOT _ttf_build_res EQUAL 0)
|
||||
message(FATAL_ERROR "SDL_ttf build failed for ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Installing SDL_ttf (${cfg}) ...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--install "${SDL2TTF_SRC_DIR}/build-${cfg}" --config ${cfg}
|
||||
RESULT_VARIABLE _ttf_inst_res
|
||||
)
|
||||
if(NOT _ttf_inst_res EQUAL 0)
|
||||
message(FATAL_ERROR "SDL_ttf install failed for ${cfg}")
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(_ttf_debug_lib "")
|
||||
foreach(cand
|
||||
"${SDL2TTF_BASE_DIR}-Debug/lib/SDL2_ttfd.lib"
|
||||
"${SDL2TTF_BASE_DIR}-Debug/lib/SDL2_ttf.lib"
|
||||
)
|
||||
if(EXISTS "${cand}")
|
||||
set(_ttf_debug_lib "${cand}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(_ttf_release_lib "")
|
||||
foreach(cand
|
||||
"${SDL2TTF_BASE_DIR}-Release/lib/SDL2_ttf.lib"
|
||||
)
|
||||
if(EXISTS "${cand}")
|
||||
set(_ttf_release_lib "${cand}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(_ttf_debug_lib STREQUAL "" OR _ttf_release_lib STREQUAL "")
|
||||
message(FATAL_ERROR "SDL_ttf libs not found in install-Debug / install-Release")
|
||||
endif()
|
||||
|
||||
add_library(SDL2_ttf_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(SDL2_ttf_external_lib PROPERTIES
|
||||
IMPORTED_LOCATION_DEBUG "${_ttf_debug_lib}"
|
||||
IMPORTED_LOCATION_RELEASE "${_ttf_release_lib}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
"$<IF:$<CONFIG:Debug>,${SDL2TTF_BASE_DIR}-Debug/include,${SDL2TTF_BASE_DIR}-Release/include>;$<IF:$<CONFIG:Debug>,${SDL2TTF_BASE_DIR}-Debug/include/SDL2,${SDL2TTF_BASE_DIR}-Release/include/SDL2>"
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
"SDL2_external_lib;freetype_external_lib"
|
||||
)
|
||||
|
||||
# ===========================================
|
||||
# 7) Eigen (5.0.0.zip → eigen-5.0.0) - HEADER-ONLY
|
||||
# ===========================================
|
||||
set(EIGEN_SRC_DIR "${THIRDPARTY_DIR}/eigen-5.0.0")
|
||||
|
||||
if(NOT TARGET eigen_external_lib)
|
||||
add_library(eigen_external_lib INTERFACE)
|
||||
target_include_directories(eigen_external_lib INTERFACE "${EIGEN_SRC_DIR}")
|
||||
endif()
|
||||
|
||||
# ===========================================
|
||||
# 8) Boost (1.90.0) - HEADER-ONLY
|
||||
# ===========================================
|
||||
set(BOOST_VERSION "1.90.0")
|
||||
set(BOOST_ARCHIVE_NAME "boost_1_90_0.zip")
|
||||
set(BOOST_ARCHIVE "${THIRDPARTY_DIR}/${BOOST_ARCHIVE_NAME}")
|
||||
# Внутри архива папка называется boost_1_90_0
|
||||
set(BOOST_SRC_DIR "${THIRDPARTY_DIR}/boost_1_90_0")
|
||||
|
||||
if(NOT TARGET boost_external_lib)
|
||||
add_library(boost_external_lib INTERFACE)
|
||||
# Boost заголовки находятся непосредственно в корне распакованной папки
|
||||
target_include_directories(boost_external_lib INTERFACE "${BOOST_SRC_DIR}")
|
||||
endif()
|
||||
@@ -0,0 +1,36 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(AudioPlayer)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Use pkg-config to find Vorbis
|
||||
#find_package(PkgConfig REQUIRED)
|
||||
#pkg_check_modules(VORBIS REQUIRED vorbis vorbisfile)
|
||||
#pkg_check_modules(OGG REQUIRED ogg)
|
||||
find_package(OpenAL REQUIRED)
|
||||
|
||||
add_library(audioplayer
|
||||
src/AudioPlayer.cpp
|
||||
include/AudioPlayer.hpp
|
||||
)
|
||||
|
||||
target_include_directories(audioplayer
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${OPENAL_INCLUDE_DIR}
|
||||
${VORBIS_INCLUDE_DIRS}
|
||||
${OGG_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(audioplayer
|
||||
PUBLIC
|
||||
${OPENAL_LIBRARY}
|
||||
${VORBIS_LIBRARIES}
|
||||
${OGG_LIBRARIES}
|
||||
)
|
||||
|
||||
# Test executable
|
||||
add_executable(test_audio examples/test_audio.cpp)
|
||||
target_link_libraries(test_audio PRIVATE audioplayer stdc++fs)
|
||||
#git add ../../sounds
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "AudioPlayer.hpp"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
int main() {
|
||||
try {
|
||||
AudioPlayer player;
|
||||
const std::string filename = "Symphony No.6 (1st movement).ogg";
|
||||
|
||||
std::cout << "🔍 Looking for file: " << filename << " in sounds directory...\n";
|
||||
|
||||
if (!player.playFromSoundsDir(filename)) {
|
||||
std::cout << "❌ Failed to play audio file\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "✅ Playing symphony...\n";
|
||||
|
||||
// Check status for 30 seconds
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
std::cout << "📊 Status: " << (player.isPlaying() ? "Playing ▶️" : "Stopped ⏹️") << "\n";
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "❌ Error: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
class AudioPlayer {
|
||||
public:
|
||||
AudioPlayer();
|
||||
~AudioPlayer();
|
||||
|
||||
// Для музыки с зацикливанием (если filename пустой - продолжает играть текущую)
|
||||
bool playMusic(const std::string& filename = "");
|
||||
|
||||
// Для одноразовых звуковых эффектов
|
||||
bool playSound(const std::string& filename);
|
||||
|
||||
void stop();
|
||||
bool isPlaying() const;
|
||||
|
||||
private:
|
||||
ALCdevice* device;
|
||||
ALCcontext* context;
|
||||
ALuint musicSource; // Источник для музыки
|
||||
ALuint soundSource; // Источник для звуков
|
||||
ALuint musicBuffer; // Буфер для музыки
|
||||
ALuint soundBuffer; // Буфер для звуков
|
||||
bool playing;
|
||||
std::string currentMusic; // Хранит имя текущего музыкального файла
|
||||
|
||||
std::vector<char> loadOgg(const std::string& filename, ALuint buffer);
|
||||
std::string findFileInSounds(const std::string& filename);
|
||||
bool isOggFile(const std::string& filename) const;
|
||||
};
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "AudioPlayer.hpp"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
|
||||
AudioPlayer::AudioPlayer() : device(nullptr), context(nullptr),
|
||||
musicSource(0), soundSource(0), musicBuffer(0), soundBuffer(0), playing(false) {
|
||||
device = alcOpenDevice(nullptr);
|
||||
if (!device) {
|
||||
throw std::runtime_error("Failed to open audio device");
|
||||
}
|
||||
|
||||
context = alcCreateContext(device, nullptr);
|
||||
if (!context) {
|
||||
alcCloseDevice(device);
|
||||
throw std::runtime_error("Failed to create audio context");
|
||||
}
|
||||
|
||||
alcMakeContextCurrent(context);
|
||||
alGenSources(1, &musicSource);
|
||||
alGenSources(1, &soundSource);
|
||||
alGenBuffers(1, &musicBuffer);
|
||||
alGenBuffers(1, &soundBuffer);
|
||||
}
|
||||
|
||||
AudioPlayer::~AudioPlayer() {
|
||||
if (musicSource)
|
||||
alDeleteSources(1, &musicSource);
|
||||
if (soundSource)
|
||||
alDeleteSources(1, &soundSource);
|
||||
if (musicBuffer)
|
||||
alDeleteBuffers(1, &musicBuffer);
|
||||
if (soundBuffer)
|
||||
alDeleteBuffers(1, &soundBuffer);
|
||||
|
||||
if (context) {
|
||||
alcMakeContextCurrent(nullptr);
|
||||
alcDestroyContext(context);
|
||||
}
|
||||
if (device)
|
||||
alcCloseDevice(device);
|
||||
}
|
||||
|
||||
bool AudioPlayer::isOggFile(const std::string& filename) const {
|
||||
std::string ext = std::filesystem::path(filename).extension().string();
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
|
||||
return ext == ".ogg";
|
||||
}
|
||||
|
||||
std::string AudioPlayer::findFileInSounds(const std::string& filename) {
|
||||
// Primary search path - "sounds" directory next to executable
|
||||
std::filesystem::path soundsDir = std::filesystem::current_path() / "sounds";
|
||||
|
||||
// Alternative search paths
|
||||
std::vector<std::filesystem::path> altPaths = {
|
||||
std::filesystem::current_path() / ".." / "sounds", // One level up
|
||||
std::filesystem::current_path() / ".." / ".." / "sounds", // Two levels up
|
||||
"/home/albert/gay-jam/ZeptoLabTest1/sounds" // Absolute path
|
||||
};
|
||||
|
||||
std::cout << "🔍 Searching for \"" << filename << "\" in:\n";
|
||||
std::cout << " " << soundsDir << "\n";
|
||||
|
||||
if (std::filesystem::exists(soundsDir / filename)) {
|
||||
return (soundsDir / filename).string();
|
||||
}
|
||||
|
||||
// Try alternative paths
|
||||
for (const auto& path : altPaths) {
|
||||
std::cout << " " << path << "\n";
|
||||
if (std::filesystem::exists(path / filename)) {
|
||||
return (path / filename).string();
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("❌ File not found: " + filename);
|
||||
}
|
||||
|
||||
std::vector<char> AudioPlayer::loadOgg(const std::string& filename, ALuint buffer) {
|
||||
FILE* file = fopen(filename.c_str(), "rb");
|
||||
if (!file) {
|
||||
throw std::runtime_error("Cannot open file: " + filename);
|
||||
}
|
||||
|
||||
OggVorbis_File vf;
|
||||
if (ov_open_callbacks(file, &vf, nullptr, 0, OV_CALLBACKS_DEFAULT) < 0) {
|
||||
fclose(file);
|
||||
throw std::runtime_error("Input not an Ogg file: " + filename);
|
||||
}
|
||||
|
||||
vorbis_info* vi = ov_info(&vf, -1);
|
||||
std::vector<char> audioData;
|
||||
char data[4096];
|
||||
int bitstream;
|
||||
long bytes;
|
||||
|
||||
do {
|
||||
bytes = ov_read(&vf, data, sizeof(data), 0, 2, 1, &bitstream);
|
||||
if (bytes > 0) {
|
||||
audioData.insert(audioData.end(), data, data + bytes);
|
||||
}
|
||||
} while (bytes > 0);
|
||||
|
||||
// Setup the buffer with the audio data
|
||||
alBufferData(buffer,
|
||||
(vi->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
|
||||
audioData.data(),
|
||||
audioData.size(),
|
||||
vi->rate);
|
||||
|
||||
ov_clear(&vf);
|
||||
return audioData;
|
||||
}
|
||||
|
||||
bool AudioPlayer::playMusic(const std::string& filename) {
|
||||
try {
|
||||
// Если filename пустой, просто проверяем играет ли музыка
|
||||
if (filename.empty()) {
|
||||
if (!isPlaying()) {
|
||||
alSourcei(musicSource, AL_LOOPING, AL_TRUE); // Включаем зацикливание
|
||||
alSourcePlay(musicSource);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Если filename не пустой, загружаем новую музыку
|
||||
if (!isOggFile(filename)) {
|
||||
std::cerr << "❌ Error: Music file must be an .ogg file\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string fullPath = findFileInSounds(filename);
|
||||
std::cout << "✅ Found music file: " << fullPath << "\n";
|
||||
|
||||
// Останавливаем текущую музыку
|
||||
alSourceStop(musicSource);
|
||||
|
||||
// Загружаем и настраиваем новую музыку
|
||||
loadOgg(fullPath, musicBuffer);
|
||||
alSourcei(musicSource, AL_BUFFER, musicBuffer);
|
||||
alSourcei(musicSource, AL_LOOPING, AL_TRUE); // Включаем зацикливание
|
||||
|
||||
std::cout << "▶️ Starting music playback... " << musicSource << std::endl;
|
||||
std::cout << "▶️ Music buffer... " << musicBuffer << std::endl;
|
||||
alSourcePlay(musicSource);
|
||||
|
||||
currentMusic = filename;
|
||||
playing = true;
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "❌ Error playing music: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioPlayer::playSound(const std::string& filename) {
|
||||
try {
|
||||
if (!isOggFile(filename)) {
|
||||
std::cerr << "❌ Error: Sound file must be an .ogg file\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string fullPath = findFileInSounds(filename);
|
||||
std::cout << "✅ Found sound file: " << fullPath << "\n";
|
||||
|
||||
// Загружаем и настраиваем звук
|
||||
loadOgg(fullPath, soundBuffer);
|
||||
alSourcei(soundSource, AL_BUFFER, soundBuffer);
|
||||
alSourcei(soundSource, AL_LOOPING, AL_FALSE); // Выключаем зацикливание
|
||||
|
||||
std::cout << "▶️ Playing sound effect...\n";
|
||||
alSourcePlay(soundSource);
|
||||
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "❌ Error playing sound: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioPlayer::stop() {
|
||||
alSourceStop(musicSource);
|
||||
alSourceStop(soundSource);
|
||||
playing = false;
|
||||
}
|
||||
|
||||
bool AudioPlayer::isPlaying() const {
|
||||
ALint state;
|
||||
alGetSourcei(musicSource, AL_SOURCE_STATE, &state);
|
||||
return state == AL_PLAYING;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "FrameLayout",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"children": [
|
||||
{
|
||||
"type": "FrameLayout",
|
||||
"name": "leftPanel",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 320,
|
||||
"height": 400,
|
||||
"children": [
|
||||
{
|
||||
"type": "LinearLayout",
|
||||
"name": "mainButtons",
|
||||
"orientation": "vertical",
|
||||
"spacing": 10,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 300,
|
||||
"height": 300,
|
||||
"children": [
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "playButton",
|
||||
"x": 100,
|
||||
"y": 300,
|
||||
"width": 200,
|
||||
"height": 50,
|
||||
"animations": {
|
||||
"buttonsExit": {
|
||||
"repeat": false,
|
||||
"steps": [
|
||||
{
|
||||
"type": "move",
|
||||
"to": [
|
||||
-400,
|
||||
0
|
||||
],
|
||||
"duration": 1.0,
|
||||
"easing": "easein"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"textures": {
|
||||
"normal": "./resources/button.png",
|
||||
"hover": "./resources/sand.png",
|
||||
"pressed": "./resources/button.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "settingsButton",
|
||||
"x": 100,
|
||||
"y": 200,
|
||||
"width": 200,
|
||||
"height": 50,
|
||||
"animations": {
|
||||
"buttonsExit": {
|
||||
"repeat": false,
|
||||
"steps": [
|
||||
{
|
||||
"type": "wait",
|
||||
"duration": 0.5
|
||||
},
|
||||
{
|
||||
"type": "move",
|
||||
"to": [
|
||||
-400,
|
||||
0
|
||||
],
|
||||
"duration": 1.0,
|
||||
"easing": "easein"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"textures": {
|
||||
"normal": "./resources/sand.png",
|
||||
"hover": "./resources/button.png",
|
||||
"pressed": "./resources/sand.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "exitButton",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 200,
|
||||
"height": 50,
|
||||
"animations": {
|
||||
"buttonsExit": {
|
||||
"repeat": false,
|
||||
"steps": [
|
||||
{
|
||||
"type": "wait",
|
||||
"duration": 1.0
|
||||
},
|
||||
{
|
||||
"type": "move",
|
||||
"to": [
|
||||
-400,
|
||||
0
|
||||
],
|
||||
"duration": 1.0,
|
||||
"easing": "easein"
|
||||
}
|
||||
]
|
||||
},
|
||||
"bgScroll": {
|
||||
"repeat": true,
|
||||
"steps": [
|
||||
{
|
||||
"type": "move",
|
||||
"to": [
|
||||
1280,
|
||||
0
|
||||
],
|
||||
"duration": 5.0,
|
||||
"easing": "linear"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"textures": {
|
||||
"normal": "./resources/rock.png",
|
||||
"hover": "./resources/button.png",
|
||||
"pressed": "./resources/rock.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Slider",
|
||||
"name": "musicVolumeSlider",
|
||||
"x": 1140,
|
||||
"y": 100,
|
||||
"width": 10,
|
||||
"height": 500,
|
||||
"value": 0.5,
|
||||
"orientation": "vertical",
|
||||
"textures": {
|
||||
"track": "./resources/musicVolumeBarTexture.png",
|
||||
"knob": "./resources/musicVolumeBarButton.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
.idea/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# CMake build files
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
*.cmake
|
||||
|
||||
# Android Studio
|
||||
*.iml
|
||||
.idea/
|
||||
.cxx/
|
||||
.gradle/
|
||||
.DS_Store
|
||||
/captures/
|
||||
.externalNativeBuild/
|
||||
|
||||
# NDK
|
||||
.obj/
|
||||
*.o
|
||||
*.so
|
||||
|
||||
# SDL2 (если используешь)
|
||||
libs/
|
||||
obj/
|
||||
|
||||
# Временные файлы
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.thumbs.db
|
||||
desktop.ini
|
||||
|
||||
# Проектные специфичные
|
||||
app/build/
|
||||
*.log
|
||||
app/jni/libpng
|
||||
app/jni/SDL
|
||||
app/jni/zlib
|
||||
|
||||
app/src/main/assets/resources
|
||||
|
||||
@@ -60,11 +60,9 @@ android {
|
||||
|
||||
if (buildAsLibrary) {
|
||||
libraryVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
def outputFile = output.outputFile
|
||||
if (outputFile != null && outputFile.name.endsWith(".aar")) {
|
||||
def fileName = "org.libsdl.app.aar";
|
||||
output.outputFile = new File(outputFile.parent, fileName);
|
||||
variant.outputs.all { output ->
|
||||
if (output.outputFileName != null && output.outputFileName.endsWith(".aar")) {
|
||||
output.outputFileName = "org.libsdl.app.aar"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
project(GAME)
|
||||
|
||||
if(POLICY CMP0079)
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
endif()
|
||||
|
||||
# ==============================================================================
|
||||
# 1. АВТО-ЗАГРУЗКА ИСХОДНИКОВ
|
||||
# ==============================================================================
|
||||
# Путь относительно текущего файла к папке с общими скриптами
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/FetchDependencies.cmake")
|
||||
|
||||
# Теперь мы уверены, что папка thirdparty заполнена исходниками.
|
||||
# Определяем базовый путь для удобства:
|
||||
set(TP_ROOT "${THIRDPARTY_DIR}")
|
||||
|
||||
# ==============================================================================
|
||||
# 2. НАСТРОЙКА ЗАВИСИМОСТЕЙ (СОБИРАЕМ ИЗ ИСХОДНИКОВ)
|
||||
# ==============================================================================
|
||||
|
||||
# --- ZLIB ---
|
||||
add_subdirectory("${TP_ROOT}/zlib-1.3.1" zlib-build)
|
||||
|
||||
# --- LIBPNG ---
|
||||
set(PNG_STATIC ON CACHE BOOL "Build static library" FORCE)
|
||||
set(PNG_SHARED OFF CACHE BOOL "Don't build shared library" FORCE)
|
||||
set(PNG_TESTS OFF CACHE BOOL "Disable tests" FORCE)
|
||||
set(PNG_TOOLS OFF CACHE BOOL "Disable tools" FORCE)
|
||||
set(PNG_EXECUTABLES OFF CACHE BOOL "Disable executables" FORCE)
|
||||
set(PNG_DEBUG OFF CACHE BOOL "Disable debug" FORCE)
|
||||
set(SKIP_INSTALL_ALL ON CACHE BOOL "Skip installation" FORCE)
|
||||
set(PNG_HARDWARE_OPTIMIZATIONS OFF CACHE BOOL "Disable hardware optimizations" FORCE)
|
||||
set(PNG_ARM_NEON "off" CACHE STRING "Disable ARM NEON" FORCE)
|
||||
|
||||
add_subdirectory("${TP_ROOT}/libpng-1.6.51" libpng-build)
|
||||
|
||||
# --- SDL2 ---
|
||||
# Android-версия SDL требует специфичных настроек, но add_subdirectory обычно подхватывает их сама
|
||||
add_subdirectory("${TP_ROOT}/SDL-release-2.32.10" sdl-build)
|
||||
|
||||
# --- LIBZIP ---
|
||||
# Отключаем поиск системных крипто-библиотек, так как в NDK их может не быть в стандартных путях
|
||||
set(ENABLE_GNUTLS OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_OPENSSL OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_WINDOWS_CRYPTO OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_COMMONCRYPTO OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_MBEDTLS OFF CACHE BOOL "" FORCE)
|
||||
|
||||
add_subdirectory("${TP_ROOT}/libzip-1.11.4" libzip-build)
|
||||
|
||||
# --- EIGEN & BOOST (Header-only) ---
|
||||
# Мы создаем интерфейсные таргеты здесь, чтобы они были доступны в подпапке src
|
||||
if(NOT TARGET eigen_external_lib)
|
||||
add_library(eigen_external_lib INTERFACE)
|
||||
target_include_directories(eigen_external_lib INTERFACE "${TP_ROOT}/eigen-5.0.0")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET boost_external_lib)
|
||||
add_library(boost_external_lib INTERFACE)
|
||||
target_include_directories(boost_external_lib INTERFACE "${TP_ROOT}/boost_1_90_0")
|
||||
endif()
|
||||
|
||||
# ==============================================================================
|
||||
# 3. ОСНОВНОЙ КОД
|
||||
# ==============================================================================
|
||||
add_subdirectory(src)
|
||||
@@ -0,0 +1,92 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
project(MY_APP CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
# Определение путей
|
||||
set(SOURCE_RES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../resources")
|
||||
set(TARGET_RES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../src/main/assets/resources")
|
||||
|
||||
# Получаем список всех файлов в исходной директории для отслеживания зависимостей
|
||||
file(GLOB_RECURSE RES_FILES RELATIVE "${SOURCE_RES_DIR}" "${SOURCE_RES_DIR}/*")
|
||||
|
||||
set(COPY_COMMANDS "")
|
||||
|
||||
foreach(RES_FILE ${RES_FILES})
|
||||
set(SRC "${SOURCE_RES_DIR}/${RES_FILE}")
|
||||
set(DST "${TARGET_RES_DIR}/${RES_FILE}")
|
||||
|
||||
# Команда копирования конкретного файла, если он изменился
|
||||
add_custom_command(
|
||||
OUTPUT "${DST}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${TARGET_RES_DIR}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SRC}" "${DST}"
|
||||
DEPENDS "${SRC}"
|
||||
COMMENT "Syncing resource: ${RES_FILE}"
|
||||
)
|
||||
list(APPEND RES_OUTPUTS "${DST}")
|
||||
endforeach()
|
||||
|
||||
# Создаем кастомную цель, которая будет запускать процесс копирования
|
||||
add_custom_target(sync_resources ALL DEPENDS ${RES_OUTPUTS})
|
||||
|
||||
|
||||
add_library(main SHARED
|
||||
SDL_android_main.c
|
||||
../../../../src/BoneAnimatedModel.cpp
|
||||
../../../../src/Environment.cpp
|
||||
../../../../src/Game.cpp
|
||||
../../../../src/main.cpp
|
||||
../../../../src/Projectile.cpp
|
||||
../../../../src/SparkEmitter.cpp
|
||||
../../../../src/TextModel.cpp
|
||||
../../../../src/UiManager.cpp
|
||||
../../../../src/utils/Perlin.cpp
|
||||
../../../../src/utils/TaskManager.cpp
|
||||
../../../../src/utils/Utils.cpp
|
||||
../../../../src/planet/PlanetData.cpp
|
||||
../../../../src/planet/PlanetObject.cpp
|
||||
../../../../src/planet/StoneObject.cpp
|
||||
../../../../src/render/FrameBuffer.cpp
|
||||
../../../../src/render/Renderer.cpp
|
||||
../../../../src/render/ShaderManager.cpp
|
||||
../../../../src/render/TextureManager.cpp
|
||||
../../../../src/render/OpenGlExtensions.cpp
|
||||
)
|
||||
|
||||
# Подключаем заголовки
|
||||
target_include_directories(main PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../SDL/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../zlib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../libpng
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/eigen-5.0.0
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/boost_1_90_0
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../libzip
|
||||
)
|
||||
|
||||
# ВАЖНО: Линкуемся с png_static (статика) или png_shared (динамика)
|
||||
# Так как мы установили PNG_STATIC=ON и PNG_SHARED=OFF,
|
||||
# должна создаться цель png_static
|
||||
target_link_libraries(main
|
||||
png_static # ← ЭТО ПРАВИЛЬНОЕ ИМЯ ЦЕЛИ!
|
||||
z
|
||||
SDL2
|
||||
)
|
||||
|
||||
|
||||
find_library(OPENGLES2_LIB GLESv2)
|
||||
|
||||
target_link_libraries(main
|
||||
${OPENGLES2_LIB} # OpenGL ES 2.0/3.0
|
||||
log
|
||||
android
|
||||
OpenSLES
|
||||
dl
|
||||
zip
|
||||
)
|
||||
|
||||
add_dependencies(main sync_resources)
|
||||
@@ -1,6 +1,6 @@
|
||||
#Thu Nov 11 18:20:34 PST 2021
|
||||
#Sat Jan 10 10:31:05 MSK 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,181 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
# Фикс для Ninja на Windows
|
||||
if(NOT CMAKE_MAKE_PROGRAM AND WIN32)
|
||||
set(POTENTIAL_NINJA "${CMAKE_CURRENT_SOURCE_DIR}/ninja/ninja.exe")
|
||||
if(EXISTS "${POTENTIAL_NINJA}")
|
||||
set(CMAKE_MAKE_PROGRAM "${POTENTIAL_NINJA}" CACHE FILEPATH "Path to ninja" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
project(space-game001 CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# --- АВТО-ЗАГРУЗКА ЗАВИСИМОСТЕЙ ---
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/FetchDependencies.cmake")
|
||||
# Теперь гарантированно есть папка ../thirdparty со всеми исходниками
|
||||
|
||||
# Список исходных файлов (без изменений)
|
||||
set(SOURCES
|
||||
../src/main.cpp
|
||||
../src/Game.cpp
|
||||
../src/Game.h
|
||||
../src/Environment.cpp
|
||||
../src/Environment.h
|
||||
../src/render/Renderer.cpp
|
||||
../src/render/Renderer.h
|
||||
../src/render/ShaderManager.cpp
|
||||
../src/render/ShaderManager.h
|
||||
../src/render/TextureManager.cpp
|
||||
../src/render/TextureManager.h
|
||||
../src/TextModel.cpp
|
||||
../src/TextModel.h
|
||||
../src/AudioPlayerAsync.cpp
|
||||
../src/AudioPlayerAsync.h
|
||||
../src/BoneAnimatedModel.cpp
|
||||
../src/BoneAnimatedModel.h
|
||||
../src/render/OpenGlExtensions.cpp
|
||||
../src/render/OpenGlExtensions.h
|
||||
../src/utils/Utils.cpp
|
||||
../src/utils/Utils.h
|
||||
../src/SparkEmitter.cpp
|
||||
../src/SparkEmitter.h
|
||||
../src/planet/PlanetObject.cpp
|
||||
../src/planet/PlanetObject.h
|
||||
../src/planet/PlanetData.cpp
|
||||
../src/planet/PlanetData.h
|
||||
../src/utils/Perlin.cpp
|
||||
../src/utils/Perlin.h
|
||||
../src/utils/TaskManager.cpp
|
||||
../src/utils/TaskManager.h
|
||||
../src/planet/StoneObject.cpp
|
||||
../src/planet/StoneObject.h
|
||||
../src/render/FrameBuffer.cpp
|
||||
../src/render/FrameBuffer.h
|
||||
../src/UiManager.cpp
|
||||
../src/UiManager.h
|
||||
../src/Projectile.h
|
||||
../src/Projectile.cpp
|
||||
../src/network/NetworkInterface.h
|
||||
../src/network/LocalClient.h
|
||||
../src/network/LocalClient.cpp
|
||||
../src/network/ClientState.h
|
||||
../src/network/ClientState.cpp
|
||||
../src/network/WebSocketClientBase.h
|
||||
../src/network/WebSocketClientBase.cpp
|
||||
../src/network/WebSocketClientEmscripten.h
|
||||
../src/network/WebSocketClientEmscripten.cpp
|
||||
../src/render/TextRenderer.h
|
||||
../src/render/TextRenderer.cpp
|
||||
../src/MenuManager.h
|
||||
../src/MenuManager.cpp
|
||||
../src/Space.h
|
||||
../src/Space.cpp
|
||||
../src/GameConstants.h
|
||||
../src/GameConstants.cpp
|
||||
)
|
||||
|
||||
add_executable(space-game001 ${SOURCES})
|
||||
|
||||
# Настройка путей к инклудам (используем скачанные исходники)
|
||||
target_include_directories(space-game001 PRIVATE
|
||||
../src
|
||||
../thirdparty/eigen-5.0.0
|
||||
../thirdparty/boost_1_90_0
|
||||
)
|
||||
|
||||
# Сборка libzip через add_subdirectory (Emscripten соберет её из исходников)
|
||||
# Опции для либзипа, чтобы он не искал лишнего в системе
|
||||
set(ENABLE_GNUTLS OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_OPENSSL OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_WINDOWS_CRYPTO OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_COMMONCRYPTO OFF CACHE BOOL "" FORCE)
|
||||
|
||||
add_subdirectory("../thirdparty/libzip-1.11.4" libzip-build)
|
||||
|
||||
target_link_libraries(space-game001 PRIVATE zip z websocket.js)
|
||||
|
||||
# Эмскриптен-флаги
|
||||
set(EMSCRIPTEN_FLAGS
|
||||
"-sUSE_SDL=2"
|
||||
"-sUSE_SDL_IMAGE=2"
|
||||
"-sUSE_LIBPNG=1"
|
||||
"-sUSE_ZLIB=1"
|
||||
"-sUSE_SDL_TTF=2"
|
||||
#"-pthread"
|
||||
#"-sUSE_PTHREADS=1"
|
||||
"-fexceptions"
|
||||
"-DNETWORK"
|
||||
)
|
||||
|
||||
target_compile_options(space-game001 PRIVATE ${EMSCRIPTEN_FLAGS} "-O2")
|
||||
|
||||
# Only loading.png and the shaders used before resources.zip is ready are preloaded.
|
||||
# resources.zip is downloaded asynchronously at runtime and served as a separate file.
|
||||
set(EMSCRIPTEN_LINK_FLAGS
|
||||
${EMSCRIPTEN_FLAGS}
|
||||
"-O2"
|
||||
#"-sPTHREAD_POOL_SIZE=4"
|
||||
"-sALLOW_MEMORY_GROWTH=1"
|
||||
"-sFULL_ES3=1"
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/loading.png@resources/loading.png"
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/shaders@resources/shaders"
|
||||
)
|
||||
|
||||
# Применяем настройки линковки
|
||||
target_link_options(space-game001 PRIVATE ${EMSCRIPTEN_LINK_FLAGS})
|
||||
|
||||
# Для совместимости со старыми версиями CMake, если target_link_options недостаточно
|
||||
string(REPLACE ";" " " EMSCRIPTEN_LINK_FLAGS_STR "${EMSCRIPTEN_LINK_FLAGS}")
|
||||
set_target_properties(space-game001 PROPERTIES
|
||||
LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS_STR}"
|
||||
SUFFIX ".html"
|
||||
)
|
||||
|
||||
# --- Ресурсы и Деплой (без изменений) ---
|
||||
set(RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../resources")
|
||||
set(RESOURCES_ZIP "${CMAKE_CURRENT_BINARY_DIR}/resources.zip")
|
||||
get_filename_component(RESOURCES_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${RESOURCES_ZIP}"
|
||||
COMMAND ${CMAKE_COMMAND} -E tar "cf" "${RESOURCES_ZIP}" --format=zip "resources"
|
||||
WORKING_DIRECTORY "${RESOURCES_PARENT_DIR}"
|
||||
DEPENDS "${RESOURCES_PARENT_DIR}/resources"
|
||||
)
|
||||
|
||||
add_custom_target(pack_resources DEPENDS "${RESOURCES_ZIP}")
|
||||
add_dependencies(space-game001 pack_resources)
|
||||
|
||||
|
||||
# Определяем путь к директории установки (относительно папки билда)
|
||||
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/public")
|
||||
|
||||
# 1. Устанавливаем основной HTML файл
|
||||
install(TARGETS space-game001
|
||||
RUNTIME DESTINATION .
|
||||
)
|
||||
|
||||
# 2. Устанавливаем сопутствующие файлы (JS, WASM и сгенерированный архив данных)
|
||||
# Emscripten создает их в той же папке, что и таргет
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/space-game001.js"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/space-game001.wasm"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/space-game001.data"
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/space-game001plain.html"
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
# resources.zip is served separately and downloaded asynchronously at runtime
|
||||
install(FILES "${RESOURCES_ZIP}" DESTINATION .)
|
||||
|
||||
add_custom_command(TARGET space-game001 POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} --install .
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
COMMENT "Automatically deploying to public directory..."
|
||||
)
|
||||
@@ -0,0 +1,39 @@
|
||||
# how to build
|
||||
|
||||
If emsdk is not installed, you need to clone it from here: https://github.com/emscripten-core/emsdk
|
||||
|
||||
and install:
|
||||
```
|
||||
C:\Work\Projects\emsdk\emsdk.bat install latest
|
||||
```
|
||||
|
||||
Then activate the environment:
|
||||
```
|
||||
C:\Work\Projects\emsdk\emsdk.bat activate latest
|
||||
C:\Work\Projects\emsdk\emsdk_env.bat
|
||||
```
|
||||
|
||||
|
||||
Optionally clear cache:
|
||||
```
|
||||
emcc --clear-cache
|
||||
embuilder build sdl2 sdl2_ttf sdl2_image sdl2_image_jpg sdl2_image_png
|
||||
```
|
||||
|
||||
Build:
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
emcmake cmake -G Ninja ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
Optionally install:
|
||||
```
|
||||
cmake --install .
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
emrun --no_browser --port 8080 public
|
||||
```
|
||||
@@ -0,0 +1,2 @@
|
||||
<!doctypehtml><html lang=en-us><head><meta charset=utf-8><meta content="text/html; charset=utf-8"http-equiv=Content-Type><title>Emscripten-Generated Code</title><style>body{font-family:arial;margin:0;padding:none}.emscripten{padding-right:0;margin-left:auto;margin-right:auto;display:block}div.emscripten{text-align:center}div.emscripten_border{border:1px solid #000}canvas.emscripten{border:0 none;background-color:#000}#emscripten_logo{display:inline-block;margin:0;padding:6px;width:265px}.spinner{height:30px;width:30px;margin:0;margin-top:20px;margin-left:20px;display:inline-block;vertical-align:top;-webkit-animation:rotation .8s linear infinite;-moz-animation:rotation .8s linear infinite;-o-animation:rotation .8s linear infinite;animation:rotation .8s linear infinite;border-left:5px solid #ebebeb;border-right:5px solid #ebebeb;border-bottom:5px solid #ebebeb;border-top:5px solid #787878;border-radius:100%;background-color:#bdd72e}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@-moz-keyframes rotation{from{-moz-transform:rotate(0)}to{-moz-transform:rotate(360deg)}}@-o-keyframes rotation{from{-o-transform:rotate(0)}to{-o-transform:rotate(360deg)}}@keyframes rotation{from{transform:rotate(0)}to{transform:rotate(360deg)}}#status{display:inline-block;vertical-align:top;margin-top:30px;margin-left:20px;font-weight:700;color:#787878}#progress{height:20px;width:300px}#controls{display:inline-block;float:right;vertical-align:top;margin-top:30px;margin-right:20px}#output{width:100%;height:200px;margin:0 auto;margin-top:10px;border-left:0;border-right:0px;padding-left:0;padding-right:0;display:block;background-color:#000;color:#fff;font-family:'Lucida Console',Monaco,monospace;outline:0}</style></head><body><script src="https://cdn.jsdelivr.net/npm/eruda"></script>
|
||||
<script>eruda.init();</script><a href=http://emscripten.org><img id=emscripten_logo src=""></a><div class=spinner id=spinner></div><div class=emscripten id=status>Downloading...</div><span id=controls><span><input type=checkbox id=resize>Resize canvas</span> <span><input type=checkbox id=pointerLock checked>Lock/hide mouse pointer </span><span><input type=button onclick='Module.requestFullscreen(document.getElementById("pointerLock").checked,document.getElementById("resize").checked)'value=Fullscreen></span></span><div class=emscripten><progress hidden id=progress max=100 value=0></progress></div><div class=emscripten_border><canvas class=emscripten id=canvas oncontextmenu=event.preventDefault() tabindex=-1></canvas></div><textarea id=output rows=8></textarea><script>var statusElement=document.getElementById("status"),progressElement=document.getElementById("progress"),spinnerElement=document.getElementById("spinner"),canvasElement=document.getElementById("canvas"),outputElement=document.getElementById("output");outputElement&&(outputElement.value=""),canvasElement.addEventListener("webglcontextlost",(e=>{alert("WebGL context lost. You will need to reload the page."),e.preventDefault()}),!1);var Module={print(...e){if(console.log(...e),outputElement){var t=e.join(" ");outputElement.value+=t+"\n",outputElement.scrollTop=outputElement.scrollHeight}},canvas:canvasElement,setStatus(e){if(Module.setStatus.last||(Module.setStatus.last={time:Date.now(),text:""}),e!==Module.setStatus.last.text){var t=e.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/),n=Date.now();t&&n-Module.setStatus.last.time<30||(Module.setStatus.last.time=n,Module.setStatus.last.text=e,t?(e=t[1],progressElement.value=100*parseInt(t[2]),progressElement.max=100*parseInt(t[4]),progressElement.hidden=!1,spinnerElement.hidden=!1):(progressElement.value=null,progressElement.max=null,progressElement.hidden=!0,e||(spinnerElement.style.display="none")),statusElement.innerHTML=e)}},totalDependencies:0,monitorRunDependencies(e){this.totalDependencies=Math.max(this.totalDependencies,e),Module.setStatus(e?"Preparing... ("+(this.totalDependencies-e)+"/"+this.totalDependencies+")":"All downloads complete.")}};Module.setStatus("Downloading..."),window.onerror=e=>{Module.setStatus("Exception thrown, see JavaScript console"),spinnerElement.style.display="none",Module.setStatus=e=>{e&&console.error("[post-exception status] "+e)}}</script><script async src="space-game001.js" crossorigin="anonymous"></script></body></html>
|
||||
@@ -0,0 +1,216 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<title>Space Game</title>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0; padding: 0; width: 100%; height: 100%;
|
||||
overflow: hidden; background-color: #000;
|
||||
position: fixed;
|
||||
}
|
||||
#canvas {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100vw; height: 100vh;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#fs-button {
|
||||
position: absolute;
|
||||
top: 10px; right: 10px;
|
||||
padding: 10px;
|
||||
z-index: 10;
|
||||
background: rgba(255,255,255,0.3);
|
||||
color: white; border: 1px solid white;
|
||||
cursor: pointer;
|
||||
font-family: sans-serif;
|
||||
border-radius: 5px;
|
||||
}
|
||||
#status { color: white; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
||||
|
||||
/* Nick modal */
|
||||
#nickOverlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0,0,0,0.85);
|
||||
z-index: 9999;
|
||||
}
|
||||
#nickBox {
|
||||
background: #111;
|
||||
border: 1px solid #444;
|
||||
padding: 24px;
|
||||
width: 320px;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.6);
|
||||
text-align: center;
|
||||
}
|
||||
#nickBox h2 { margin: 0 0 12px 0; font-size: 18px; color: #eee; }
|
||||
#nickBox input[type="text"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid #333;
|
||||
background: #000;
|
||||
color: #fff;
|
||||
}
|
||||
#nickBox button {
|
||||
padding: 10px 16px;
|
||||
font-size: 16px;
|
||||
background: #2a9fd6;
|
||||
border: none;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
#nickSkip { margin-left: 8px; background: #666; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<button id="fs-button">Fullscreen</button>
|
||||
<div id="status">Downloading...</div>
|
||||
<canvas id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1"></canvas>
|
||||
<!--
|
||||
<script>
|
||||
var statusElement = document.getElementById("status");
|
||||
var canvas = document.getElementById("canvas");
|
||||
|
||||
var Module = {
|
||||
canvas: canvas,
|
||||
setStatus: function(text) {
|
||||
statusElement.innerHTML = text;
|
||||
statusElement.style.display = text ? 'block' : 'none';
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById('fs-button').addEventListener('click', function() {
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen().catch(e => {
|
||||
console.error(`Error attempting to enable full-screen mode: ${e.message}`);
|
||||
});
|
||||
} else {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("orientationchange", function() {
|
||||
setTimeout(() => {
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
}, 200);
|
||||
});
|
||||
|
||||
</script>
|
||||
<script async src="space-game001.js"></script>-->
|
||||
|
||||
<div id="nickOverlay" style="display:none;">
|
||||
<div id="nickBox">
|
||||
<h2>Enter your nickname</h2>
|
||||
<input id="nickInput" type="text" maxlength="32" placeholder="Player" />
|
||||
<div>
|
||||
<button id="nickSubmit">Start</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Utility: подготовить глобальный Module до загрузки Emscripten-скрипта
|
||||
function prepareModuleEnvironment() {
|
||||
window.Module = window.Module || {};
|
||||
var canvasEl = document.getElementById('canvas');
|
||||
// Устанавливаем canvas для Emscripten, чтобы createContext не падал
|
||||
window.Module.canvas = canvasEl;
|
||||
// Подготовим заглушку setStatus, если ещё нет
|
||||
window.Module.setStatus = window.Module.setStatus || function (text) {
|
||||
var statusElement = document.getElementById("status");
|
||||
statusElement.innerHTML = text;
|
||||
statusElement.style.display = text ? 'block' : 'none';
|
||||
};
|
||||
}
|
||||
|
||||
// Show overlay only if no nickname saved.
|
||||
function loadGameScript() {
|
||||
var s = document.createElement('script');
|
||||
s.src = 'space-game001.js';
|
||||
s.async = true;
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
|
||||
function showNickOverlay() {
|
||||
var overlay = document.getElementById('nickOverlay');
|
||||
overlay.style.display = 'flex';
|
||||
var input = document.getElementById('nickInput');
|
||||
input.focus();
|
||||
}
|
||||
|
||||
function hideNickOverlay() {
|
||||
var overlay = document.getElementById('nickOverlay');
|
||||
overlay.style.display = 'none';
|
||||
}
|
||||
|
||||
function saveNickAndStart(nick) {
|
||||
try {
|
||||
if (!nick || nick.trim() === '') nick = 'Player';
|
||||
localStorage.setItem('spacegame_nick', nick);
|
||||
} catch (e) {
|
||||
console.warn('localStorage not available', e);
|
||||
}
|
||||
hideNickOverlay();
|
||||
// перед загрузкой скрипта гарантируем, что Module.canvas задан
|
||||
prepareModuleEnvironment();
|
||||
loadGameScript();
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Готовим Module сразу — даже если откроется модалка, поле canvas будет доступно для скрипта (если он загружается позже)
|
||||
prepareModuleEnvironment();
|
||||
|
||||
var stored = null;
|
||||
try {
|
||||
stored = localStorage.getItem('spacegame_nick');
|
||||
} catch (e) {
|
||||
console.warn('localStorage not available', e);
|
||||
}
|
||||
|
||||
if (stored && stored.trim() !== '') {
|
||||
// Nick is present — start immediately
|
||||
loadGameScript();
|
||||
} else {
|
||||
// Show modal to request nickname before loading WASM
|
||||
showNickOverlay();
|
||||
var submit = document.getElementById('nickSubmit');
|
||||
var skip = document.getElementById('nickSkip');
|
||||
var input = document.getElementById('nickInput');
|
||||
|
||||
submit.addEventListener('click', function() {
|
||||
saveNickAndStart(input.value);
|
||||
});
|
||||
skip.addEventListener('click', function() {
|
||||
saveNickAndStart('Player');
|
||||
});
|
||||
|
||||
input.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
saveNickAndStart(input.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("orientationchange", function() {
|
||||
// Chrome на Android обновляет innerWidth/Height не мгновенно.
|
||||
// Ждем завершения анимации поворота.
|
||||
setTimeout(() => {
|
||||
// В Emscripten это вызовет ваш onWindowResized в C++
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
}, 200);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,180 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(space-game001 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ThirdParty.cmake)
|
||||
|
||||
# ===========================================
|
||||
# Основной проект space-game001
|
||||
# ===========================================
|
||||
add_executable(space-game001
|
||||
../src/main.cpp
|
||||
../src/Game.cpp
|
||||
../src/Game.h
|
||||
../src/Environment.cpp
|
||||
../src/Environment.h
|
||||
../src/render/Renderer.cpp
|
||||
../src/render/Renderer.h
|
||||
../src/render/ShaderManager.cpp
|
||||
../src/render/ShaderManager.h
|
||||
../src/render/TextureManager.cpp
|
||||
../src/render/TextureManager.h
|
||||
../src/TextModel.cpp
|
||||
../src/TextModel.h
|
||||
../src/AudioPlayerAsync.cpp
|
||||
../src/AudioPlayerAsync.h
|
||||
../src/BoneAnimatedModel.cpp
|
||||
../src/BoneAnimatedModel.h
|
||||
../src/render/OpenGlExtensions.cpp
|
||||
../src/render/OpenGlExtensions.h
|
||||
../src/utils/Utils.cpp
|
||||
../src/utils/Utils.h
|
||||
../src/SparkEmitter.cpp
|
||||
../src/SparkEmitter.h
|
||||
../src/planet/PlanetObject.cpp
|
||||
../src/planet/PlanetObject.h
|
||||
../src/planet/PlanetData.cpp
|
||||
../src/planet/PlanetData.h
|
||||
../src/utils/Perlin.cpp
|
||||
../src/utils/Perlin.h
|
||||
../src/utils/TaskManager.cpp
|
||||
../src/utils/TaskManager.h
|
||||
../src/planet/StoneObject.cpp
|
||||
../src/planet/StoneObject.h
|
||||
../src/render/FrameBuffer.cpp
|
||||
../src/render/FrameBuffer.h
|
||||
../src/UiManager.cpp
|
||||
../src/UiManager.h
|
||||
../src/Projectile.h
|
||||
../src/Projectile.cpp
|
||||
../src/network/NetworkInterface.h
|
||||
../src/network/LocalClient.h
|
||||
../src/network/LocalClient.cpp
|
||||
../src/network/ClientState.h
|
||||
../src/network/ClientState.cpp
|
||||
../src/network/WebSocketClient.h
|
||||
../src/network/WebSocketClient.cpp
|
||||
../src/network/WebSocketClientBase.h
|
||||
../src/network/WebSocketClientBase.cpp
|
||||
../src/network/WebSocketClientEmscripten.h
|
||||
../src/network/WebSocketClientEmscripten.cpp
|
||||
../src/render/TextRenderer.h
|
||||
../src/render/TextRenderer.cpp
|
||||
../src/MenuManager.h
|
||||
../src/MenuManager.cpp
|
||||
../src/Space.h
|
||||
../src/Space.cpp
|
||||
../src/GameConstants.h
|
||||
../src/GameConstants.cpp
|
||||
)
|
||||
|
||||
# Установка проекта по умолчанию для Visual Studio
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT space-game001)
|
||||
|
||||
# include-пути проекта
|
||||
target_include_directories(space-game001 PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../src"
|
||||
)
|
||||
|
||||
set_target_properties(space-game001 PROPERTIES
|
||||
OUTPUT_NAME "space-game001"
|
||||
)
|
||||
|
||||
# Определения препроцессора:
|
||||
# PNG_ENABLED – включает код PNG в TextureManager
|
||||
# SDL_MAIN_HANDLED – отключает переопределение main -> SDL_main
|
||||
target_compile_definitions(space-game001 PRIVATE
|
||||
WIN32_LEAN_AND_MEAN
|
||||
PNG_ENABLED
|
||||
SDL_MAIN_HANDLED
|
||||
NETWORK
|
||||
# SIMPLIFIED
|
||||
)
|
||||
|
||||
# Линкуем с SDL2main, если он вообще установлен
|
||||
target_link_libraries(space-game001 PRIVATE SDL2main_external_lib)
|
||||
|
||||
# Линкуем сторонние библиотеки
|
||||
target_link_libraries(space-game001 PRIVATE
|
||||
SDL2_external_lib
|
||||
libpng_external_lib
|
||||
zlib_external_lib
|
||||
libzip_external_lib
|
||||
freetype_external_lib
|
||||
SDL2_ttf_external_lib
|
||||
eigen_external_lib
|
||||
boost_external_lib
|
||||
)
|
||||
|
||||
# Линкуем OpenGL (Windows)
|
||||
if(WIN32)
|
||||
target_link_libraries(space-game001 PRIVATE opengl32)
|
||||
endif()
|
||||
|
||||
# ===========================================
|
||||
# Копирование SDL2d.dll и zlibd.dll рядом с exe
|
||||
# ===========================================
|
||||
if (WIN32)
|
||||
|
||||
# SDL2: в Debug - SDL2d.dll, в Release - SDL2.dll
|
||||
set(SDL2_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2_INSTALL_DIR}/bin/SDL2d.dll,${SDL2_INSTALL_DIR}/bin/SDL2.dll>")
|
||||
set(SDL2_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:space-game001>/SDL2d.dll,$<TARGET_FILE_DIR:space-game001>/SDL2.dll>")
|
||||
|
||||
|
||||
set(LIBZIP_DLL_SRC "$<IF:$<CONFIG:Debug>,${LIBZIP_BASE_DIR}-Debug/bin/zip.dll,${LIBZIP_BASE_DIR}-Release/bin/zip.dll>")
|
||||
|
||||
set(ZLIB_DLL_SRC "$<IF:$<CONFIG:Debug>,${ZLIB_INSTALL_DIR}/bin/zlibd.dll,${ZLIB_INSTALL_DIR}/bin/zlib.dll>")
|
||||
set(ZLIB_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:space-game001>/zlibd.dll,$<TARGET_FILE_DIR:space-game001>/zlib.dll>")
|
||||
|
||||
set(SDL2TTF_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2TTF_BASE_DIR}-Debug/bin/SDL2_ttfd.dll,${SDL2TTF_BASE_DIR}-Release/bin/SDL2_ttf.dll>")
|
||||
|
||||
|
||||
add_custom_command(TARGET space-game001 POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying DLLs to output folder..."
|
||||
|
||||
# Копируем SDL2 (целевое имя всегда SDL2.dll)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${SDL2_DLL_SRC}"
|
||||
"${SDL2_DLL_DST}"
|
||||
|
||||
# Копируем LIBZIP (целевое имя всегда zip.dll)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${LIBZIP_DLL_SRC}"
|
||||
"$<TARGET_FILE_DIR:space-game001>/zip.dll"
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${ZLIB_DLL_SRC}"
|
||||
"${ZLIB_DLL_DST}"
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${SDL2TTF_DLL_SRC}"
|
||||
"$<TARGET_FILE_DIR:space-game001>"
|
||||
)
|
||||
endif()
|
||||
|
||||
# ===========================================
|
||||
# Копирование ресурсов после сборки
|
||||
# ===========================================
|
||||
|
||||
# Какие папки с ресурсами нужно копировать
|
||||
set(RUNTIME_RESOURCE_DIRS
|
||||
"resources"
|
||||
)
|
||||
|
||||
# Копируем ресурсы и шейдеры в папку exe и в корень build/
|
||||
foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
|
||||
add_custom_command(TARGET space-game001 POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying ${resdir} to runtime folders..."
|
||||
# 1) туда, где лежит exe (build/Debug, build/Release и т.п.)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
||||
"$<TARGET_FILE_DIR:space-game001>/${resdir}"
|
||||
# 2) в корень build, если захочешь запускать из этой папки
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
||||
"${CMAKE_BINARY_DIR}/${resdir}"
|
||||
)
|
||||
endforeach()
|
||||
@@ -0,0 +1,29 @@
|
||||
===Vertices (Split by UV/Normal): 14
|
||||
V 0: Pos(1.0, 1.0, 1.0) Norm(0.57735, 0.57735, 0.57735) UV(0.5, 0.5)
|
||||
V 1: Pos(-1.0, 1.0, 1.0) Norm(-0.57735, 0.57735, 0.57735) UV(0.75, 0.5)
|
||||
V 2: Pos(-1.0, -1.0, 1.0) Norm(-0.57735, -0.57735, 0.57735) UV(0.75, 0.75)
|
||||
V 3: Pos(1.0, -1.0, 1.0) Norm(0.57735, -0.57735, 0.57735) UV(0.5, 0.75)
|
||||
V 4: Pos(1.0, -1.0, -1.0) Norm(0.57735, -0.57735, -0.57735) UV(0.25, 0.75)
|
||||
V 5: Pos(-1.0, -1.0, 1.0) Norm(-0.57735, -0.57735, 0.57735) UV(0.5, 1.0)
|
||||
V 6: Pos(-1.0, -1.0, -1.0) Norm(-0.57735, -0.57735, -0.57735) UV(0.25, 1.0)
|
||||
V 7: Pos(-1.0, -1.0, -1.0) Norm(-0.57735, -0.57735, -0.57735) UV(0.25, 0.0)
|
||||
V 8: Pos(-1.0, -1.0, 1.0) Norm(-0.57735, -0.57735, 0.57735) UV(0.5, 0.0)
|
||||
V 9: Pos(-1.0, 1.0, 1.0) Norm(-0.57735, 0.57735, 0.57735) UV(0.5, 0.25)
|
||||
V 10: Pos(-1.0, 1.0, -1.0) Norm(-0.57735, 0.57735, -0.57735) UV(0.25, 0.25)
|
||||
V 11: Pos(-1.0, 1.0, -1.0) Norm(-0.57735, 0.57735, -0.57735) UV(0.0, 0.5)
|
||||
V 12: Pos(1.0, 1.0, -1.0) Norm(0.57735, 0.57735, -0.57735) UV(0.25, 0.5)
|
||||
V 13: Pos(-1.0, -1.0, -1.0) Norm(-0.57735, -0.57735, -0.57735) UV(0.0, 0.75)
|
||||
|
||||
===Triangles (Indices): 12
|
||||
Tri: 0 1 2
|
||||
Tri: 0 2 3
|
||||
Tri: 4 3 5
|
||||
Tri: 4 5 6
|
||||
Tri: 7 8 9
|
||||
Tri: 7 9 10
|
||||
Tri: 11 12 4
|
||||
Tri: 11 4 13
|
||||
Tri: 12 0 3
|
||||
Tri: 12 3 4
|
||||
Tri: 10 9 0
|
||||
Tri: 10 0 12
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "FrameLayout",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": "match_parent",
|
||||
"height": "match_parent",
|
||||
"children": [
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "connecting",
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"width": 488,
|
||||
"height": 154,
|
||||
"horizontal_gravity": "center",
|
||||
"vertical_gravity": "center",
|
||||
"texture": "resources/connecting.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "FrameLayout",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": "match_parent",
|
||||
"height": "match_parent",
|
||||
"children": [
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "connectionFailed",
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"width": 488,
|
||||
"height": 308,
|
||||
"horizontal_gravity": "center",
|
||||
"vertical_gravity": "center",
|
||||
"texture": "resources/connection_failed.png"
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "connectionFailedReconnectButton",
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"x" : 0,
|
||||
"y" : -20,
|
||||
"horizontal_gravity": "center",
|
||||
"vertical_gravity": "center",
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Filledbuttons.png",
|
||||
"hover": "resources/game_over/Variant5.png",
|
||||
"pressed": "resources/game_over/Variant6.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "connectionFailedGoBack",
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"x" : 0,
|
||||
"y" : -86,
|
||||
"horizontal_gravity": "center",
|
||||
"vertical_gravity": "center",
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Secondarybutton.png",
|
||||
"hover": "resources/game_over/Secondarybutton.png",
|
||||
"pressed": "resources/game_over/Secondarybutton.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "FrameLayout",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": "match_parent",
|
||||
"height": "match_parent",
|
||||
"children": [
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "connectionLost",
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"width": 488,
|
||||
"height": 308,
|
||||
"horizontal_gravity": "center",
|
||||
"vertical_gravity": "center",
|
||||
"texture": "resources/connection_lost.png"
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "reconnectButton",
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"x" : 0,
|
||||
"y" : -20,
|
||||
"horizontal_gravity": "center",
|
||||
"vertical_gravity": "center",
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Filledbuttons.png",
|
||||
"hover": "resources/game_over/Variant5.png",
|
||||
"pressed": "resources/game_over/Variant6.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "exitServerButton",
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"x" : 0,
|
||||
"y" : -86,
|
||||
"horizontal_gravity": "center",
|
||||
"vertical_gravity": "center",
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Secondarybutton.png",
|
||||
"hover": "resources/game_over/Secondarybutton.png",
|
||||
"pressed": "resources/game_over/Secondarybutton.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"enabled": true,
|
||||
|
||||
"referenceResolution": [1280, 720],
|
||||
|
||||
"color": [1.0, 1.0, 1.0],
|
||||
"cl_crosshairalpha": 1.0,
|
||||
"cl_crosshairthickness": 2.0,
|
||||
|
||||
"centerGapPx": 10.0,
|
||||
|
||||
"top": {
|
||||
"lengthPx": 14.0,
|
||||
"angleDeg": 90.0
|
||||
},
|
||||
|
||||
"arms": [
|
||||
{ "lengthPx": 20.0, "angleDeg": 210.0 },
|
||||
{ "lengthPx": 20.0, "angleDeg": 330.0 }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"emissionPoints": [
|
||||
{ "position": [0.0, 0.0, 0.0] }
|
||||
],
|
||||
"texture": "resources/spark_white.png",
|
||||
"speedRange": [10.0, 30.0],
|
||||
"zSpeedRange": [-1.0, 1.0],
|
||||
"scaleRange": [5.0, 10.0],
|
||||
"lifeTimeRange": [200.0, 800.0],
|
||||
"emissionRate": 50.0,
|
||||
"maxParticles": 5,
|
||||
"particleSize": 2,
|
||||
"biasX": 0.1,
|
||||
"shaderProgramName": "default"
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "LinearLayout",
|
||||
"orientation": "vertical",
|
||||
"vertical_align": "center",
|
||||
"horizontal_align": "center",
|
||||
"spacing": 10,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": "match_parent",
|
||||
"height": "match_parent",
|
||||
"children": [
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "gameOverText",
|
||||
"width": 327,
|
||||
"height": 26,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/MissionFailed.png",
|
||||
"hover": "resources/game_over/MissionFailed.png",
|
||||
"pressed": "resources/game_over/MissionFailed.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "underlineBtn",
|
||||
"width": 168,
|
||||
"height": 44,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Container.png",
|
||||
"hover": "resources/game_over/Container.png",
|
||||
"pressed": "resources/game_over/Container.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "finalscore",
|
||||
"width": 87,
|
||||
"height": 9,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/FinalScore.png",
|
||||
"hover": "resources/game_over/FinalScore.png",
|
||||
"pressed": "resources/game_over/FinalScore.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TextView",
|
||||
"name": "scoreText",
|
||||
"width": 600,
|
||||
"height": 80,
|
||||
"text": "0",
|
||||
"fontSize": 36,
|
||||
"color": [
|
||||
0,
|
||||
217,
|
||||
255,
|
||||
1
|
||||
],
|
||||
"align": "center"
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "restartButton",
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Filledbuttons.png",
|
||||
"hover": "resources/game_over/Variant5.png",
|
||||
"pressed": "resources/game_over/Variant6.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "gameOverExitButton",
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Secondarybutton.png",
|
||||
"hover": "resources/game_over/Secondarybutton.png",
|
||||
"pressed": "resources/game_over/Secondarybutton.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "LinearLayout",
|
||||
"orientation": "vertical",
|
||||
"align": "center",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"background": {
|
||||
"color": [0, 0, 0, 0.7]
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "gameOverText",
|
||||
"x": 476.5,
|
||||
"y": 500,
|
||||
"width": 327,
|
||||
"height": 26,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/MissionFailed.png",
|
||||
"hover": "resources/game_over/MissionFailed.png",
|
||||
"pressed": "resources/game_over/MissionFailed.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "underlineBtn",
|
||||
"x": 556,
|
||||
"y": 465,
|
||||
"width": 168,
|
||||
"height": 44,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Container.png",
|
||||
"hover": "resources/game_over/Container.png",
|
||||
"pressed": "resources/game_over/Container.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "finalscore",
|
||||
"x": 596.5,
|
||||
"y": 436,
|
||||
"width": 87,
|
||||
"height": 9,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/FinalScore.png",
|
||||
"hover": "resources/game_over/FinalScore.png",
|
||||
"pressed": "resources/game_over/FinalScore.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TextView",
|
||||
"name": "scoreText",
|
||||
"x": 350,
|
||||
"y": 356,
|
||||
"width": 600,
|
||||
"height": 80,
|
||||
"text": "0",
|
||||
"fontSize": 36,
|
||||
"color": [0, 217, 255, 1],
|
||||
"align": "center"
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "restartButton",
|
||||
"x": 449,
|
||||
"y": 308,
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Filledbuttons.png",
|
||||
"hover": "resources/game_over/Filledbuttons.png",
|
||||
"pressed": "resources/game_over/Filledbuttons.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "gameOverExitButton",
|
||||
"x": 449,
|
||||
"y": 240,
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"textures": {
|
||||
"normal": "resources/game_over/Secondarybutton.png",
|
||||
"hover": "resources/game_over/Secondarybutton.png",
|
||||
"pressed": "resources/game_over/Secondarybutton.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "LinearLayout",
|
||||
"orientation": "vertical",
|
||||
"vertical_align": "center",
|
||||
"horizontal_align": "center",
|
||||
"spacing": 10,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": "match_parent",
|
||||
"height": "match_parent",
|
||||
"children": [
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "titleBtn",
|
||||
"width": 434,
|
||||
"height": 35,
|
||||
"texture": "resources/main_menu/title.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "underlineBtn",
|
||||
"width": 168,
|
||||
"height": 44,
|
||||
"texture": "resources/main_menu/line.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "subtitleBtn",
|
||||
"width": 144,
|
||||
"height": 11,
|
||||
"texture": "resources/main_menu/subtitle.png"
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "singleButton",
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"textures": {
|
||||
"normal": "resources/main_menu/single.png",
|
||||
"hover": "resources/main_menu/Variant5.png",
|
||||
"pressed": "resources/main_menu/Variant6.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "multiplayerButton",
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"textures": {
|
||||
"normal": "resources/main_menu/multi.png",
|
||||
"hover": "resources/main_menu/Variant7.png",
|
||||
"pressed": "resources/main_menu/Variant8.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "versionLabel",
|
||||
"width": 81,
|
||||
"height": 9,
|
||||
"texture": "resources/main_menu/version.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "LinearLayout",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"children": [
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "langButton",
|
||||
"x": 1100,
|
||||
"y": 580,
|
||||
"width": 142,
|
||||
"height": 96,
|
||||
"textures": {
|
||||
"normal": "resources/main_menu/lang.png",
|
||||
"hover": "resources/main_menu/lang.png",
|
||||
"pressed": "resources/main_menu/lang.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "titleBtn",
|
||||
"x": 512,
|
||||
"y": 500,
|
||||
"width": 254,
|
||||
"height": 35,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/title.png",
|
||||
"hover": "resources/multiplayer_menu/title.png",
|
||||
"pressed": "resources/multiplayer_menu/title.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "subtitle",
|
||||
"x": 596.5,
|
||||
"y": 470,
|
||||
"width": 87,
|
||||
"height": 11,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/JoinServer.png",
|
||||
"hover": "resources/multiplayer_menu/JoinServer.png",
|
||||
"pressed": "resources/multiplayer_menu/JoinServer.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "subtitleBtn",
|
||||
"x": 450,
|
||||
"y": 445,
|
||||
"width": 94,
|
||||
"height": 9,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/ServerName.png",
|
||||
"hover": "resources/multiplayer_menu/ServerName.png",
|
||||
"pressed": "resources/multiplayer_menu/ServerName.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TextField",
|
||||
"name": "serverInputField",
|
||||
"x": 449,
|
||||
"y": 390,
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"placeholder": "Enter server name or IP",
|
||||
"fontPath": "resources/fonts/DroidSans.ttf",
|
||||
"fontSize": 16,
|
||||
"maxLength": 256,
|
||||
"color": [122, 156, 198, 1],
|
||||
"placeholderColor": [122, 156, 198, 1],
|
||||
"backgroundColor": [15, 29, 51, 1],
|
||||
"borderColor": [15, 29, 51, 1]
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "connectButton",
|
||||
"x": 449,
|
||||
"y": 350,
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/Filledbuttons.png",
|
||||
"hover": "resources/multiplayer_menu/Filledbuttons.png",
|
||||
"pressed": "resources/multiplayer_menu/Filledbuttons.png"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "backButton",
|
||||
"x": 449,
|
||||
"y": 280,
|
||||
"width": 382,
|
||||
"height": 56,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/Backbutton.png",
|
||||
"hover": "resources/multiplayer_menu/Backbutton.png",
|
||||
"pressed": "resources/multiplayer_menu/Backbutton.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "AvailableServers",
|
||||
"x": 450,
|
||||
"y": 240,
|
||||
"width": 139,
|
||||
"height": 9,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/AvailableServers.png",
|
||||
"hover": "resources/multiplayer_menu/AvailableServers.png",
|
||||
"pressed": "resources/multiplayer_menu/AvailableServers.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "SerButton",
|
||||
"x": 436.5,
|
||||
"y": 170,
|
||||
"width": 407,
|
||||
"height": 62,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/Button.png",
|
||||
"hover": "resources/multiplayer_menu/Button.png",
|
||||
"pressed": "resources/multiplayer_menu/Button.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "SerButton2",
|
||||
"x": 436.5,
|
||||
"y": 88,
|
||||
"width": 407,
|
||||
"height": 62,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/Button2.png",
|
||||
"hover": "resources/multiplayer_menu/Button2.png",
|
||||
"pressed": "resources/multiplayer_menu/Button2.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "SerButton3",
|
||||
"x": 436.5,
|
||||
"y": 6,
|
||||
"width": 407,
|
||||
"height": 62,
|
||||
"textures": {
|
||||
"normal": "resources/multiplayer_menu/Button3.png",
|
||||
"hover": "resources/multiplayer_menu/Button3.png",
|
||||
"pressed": "resources/multiplayer_menu/Button3.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||