mirror of
https://github.com/MapMakersAndProgrammers/alternativa3d-archive.git
synced 2025-10-30 08:55:21 -07:00
more versions added
This commit is contained in:
39
Alternativa3D7/7.2.1/.actionScriptProperties
Normal file
39
Alternativa3D7/7.2.1/.actionScriptProperties
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<actionScriptProperties mainApplicationPath="Engine3DLibrary.as" version="3">
|
||||
<compiler additionalCompilerArguments="" copyDependentFiles="false" enableModuleDebug="false" flexSDK="Flex 4.0" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="false" htmlPlayerVersion="10.0.0" htmlPlayerVersionCheck="true" outputFolderPath="bin" sourceFolderPath="src" strict="true" useApolloConfig="false" verifyDigests="true" warn="true">
|
||||
<compilerSourcePath/>
|
||||
<libraryPath defaultLinkType="1">
|
||||
<libraryPathEntry kind="4" path="">
|
||||
<excludedEntries>
|
||||
<libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/text_model.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/player/{targetPlayerMajorVersion}" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/text_importExport.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flex4.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/textLayout_conversion.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="2" path="${PROJECT_FRAMEWORKS}/libs/utilities.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/text_edit.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/textLayout_textField.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/textLayout_edit.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/textLayout_core.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flex.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework_textLayout.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
|
||||
</excludedEntries>
|
||||
</libraryPathEntry>
|
||||
</libraryPath>
|
||||
<sourceAttachmentPath/>
|
||||
</compiler>
|
||||
<applications>
|
||||
<application path="Engine3DLibrary.as"/>
|
||||
</applications>
|
||||
<modules/>
|
||||
<buildCSSFiles/>
|
||||
</actionScriptProperties>
|
||||
57
Alternativa3D7/7.2.1/.flexLibProperties
Normal file
57
Alternativa3D7/7.2.1/.flexLibProperties
Normal file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<flexLibProperties version="1">
|
||||
<includeClasses>
|
||||
<classEntry path="alternativa.Alternativa3D"/>
|
||||
<classEntry path="alternativa.engine3d.core.MipMap"/>
|
||||
<classEntry path="alternativa.engine3d.core.Object3DContainer"/>
|
||||
<classEntry path="alternativa.engine3d.controllers.SimpleObjectController"/>
|
||||
<classEntry path="alternativa.engine3d.objects.WireQuad"/>
|
||||
<classEntry path="alternativa.engine3d.core.Canvas"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.BatchTextureLoader"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.Parser3DS"/>
|
||||
<classEntry path="alternativa.engine3d.core.BoundBox"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.TextureLoader"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Sprite3D"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.Loader3DS"/>
|
||||
<classEntry path="alternativa.engine3d.core.Debug"/>
|
||||
<classEntry path="alternativa.engine3d.containers.DirectionContainer"/>
|
||||
<classEntry path="alternativa.engine3d.containers.SkyBox"/>
|
||||
<classEntry path="alternativa.engine3d.primitives.Box"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.events.LoaderProgressEvent"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Reference"/>
|
||||
<classEntry path="alternativa.engine3d.core.Object3D"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.events.BatchTextureLoaderErrorEvent"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.TextureFilesData"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Axes"/>
|
||||
<classEntry path="alternativa.engine3d.containers.SplitContainer"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.events.LoaderEvent"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.MaterialParams"/>
|
||||
<classEntry path="alternativa.engine3d.core.Geometry"/>
|
||||
<classEntry path="alternativa.engine3d.core.Sorting"/>
|
||||
<classEntry path="alternativa.engine3d.core.Clipping"/>
|
||||
<classEntry path="alternativa.engine3d.containers.BSPTree"/>
|
||||
<classEntry path="alternativa.engine3d.objects.WireBoundBox"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Occluder"/>
|
||||
<classEntry path="alternativa.engine3d.containers.AverageZContainer"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.TextureInfo"/>
|
||||
<classEntry path="alternativa.engine3d.objects.LOD"/>
|
||||
<classEntry path="alternativa.engine3d.core.Node"/>
|
||||
<classEntry path="alternativa.engine3d.containers.KDTree"/>
|
||||
<classEntry path="alternativa.engine3d.core.MipMapping"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.Loader3DSByteArray"/>
|
||||
<classEntry path="alternativa.engine3d.core.BackfaceCulling"/>
|
||||
<classEntry path="alternativa.engine3d.containers.ConflictContainer"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Bone"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Mesh"/>
|
||||
<classEntry path="alternativa.engine3d.objects.SkeletalMesh"/>
|
||||
<classEntry path="alternativa.engine3d.primitives.GeoSphere"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.Parsed3DSData"/>
|
||||
<classEntry path="alternativa.engine3d.objects.AnimSprite"/>
|
||||
<classEntry path="alternativa.engine3d.alternativa3d"/>
|
||||
<classEntry path="alternativa.engine3d.core.Camera3D"/>
|
||||
<classEntry path="alternativa.engine3d.primitives.Plane"/>
|
||||
<classEntry path="alternativa.engine3d.core.Fragment"/>
|
||||
</includeClasses>
|
||||
<includeResources/>
|
||||
<namespaceManifests/>
|
||||
</flexLibProperties>
|
||||
19
Alternativa3D7/7.2.1/.project
Normal file
19
Alternativa3D7/7.2.1/.project
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Alternativa3D</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.adobe.flexbuilder.project.flexbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.maven.ide.eclipse.maven2Nature</nature>
|
||||
<nature>com.adobe.flexbuilder.project.flexlibnature</nature>
|
||||
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
17
Alternativa3D7/7.2.1/.settings/.svn/all-wcprops
Normal file
17
Alternativa3D7/7.2.1/.settings/.svn/all-wcprops
Normal file
@@ -0,0 +1,17 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 82
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/.settings
|
||||
END
|
||||
org.eclipse.core.resources.prefs
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 115
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/.settings/org.eclipse.core.resources.prefs
|
||||
END
|
||||
org.eclipse.ltk.core.refactoring.prefs
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 121
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/.settings/org.eclipse.ltk.core.refactoring.prefs
|
||||
END
|
||||
52
Alternativa3D7/7.2.1/.settings/.svn/entries
Normal file
52
Alternativa3D7/7.2.1/.settings/.svn/entries
Normal file
@@ -0,0 +1,52 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/.settings
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2008-08-25T13:44:47.077292Z
|
||||
176
|
||||
int
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
org.eclipse.core.resources.prefs
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
63644c8a8f9fe441148cb750eb3dc2f3
|
||||
2008-08-25T13:44:47.077292Z
|
||||
176
|
||||
int
|
||||
|
||||
org.eclipse.ltk.core.refactoring.prefs
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
85719ffc1d818e46b40e2f90aad31e8c
|
||||
2008-08-25T13:44:47.077292Z
|
||||
176
|
||||
int
|
||||
|
||||
1
Alternativa3D7/7.2.1/.settings/.svn/format
Normal file
1
Alternativa3D7/7.2.1/.settings/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,3 @@
|
||||
#Thu Feb 14 09:12:30 YEKT 2008
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@@ -0,0 +1,3 @@
|
||||
#Tue Nov 13 17:53:36 YEKT 2007
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
||||
@@ -0,0 +1,3 @@
|
||||
#Thu Feb 14 09:12:30 YEKT 2008
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@@ -0,0 +1,3 @@
|
||||
#Tue Nov 13 17:53:36 YEKT 2007
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
||||
29
Alternativa3D7/7.2.1/.svn/all-wcprops
Normal file
29
Alternativa3D7/7.2.1/.svn/all-wcprops
Normal file
@@ -0,0 +1,29 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 72
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1
|
||||
END
|
||||
.flexLibProperties
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 91
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/.flexLibProperties
|
||||
END
|
||||
.project
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 81
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/.project
|
||||
END
|
||||
pom.xml
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 80
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/pom.xml
|
||||
END
|
||||
.actionScriptProperties
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 96
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/.actionScriptProperties
|
||||
END
|
||||
16
Alternativa3D7/7.2.1/.svn/dir-prop-base
Normal file
16
Alternativa3D7/7.2.1/.svn/dir-prop-base
Normal file
@@ -0,0 +1,16 @@
|
||||
K 10
|
||||
svn:ignore
|
||||
V 46
|
||||
help
|
||||
Alternativa3D API Documentation.launch
|
||||
|
||||
K 13
|
||||
svn:mergeinfo
|
||||
V 492
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0:5796-7235
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0.2:17447,17456-18883
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4:304-463
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.MouseEvents:1556-1900
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.SingularMapping:2042-2060
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk:304-494,1465-2616,2621-2676,2680-2696,2710-2743,2778-2783
|
||||
END
|
||||
85
Alternativa3D7/7.2.1/.svn/entries
Normal file
85
Alternativa3D7/7.2.1/.svn/entries
Normal file
@@ -0,0 +1,85 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-10-21T13:59:37.521903Z
|
||||
22370
|
||||
int
|
||||
has-props
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
META-INF
|
||||
dir
|
||||
|
||||
.flexLibProperties
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
cfef2cb5a752a4d5f0fd1e5699ca3577
|
||||
2009-10-19T11:39:18.186364Z
|
||||
22296
|
||||
int
|
||||
|
||||
.project
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
b667ec054eff8af05ac9a51ee210a30a
|
||||
2009-08-28T03:11:42.975760Z
|
||||
18921
|
||||
wolf
|
||||
|
||||
src
|
||||
dir
|
||||
|
||||
pom.xml
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
e08e402e98c3636a8bc811dd207ba917
|
||||
2009-09-24T14:32:07.662209Z
|
||||
20457
|
||||
mike
|
||||
|
||||
.actionScriptProperties
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
c0bc1cfcf7e01fc8676152a140cba730
|
||||
2009-10-15T15:24:10.867373Z
|
||||
22063
|
||||
int
|
||||
|
||||
.settings
|
||||
dir
|
||||
|
||||
1
Alternativa3D7/7.2.1/.svn/format
Normal file
1
Alternativa3D7/7.2.1/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<actionScriptProperties mainApplicationPath="Engine3DLibrary.as" version="3">
|
||||
<compiler additionalCompilerArguments="" copyDependentFiles="false" enableModuleDebug="false" flexSDK="Flex 4.0" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="false" htmlPlayerVersion="10.0.0" htmlPlayerVersionCheck="true" outputFolderPath="bin" sourceFolderPath="src" strict="true" useApolloConfig="false" verifyDigests="true" warn="true">
|
||||
<compilerSourcePath/>
|
||||
<libraryPath defaultLinkType="1">
|
||||
<libraryPathEntry kind="4" path="">
|
||||
<excludedEntries>
|
||||
<libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/text_model.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/player/{targetPlayerMajorVersion}" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/text_importExport.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flex4.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/textLayout_conversion.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="2" path="${PROJECT_FRAMEWORKS}/libs/utilities.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/text_edit.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/textLayout_textField.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/textLayout_edit.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/textLayout_core.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flex.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework_textLayout.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
|
||||
</excludedEntries>
|
||||
</libraryPathEntry>
|
||||
</libraryPath>
|
||||
<sourceAttachmentPath/>
|
||||
</compiler>
|
||||
<applications>
|
||||
<application path="Engine3DLibrary.as"/>
|
||||
</applications>
|
||||
<modules/>
|
||||
<buildCSSFiles/>
|
||||
</actionScriptProperties>
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<flexLibProperties version="1">
|
||||
<includeClasses>
|
||||
<classEntry path="alternativa.Alternativa3D"/>
|
||||
<classEntry path="alternativa.engine3d.core.MipMap"/>
|
||||
<classEntry path="alternativa.engine3d.core.Object3DContainer"/>
|
||||
<classEntry path="alternativa.engine3d.controllers.SimpleObjectController"/>
|
||||
<classEntry path="alternativa.engine3d.objects.WireQuad"/>
|
||||
<classEntry path="alternativa.engine3d.core.Canvas"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.BatchTextureLoader"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.Parser3DS"/>
|
||||
<classEntry path="alternativa.engine3d.core.BoundBox"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.TextureLoader"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Sprite3D"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.Loader3DS"/>
|
||||
<classEntry path="alternativa.engine3d.core.Debug"/>
|
||||
<classEntry path="alternativa.engine3d.containers.DirectionContainer"/>
|
||||
<classEntry path="alternativa.engine3d.containers.SkyBox"/>
|
||||
<classEntry path="alternativa.engine3d.primitives.Box"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.events.LoaderProgressEvent"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Reference"/>
|
||||
<classEntry path="alternativa.engine3d.core.Object3D"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.events.BatchTextureLoaderErrorEvent"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.TextureFilesData"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Axes"/>
|
||||
<classEntry path="alternativa.engine3d.containers.SplitContainer"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.events.LoaderEvent"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.MaterialParams"/>
|
||||
<classEntry path="alternativa.engine3d.core.Geometry"/>
|
||||
<classEntry path="alternativa.engine3d.core.Sorting"/>
|
||||
<classEntry path="alternativa.engine3d.core.Clipping"/>
|
||||
<classEntry path="alternativa.engine3d.containers.BSPTree"/>
|
||||
<classEntry path="alternativa.engine3d.objects.WireBoundBox"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Occluder"/>
|
||||
<classEntry path="alternativa.engine3d.containers.AverageZContainer"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.TextureInfo"/>
|
||||
<classEntry path="alternativa.engine3d.objects.LOD"/>
|
||||
<classEntry path="alternativa.engine3d.core.Node"/>
|
||||
<classEntry path="alternativa.engine3d.containers.KDTree"/>
|
||||
<classEntry path="alternativa.engine3d.core.MipMapping"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.Loader3DSByteArray"/>
|
||||
<classEntry path="alternativa.engine3d.core.BackfaceCulling"/>
|
||||
<classEntry path="alternativa.engine3d.containers.ConflictContainer"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Bone"/>
|
||||
<classEntry path="alternativa.engine3d.objects.Mesh"/>
|
||||
<classEntry path="alternativa.engine3d.objects.SkeletalMesh"/>
|
||||
<classEntry path="alternativa.engine3d.primitives.GeoSphere"/>
|
||||
<classEntry path="alternativa.engine3d.loaders.Parsed3DSData"/>
|
||||
<classEntry path="alternativa.engine3d.objects.AnimSprite"/>
|
||||
<classEntry path="alternativa.engine3d.alternativa3d"/>
|
||||
<classEntry path="alternativa.engine3d.core.Camera3D"/>
|
||||
<classEntry path="alternativa.engine3d.primitives.Plane"/>
|
||||
<classEntry path="alternativa.engine3d.core.Fragment"/>
|
||||
</includeClasses>
|
||||
<includeResources/>
|
||||
<namespaceManifests/>
|
||||
</flexLibProperties>
|
||||
19
Alternativa3D7/7.2.1/.svn/text-base/.project.svn-base
Normal file
19
Alternativa3D7/7.2.1/.svn/text-base/.project.svn-base
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Alternativa3D</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.adobe.flexbuilder.project.flexbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.maven.ide.eclipse.maven2Nature</nature>
|
||||
<nature>com.adobe.flexbuilder.project.flexlibnature</nature>
|
||||
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
15
Alternativa3D7/7.2.1/.svn/text-base/pom.xml.svn-base
Normal file
15
Alternativa3D7/7.2.1/.svn/text-base/pom.xml.svn-base
Normal file
@@ -0,0 +1,15 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>platform.clients.fp10.libraries</groupId>
|
||||
<artifactId>Alternativa3D</artifactId>
|
||||
<packaging>swc</packaging>
|
||||
<version>7.0.6.0-SNAPSHOT</version>
|
||||
<parent>
|
||||
<groupId>platform.tools.maven</groupId>
|
||||
<artifactId>FlashBasePom</artifactId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
<scm>
|
||||
<connection>scm:svn:http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/branches/7.0.TanksTest</connection>
|
||||
</scm>
|
||||
</project>
|
||||
11
Alternativa3D7/7.2.1/META-INF/.svn/all-wcprops
Normal file
11
Alternativa3D7/7.2.1/META-INF/.svn/all-wcprops
Normal file
@@ -0,0 +1,11 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 81
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/META-INF
|
||||
END
|
||||
MANIFEST.MF
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 93
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/META-INF/MANIFEST.MF
|
||||
END
|
||||
40
Alternativa3D7/7.2.1/META-INF/.svn/entries
Normal file
40
Alternativa3D7/7.2.1/META-INF/.svn/entries
Normal file
@@ -0,0 +1,40 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/META-INF
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-03-04T09:09:17.957056Z
|
||||
8649
|
||||
mike
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
MANIFEST.MF
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
0069b2b9a3b474d1d94113e9d6731290
|
||||
2009-03-04T09:09:17.957056Z
|
||||
8649
|
||||
mike
|
||||
|
||||
1
Alternativa3D7/7.2.1/META-INF/.svn/format
Normal file
1
Alternativa3D7/7.2.1/META-INF/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1 @@
|
||||
Bundle-Name: platform.clients.fp10.libraries.Alternativa3D
|
||||
1
Alternativa3D7/7.2.1/META-INF/MANIFEST.MF
Normal file
1
Alternativa3D7/7.2.1/META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1 @@
|
||||
Bundle-Name: platform.clients.fp10.libraries.Alternativa3D
|
||||
15
Alternativa3D7/7.2.1/pom.xml
Normal file
15
Alternativa3D7/7.2.1/pom.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>platform.clients.fp10.libraries</groupId>
|
||||
<artifactId>Alternativa3D</artifactId>
|
||||
<packaging>swc</packaging>
|
||||
<version>7.0.6.0-SNAPSHOT</version>
|
||||
<parent>
|
||||
<groupId>platform.tools.maven</groupId>
|
||||
<artifactId>FlashBasePom</artifactId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
<scm>
|
||||
<connection>scm:svn:http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/branches/7.0.TanksTest</connection>
|
||||
</scm>
|
||||
</project>
|
||||
11
Alternativa3D7/7.2.1/src/.svn/all-wcprops
Normal file
11
Alternativa3D7/7.2.1/src/.svn/all-wcprops
Normal file
@@ -0,0 +1,11 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 76
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src
|
||||
END
|
||||
manifest.xml
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 89
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/manifest.xml
|
||||
END
|
||||
43
Alternativa3D7/7.2.1/src/.svn/entries
Normal file
43
Alternativa3D7/7.2.1/src/.svn/entries
Normal file
@@ -0,0 +1,43 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-10-20T15:36:49.086084Z
|
||||
22341
|
||||
int
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
manifest.xml
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
2e2b1aa9d128d192e5f544209f610433
|
||||
2009-06-25T13:27:32.420515Z
|
||||
15144
|
||||
int
|
||||
|
||||
alternativa
|
||||
dir
|
||||
|
||||
1
Alternativa3D7/7.2.1/src/.svn/format
Normal file
1
Alternativa3D7/7.2.1/src/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<componentPackage>
|
||||
<component id="Alternativa3D" class="alternativa.Alternativa3D"/>
|
||||
</componentPackage>
|
||||
11
Alternativa3D7/7.2.1/src/alternativa/.svn/all-wcprops
Normal file
11
Alternativa3D7/7.2.1/src/alternativa/.svn/all-wcprops
Normal file
@@ -0,0 +1,11 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 88
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa
|
||||
END
|
||||
Alternativa3D.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 105
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/Alternativa3D.as
|
||||
END
|
||||
11
Alternativa3D7/7.2.1/src/alternativa/.svn/dir-prop-base
Normal file
11
Alternativa3D7/7.2.1/src/alternativa/.svn/dir-prop-base
Normal file
@@ -0,0 +1,11 @@
|
||||
K 13
|
||||
svn:mergeinfo
|
||||
V 648
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0/src/alternativa:5796-7235
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0.2/src/alternativa:17447,17456-18883
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4/alternativa:304-463
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.MouseEvents/src/alternativa:1556-1900
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.SingularMapping/src/alternativa:2042-2060
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk/alternativa:304-494
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk/src/alternativa:1465-2616,2621-2676,2680-2696,2710-2743,2778-2783
|
||||
END
|
||||
43
Alternativa3D7/7.2.1/src/alternativa/.svn/entries
Normal file
43
Alternativa3D7/7.2.1/src/alternativa/.svn/entries
Normal file
@@ -0,0 +1,43 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-10-20T15:36:49.086084Z
|
||||
22341
|
||||
int
|
||||
has-props
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
Alternativa3D.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
1500acb71dc17d3fd581f2398575f25e
|
||||
2009-06-25T13:27:32.420515Z
|
||||
15144
|
||||
int
|
||||
|
||||
engine3d
|
||||
dir
|
||||
|
||||
1
Alternativa3D7/7.2.1/src/alternativa/.svn/format
Normal file
1
Alternativa3D7/7.2.1/src/alternativa/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,14 @@
|
||||
package alternativa {
|
||||
|
||||
/**
|
||||
* Класс содержит информацию о версии библиотеки.
|
||||
* Также используется для интеграции библиотеки в среду разработки Adobe Flash.
|
||||
*/
|
||||
public class Alternativa3D {
|
||||
|
||||
/**
|
||||
* Версия библиотеки в формате: поколение.feature-версия.fix-версия
|
||||
*/
|
||||
public static const version:String = "7.0.0";
|
||||
}
|
||||
}
|
||||
14
Alternativa3D7/7.2.1/src/alternativa/Alternativa3D.as
Normal file
14
Alternativa3D7/7.2.1/src/alternativa/Alternativa3D.as
Normal file
@@ -0,0 +1,14 @@
|
||||
package alternativa {
|
||||
|
||||
/**
|
||||
* Класс содержит информацию о версии библиотеки.
|
||||
* Также используется для интеграции библиотеки в среду разработки Adobe Flash.
|
||||
*/
|
||||
public class Alternativa3D {
|
||||
|
||||
/**
|
||||
* Версия библиотеки в формате: поколение.feature-версия.fix-версия
|
||||
*/
|
||||
public static const version:String = "7.0.0";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 97
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d
|
||||
END
|
||||
alternativa3d.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 114
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/alternativa3d.as
|
||||
END
|
||||
58
Alternativa3D7/7.2.1/src/alternativa/engine3d/.svn/entries
Normal file
58
Alternativa3D7/7.2.1/src/alternativa/engine3d/.svn/entries
Normal file
@@ -0,0 +1,58 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-10-20T15:36:49.086084Z
|
||||
22341
|
||||
int
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
alternativa3d.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:17.000000Z
|
||||
64183f832985e252cc4bc98977484bc9
|
||||
2009-02-11T11:56:39.925226Z
|
||||
7238
|
||||
wolf
|
||||
|
||||
containers
|
||||
dir
|
||||
|
||||
controllers
|
||||
dir
|
||||
|
||||
core
|
||||
dir
|
||||
|
||||
loaders
|
||||
dir
|
||||
|
||||
objects
|
||||
dir
|
||||
|
||||
primitives
|
||||
dir
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,3 @@
|
||||
package alternativa.engine3d {
|
||||
public namespace alternativa3d = "http://alternativaplatform.com/en/alternativa3d";
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package alternativa.engine3d {
|
||||
public namespace alternativa3d = "http://alternativaplatform.com/en/alternativa3d";
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 108
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers
|
||||
END
|
||||
KDTree.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 118
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers/KDTree.as
|
||||
END
|
||||
SplitContainer.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 126
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers/SplitContainer.as
|
||||
END
|
||||
SkyBox.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 118
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers/SkyBox.as
|
||||
END
|
||||
DirectionContainer.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 130
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers/DirectionContainer.as
|
||||
END
|
||||
BSPTree.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 119
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers/BSPTree.as
|
||||
END
|
||||
ConflictContainer.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 129
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers/ConflictContainer.as
|
||||
END
|
||||
AverageZContainer.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 129
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers/AverageZContainer.as
|
||||
END
|
||||
@@ -0,0 +1,113 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/containers
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-10-20T15:36:49.086084Z
|
||||
22341
|
||||
int
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
KDTree.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
7b8bf5f7391901c409b1efd39b1b8495
|
||||
2009-10-19T11:39:18.186364Z
|
||||
22296
|
||||
int
|
||||
|
||||
SplitContainer.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
64e1b96019ddcb6251c485edf7743afc
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
|
||||
SkyBox.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
d5637774608e1a7c6c303f83e55afeb9
|
||||
2009-10-18T15:26:30.880098Z
|
||||
22239
|
||||
int
|
||||
|
||||
DirectionContainer.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
9e2cc7ec294ef915a6c85fa2564e6214
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
|
||||
BSPTree.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
b1334a64f09aa52c172b20df7fa66f5a
|
||||
2009-10-19T11:39:18.186364Z
|
||||
22296
|
||||
int
|
||||
|
||||
ConflictContainer.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
795ebff90c493f5d194a202a73f0fa0e
|
||||
2009-10-20T15:36:49.086084Z
|
||||
22341
|
||||
int
|
||||
has-props
|
||||
|
||||
AverageZContainer.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
2869f9a450deef9ccb26b0bd328dabd7
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,5 @@
|
||||
K 13
|
||||
svn:mergeinfo
|
||||
V 0
|
||||
|
||||
END
|
||||
@@ -0,0 +1,77 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Canvas;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
import alternativa.engine3d.core.Object3DContainer;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Контейнер, дочерние объекты которого отрисовываются по удалённости от камеры
|
||||
*/
|
||||
public class AverageZContainer extends Object3DContainer {
|
||||
|
||||
static private const averageZ:Vector.<Number> = new Vector.<Number>();
|
||||
static private const center:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
static private const cameraCenter:Vector.<Number> = new Vector.<Number>(3, true);
|
||||
static private const sortingStack:Vector.<int> = new Vector.<int>();
|
||||
|
||||
override protected function drawVisibleChildren(camera:Camera3D, object:Object3D, canvas:Canvas):void {
|
||||
var i:int;
|
||||
var j:int;
|
||||
var l:int = 0;
|
||||
var r:int = numVisibleChildren - 1;
|
||||
var child:Object3D;
|
||||
var sortingStackIndex:int;
|
||||
var sortingLeft:Number;
|
||||
var sortingMedian:Number;
|
||||
var sortingRight:Number;
|
||||
var sortingChild:Object3D;
|
||||
// Сортировка
|
||||
for (i = 0; i < numVisibleChildren; i++) {
|
||||
child = visibleChildren[i];
|
||||
child.cameraMatrix.transformVectors(center, cameraCenter);
|
||||
averageZ[i] = cameraCenter[0]*cameraCenter[0] + cameraCenter[1]*cameraCenter[1] + cameraCenter[2]*cameraCenter[2];
|
||||
}
|
||||
sortingStack[0] = l;
|
||||
sortingStack[1] = r;
|
||||
sortingStackIndex = 2;
|
||||
while (sortingStackIndex > 0) {
|
||||
j = r = sortingStack[--sortingStackIndex];
|
||||
i = l = sortingStack[--sortingStackIndex];
|
||||
sortingMedian = averageZ[(r + l) >> 1];
|
||||
do {
|
||||
while ((sortingLeft = averageZ[i]) > sortingMedian) i++;
|
||||
while ((sortingRight = averageZ[j]) < sortingMedian) j--;
|
||||
if (i <= j) {
|
||||
sortingChild = visibleChildren[i];
|
||||
visibleChildren[i] = visibleChildren[j];
|
||||
visibleChildren[j] = sortingChild;
|
||||
averageZ[i++] = sortingRight;
|
||||
averageZ[j--] = sortingLeft;
|
||||
}
|
||||
} while (i <= j);
|
||||
if (l < j) {
|
||||
sortingStack[sortingStackIndex++] = l;
|
||||
sortingStack[sortingStackIndex++] = j;
|
||||
}
|
||||
if (i < r) {
|
||||
sortingStack[sortingStackIndex++] = i;
|
||||
sortingStack[sortingStackIndex++] = r;
|
||||
}
|
||||
}
|
||||
// Отрисовка
|
||||
for (i = numVisibleChildren - 1; i >= 0; i--) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class BSPTree extends ConflictContainer {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Canvas;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
import alternativa.engine3d.core.Object3DContainer;
|
||||
|
||||
import flash.geom.Vector3D;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class DirectionContainer extends Object3DContainer {
|
||||
|
||||
public var direction:Vector3D = new Vector3D(0, 0, -1);
|
||||
|
||||
override protected function drawVisibleChildren(camera:Camera3D, object:Object3D, canvas:Canvas):void {
|
||||
var i:int;
|
||||
var child:Object3D;
|
||||
if (Vector3D.Z_AXIS.dotProduct(object.cameraMatrix.deltaTransformVector(direction)) < 0) {
|
||||
for (i = 0; i < numVisibleChildren; i++) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
} else {
|
||||
for (i = numVisibleChildren - 1; i >= 0; i--) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,826 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
import alternativa.engine3d.core.BoundBox;
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Canvas;
|
||||
import alternativa.engine3d.core.Debug;
|
||||
import alternativa.engine3d.core.Geometry;
|
||||
import alternativa.engine3d.core.Node;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
import alternativa.engine3d.objects.Occluder;
|
||||
import alternativa.engine3d.objects.Reference;
|
||||
|
||||
import flash.geom.Utils3D;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Контейнер, дочерние объекты которого помещены в бинарную древовидную структуру.
|
||||
* Для построения дерева нужно добавить статические дочерние объекты
|
||||
* с помощью addStaticChild(), затем вызвать createTree(). По баундам статических объектов
|
||||
* построится ориентированная по осям бинарная древовидная структура (KD - частный случай BSP).
|
||||
* Динамические объекты, можно в любое время добавлять addDynamicChild() и удалять removeDynamicChild().
|
||||
* Объекты, добавленные с помощью addChild() будут отрисовываться поверх всего в порядке добавления.
|
||||
*/
|
||||
public class KDTree extends ConflictContainer {
|
||||
|
||||
public var debugAlphaFade:Number = 0.8;
|
||||
|
||||
private var rootNode:Node;
|
||||
|
||||
override alternativa3d function get canDraw():Boolean {
|
||||
return _numChildren > 0 || rootNode != null;
|
||||
}
|
||||
|
||||
override alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
||||
// Если есть корневая нода
|
||||
if (rootNode != null) {
|
||||
// Расчёт инверсной матрицы камеры и позицци камеры в контейнере
|
||||
calculateInverseCameraMatrix(object.cameraMatrix);
|
||||
// Расчёт плоскостей камеры в контейнере
|
||||
calculateCameraPlanes(camera);
|
||||
// Проверка на видимость рутовой ноды
|
||||
var culling:int = cullingInContainer(camera, rootNode.boundBox, object.culling);
|
||||
if (culling >= 0) {
|
||||
// Подготовка канваса
|
||||
var canvas:Canvas = parentCanvas.getChildCanvas(false, true, object.alpha, object.blendMode, object.colorTransform, object.filters);
|
||||
canvas.numDraws = 0;
|
||||
// Окклюдеры
|
||||
numOccluders = 0;
|
||||
if (camera.numOccluders > 0) {
|
||||
updateOccluders(camera);
|
||||
}
|
||||
// Сбор видимой геометрии
|
||||
var geometry:Geometry = getGeometry(camera, object);
|
||||
var current:Geometry = geometry;
|
||||
while (current != null) {
|
||||
current.vertices.length = current.verticesLength;
|
||||
inverseCameraMatrix.transformVectors(current.vertices, current.vertices);
|
||||
current.calculateAABB();
|
||||
current = current.next;
|
||||
}
|
||||
// Отрисовка дерева
|
||||
drawNode(rootNode, culling, camera, object, canvas, geometry);
|
||||
// Если была отрисовка
|
||||
if (canvas.numDraws > 0) {
|
||||
canvas.removeChildren(canvas.numDraws);
|
||||
} else {
|
||||
parentCanvas.numDraws--;
|
||||
}
|
||||
} else {
|
||||
super.draw(camera, object, parentCanvas);
|
||||
}
|
||||
} else {
|
||||
super.draw(camera, object, parentCanvas);
|
||||
}
|
||||
}
|
||||
|
||||
override alternativa3d function debug(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
||||
var debugResult:int = camera.checkInDebug(this);
|
||||
if (debugResult == 0) return;
|
||||
var canvas:Canvas = parentCanvas.getChildCanvas(true, false);
|
||||
// Ноды
|
||||
if (debugResult & Debug.NODES) {
|
||||
if (rootNode != null) {
|
||||
var culling:int = cullingInContainer(camera, rootNode.boundBox, object.culling);
|
||||
if (culling >= 0) {
|
||||
debugNode(rootNode, culling, camera, object, canvas, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Оси, центры, имена, баунды
|
||||
if (debugResult & Debug.AXES) object.drawAxes(camera, canvas);
|
||||
if (debugResult & Debug.CENTERS) object.drawCenter(camera, canvas);
|
||||
if (debugResult & Debug.NAMES) object.drawName(camera, canvas);
|
||||
if (debugResult & Debug.BOUNDS) object.drawBoundBox(camera, canvas);
|
||||
}
|
||||
|
||||
// Отрисовка ноды
|
||||
private function drawNode(node:Node, culling:int, camera:Camera3D, object:Object3D, canvas:Canvas, geometry:Geometry):void {
|
||||
var i:int;
|
||||
var next:Geometry;
|
||||
var negative:Geometry;
|
||||
var middle:Geometry;
|
||||
var positive:Geometry;
|
||||
var negativePart:Geometry;
|
||||
var positivePart:Geometry;
|
||||
if (camera.occludedAll) {
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
geometry.destroy();
|
||||
geometry = next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var nodeObjects:Vector.<Object3D> = node.objects;
|
||||
var nodeNumObjects:int = node.numObjects;
|
||||
var nodeNumNonOccluders:int = node.numNonOccluders;
|
||||
var staticChild:Object3D;
|
||||
// Узловая нода
|
||||
if (node.negative != null) {
|
||||
var negativeCulling:int = (culling > 0 || numOccluders > 0) ? cullingInContainer(camera, node.negative.boundBox, culling) : 0;
|
||||
var positiveCulling:int = (culling > 0 || numOccluders > 0) ? cullingInContainer(camera, node.positive.boundBox, culling) : 0;
|
||||
var axisX:Boolean = node.normalX != 0;
|
||||
var axisY:Boolean = node.normalY != 0;
|
||||
var min:Number;
|
||||
var max:Number;
|
||||
// Если видны обе дочерние ноды
|
||||
if (negativeCulling >= 0 && positiveCulling >= 0) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
min = axisX ? geometry.minX : (axisY ? geometry.minY : geometry.minZ);
|
||||
max = axisX ? geometry.maxX : (axisY ? geometry.maxY : geometry.maxZ);
|
||||
if (max <= node.offsetMax) {
|
||||
if (min < node.offsetMin) {
|
||||
geometry.next = negative;
|
||||
negative = geometry;
|
||||
} else {
|
||||
geometry.next = middle;
|
||||
middle = geometry;
|
||||
}
|
||||
} else {
|
||||
if (min >= node.offsetMin) {
|
||||
geometry.next = positive;
|
||||
positive = geometry;
|
||||
} else {
|
||||
negativePart = geometry.create();
|
||||
positivePart = geometry.create();
|
||||
geometry.split(axisX, axisY, node.offset, threshold, negativePart, positivePart);
|
||||
geometry.destroy();
|
||||
// Если негативный не пустой
|
||||
if (negativePart.fragment != null) {
|
||||
negativePart.next = negative;
|
||||
negative = negativePart;
|
||||
} else {
|
||||
negativePart.destroy();
|
||||
}
|
||||
// Если позитивный не пустой
|
||||
if (positivePart.fragment != null) {
|
||||
positivePart.next = positive;
|
||||
positive = positivePart;
|
||||
} else {
|
||||
positivePart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Отрисовка дочерних нод и объектов в плоскости
|
||||
if (axisX && cameraX > node.offset || axisY && cameraY > node.offset || !axisX && !axisY && cameraZ > node.offset) {
|
||||
// Отрисовка позитивной ноды
|
||||
drawNode(node.positive, positiveCulling, camera, object, canvas, positive);
|
||||
// Отрисовка динамических объектов в ноде
|
||||
while (middle != null) {
|
||||
next = middle.next;
|
||||
// Проверка с окклюдерами и отрисовка
|
||||
if (middle.numOccluders >= numOccluders || !occludeGeometry(camera, middle)) {
|
||||
if (camera.debugMode) middle.debug(camera, object, canvas, threshold, 1, object.cameraMatrix);
|
||||
middle.draw(camera, canvas, threshold, object.cameraMatrix);
|
||||
}
|
||||
middle.destroy();
|
||||
middle = next;
|
||||
}
|
||||
// Отрисовка плоских статических объектов в ноде
|
||||
for (i = 0; i < nodeNumObjects; i++) {
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw && ((staticChild.culling = culling) == 0 && numOccluders == 0 || (staticChild.culling = cullingInContainer(camera, node.bounds[i], culling)) >= 0)) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
if (camera.debugMode) staticChild.debug(camera, staticChild, canvas);
|
||||
staticChild.draw(camera, staticChild, canvas);
|
||||
}
|
||||
}
|
||||
// Обновление окклюдеров
|
||||
if (nodeNumObjects > nodeNumNonOccluders) {
|
||||
updateOccluders(camera);
|
||||
}
|
||||
// Отрисовка негативной ноды
|
||||
drawNode(node.negative, negativeCulling, camera, object, canvas, negative);
|
||||
} else {
|
||||
// Отрисовка негативной ноды
|
||||
drawNode(node.negative, negativeCulling, camera, object, canvas, negative);
|
||||
// Отрисовка динамических объектов в ноде
|
||||
while (middle != null) {
|
||||
next = middle.next;
|
||||
// Проверка с окклюдерами и отрисовка
|
||||
if (middle.numOccluders >= numOccluders || !occludeGeometry(camera, middle)) {
|
||||
if (camera.debugMode) middle.debug(camera, object, canvas, threshold, 1, object.cameraMatrix);
|
||||
middle.draw(camera, canvas, threshold, object.cameraMatrix);
|
||||
}
|
||||
middle.destroy();
|
||||
middle = next;
|
||||
}
|
||||
// Отрисовка статических объектов в ноде
|
||||
for (i = 0; i < nodeNumObjects; i++) {
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw && ((staticChild.culling = culling) == 0 && numOccluders == 0 || (staticChild.culling = cullingInContainer(camera, node.bounds[i], culling)) >= 0)) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
if (camera.debugMode) staticChild.debug(camera, staticChild, canvas);
|
||||
staticChild.draw(camera, staticChild, canvas);
|
||||
}
|
||||
}
|
||||
// Обновление окклюдеров
|
||||
if (nodeNumObjects > nodeNumNonOccluders) {
|
||||
updateOccluders(camera);
|
||||
}
|
||||
// Отрисовка позитивной ноды
|
||||
drawNode(node.positive, positiveCulling, camera, object, canvas, positive);
|
||||
}
|
||||
// Если видна только негативная
|
||||
} else if (negativeCulling >= 0) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
min = axisX ? geometry.minX : (axisY ? geometry.minY : geometry.minZ);
|
||||
max = axisX ? geometry.maxX : (axisY ? geometry.maxY : geometry.maxZ);
|
||||
if (max <= node.offsetMax) {
|
||||
geometry.next = negative;
|
||||
negative = geometry;
|
||||
} else if (min < node.offsetMin) {
|
||||
negativePart = geometry.create();
|
||||
geometry.split(axisX, axisY, node.offset, threshold, negativePart, null);
|
||||
geometry.destroy();
|
||||
// Если негативный не пустой
|
||||
if (negativePart.fragment != null) {
|
||||
negativePart.next = negative;
|
||||
negative = negativePart;
|
||||
} else {
|
||||
negativePart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Отрисовка негативной ноды
|
||||
drawNode(node.negative, negativeCulling, camera, object, canvas, negative);
|
||||
// Если видна только позитивная
|
||||
} else if (positiveCulling >= 0) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
min = axisX ? geometry.minX : (axisY ? geometry.minY : geometry.minZ);
|
||||
max = axisX ? geometry.maxX : (axisY ? geometry.maxY : geometry.maxZ);
|
||||
if (min >= node.offsetMin) {
|
||||
geometry.next = positive;
|
||||
positive = geometry;
|
||||
} else if (max > node.offsetMax) {
|
||||
positivePart = geometry.create();
|
||||
geometry.split(axisX, axisY, node.offset, threshold, null, positivePart);
|
||||
geometry.destroy();
|
||||
// Если позитивный не пустой
|
||||
if (positivePart.fragment != null) {
|
||||
positivePart.next = positive;
|
||||
positive = positivePart;
|
||||
} else {
|
||||
positivePart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Отрисовка позитивной ноды
|
||||
drawNode(node.positive, positiveCulling, camera, object, canvas, positive);
|
||||
}
|
||||
// Конечная нода
|
||||
} else {
|
||||
// Если есть статические объекты, не считая окклюдеры
|
||||
if (nodeNumNonOccluders > 0) {
|
||||
// Если есть конфликт
|
||||
if (nodeNumNonOccluders > 1 || geometry != null) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
geometry.next = middle;
|
||||
middle = geometry;
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Превращение статиков в геометрию
|
||||
for (i = 0; i < nodeNumNonOccluders; i++) {
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw && ((staticChild.culling = culling) == 0 && numOccluders == 0 || (staticChild.culling = cullingInContainer(camera, node.bounds[i], culling)) >= 0)) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
geometry = staticChild.getGeometry(camera, staticChild);
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
geometry.next = middle;
|
||||
middle = geometry;
|
||||
geometry = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Разруливаем конфликт
|
||||
if (middle != null) {
|
||||
if (middle.next != null) {
|
||||
drawConflictGeometry(camera, object, canvas, middle);
|
||||
} else {
|
||||
if (camera.debugMode) middle.debug(camera, object, canvas, threshold, 1);
|
||||
middle.draw(camera, canvas, threshold);
|
||||
middle.destroy();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Если только один статик
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
staticChild.culling = culling;
|
||||
if (camera.debugMode) staticChild.debug(camera, staticChild, canvas);
|
||||
staticChild.draw(camera, staticChild, canvas);
|
||||
}
|
||||
}
|
||||
// Если нет статических объектов
|
||||
} else {
|
||||
// Если есть динамические объекты
|
||||
if (geometry != null) {
|
||||
// Если динамических объектов несколько
|
||||
if (geometry.next != null) {
|
||||
// Если есть окклюдеры
|
||||
if (numOccluders > 0) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
geometry.next = middle;
|
||||
middle = geometry;
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Если остались объекты
|
||||
if (middle != null) {
|
||||
if (middle.next != null) {
|
||||
// Разруливание
|
||||
if (resolveByAABB) {
|
||||
drawAABBGeometry(camera, object, canvas, middle);
|
||||
} else if (resolveByOOBB) {
|
||||
geometry = middle;
|
||||
while (geometry != null) {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
if (!geometry.viewAligned) {
|
||||
geometry.calculateOOBB();
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
drawOOBBGeometry(camera, object, canvas, middle);
|
||||
} else {
|
||||
geometry = middle;
|
||||
while (geometry != null) {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
geometry = geometry.next;
|
||||
}
|
||||
drawConflictGeometry(camera, object, canvas, middle);
|
||||
}
|
||||
} else {
|
||||
if (camera.debugMode) middle.debug(camera, object, canvas, threshold, 1, object.cameraMatrix);
|
||||
middle.draw(camera, canvas, threshold, object.cameraMatrix);
|
||||
middle.destroy();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Разруливание
|
||||
middle = geometry;
|
||||
if (resolveByAABB) {
|
||||
drawAABBGeometry(camera, object, canvas, middle);
|
||||
} else if (resolveByOOBB) {
|
||||
geometry = middle;
|
||||
while (geometry != null) {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
if (!geometry.viewAligned) {
|
||||
geometry.calculateOOBB();
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
drawOOBBGeometry(camera, object, canvas, middle);
|
||||
} else {
|
||||
geometry = middle;
|
||||
while (geometry != null) {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
geometry = geometry.next;
|
||||
}
|
||||
drawConflictGeometry(camera, object, canvas, middle);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Проверка с окклюдерами и отрисовка
|
||||
if (geometry.numOccluders >= numOccluders || !occludeGeometry(camera, geometry)) {
|
||||
if (camera.debugMode) geometry.debug(camera, object, canvas, threshold, 1, object.cameraMatrix);
|
||||
geometry.draw(camera, canvas, threshold, object.cameraMatrix);
|
||||
}
|
||||
geometry.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Если в ноде есть окклюдеры
|
||||
if (nodeNumObjects > nodeNumNonOccluders) {
|
||||
for (i = nodeNumNonOccluders; i < nodeNumObjects; i++) {
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw && ((staticChild.culling = culling) == 0 && numOccluders == 0 || (staticChild.culling = cullingInContainer(camera, node.bounds[i], culling)) >= 0)) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
if (camera.debugMode) staticChild.debug(camera, staticChild, canvas);
|
||||
staticChild.draw(camera, staticChild, canvas);
|
||||
}
|
||||
}
|
||||
// Обновление окклюдеров
|
||||
updateOccluders(camera);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private const nodeVertices:Vector.<Number> = new Vector.<Number>(12, true);
|
||||
static private const nodeProjectedVertices:Vector.<Number> = new Vector.<Number>(8, true);
|
||||
static private const nodeUVTs:Vector.<Number> = new Vector.<Number>(12, true);
|
||||
|
||||
private function debugNode(node:Node, culling:int, camera:Camera3D, object:Object3D, canvas:Canvas, alpha:Number):void {
|
||||
if (node.negative != null) {
|
||||
var negativeCulling:int = (culling > 0) ? cullingInContainer(camera, node.negative.boundBox, culling) : 0;
|
||||
var positiveCulling:int = (culling > 0) ? cullingInContainer(camera, node.positive.boundBox, culling) : 0;
|
||||
if (negativeCulling >= 0) {
|
||||
debugNode(node.negative, negativeCulling, camera, object, canvas, alpha*debugAlphaFade);
|
||||
}
|
||||
if (positiveCulling >= 0) {
|
||||
debugNode(node.positive, positiveCulling, camera, object, canvas, alpha*debugAlphaFade);
|
||||
}
|
||||
|
||||
if (node.normalX) {
|
||||
nodeVertices[0] = node.offset;
|
||||
nodeVertices[1] = node.boundBox.minY;
|
||||
nodeVertices[2] = node.boundBox.maxZ;
|
||||
|
||||
nodeVertices[3] = node.offset;
|
||||
nodeVertices[4] = node.boundBox.maxY;
|
||||
nodeVertices[5] = node.boundBox.maxZ;
|
||||
|
||||
nodeVertices[6] = node.offset;
|
||||
nodeVertices[7] = node.boundBox.maxY;
|
||||
nodeVertices[8] = node.boundBox.minZ;
|
||||
|
||||
nodeVertices[9] = node.offset;
|
||||
nodeVertices[10] = node.boundBox.minY;
|
||||
nodeVertices[11] = node.boundBox.minZ;
|
||||
} else if (node.normalY) {
|
||||
nodeVertices[0] = node.boundBox.maxX;
|
||||
nodeVertices[1] = node.offset;
|
||||
nodeVertices[2] = node.boundBox.maxZ;
|
||||
|
||||
nodeVertices[3] = node.boundBox.minX;
|
||||
nodeVertices[4] = node.offset;
|
||||
nodeVertices[5] = node.boundBox.maxZ;
|
||||
|
||||
nodeVertices[6] = node.boundBox.minX;
|
||||
nodeVertices[7] = node.offset;
|
||||
nodeVertices[8] = node.boundBox.minZ;
|
||||
|
||||
nodeVertices[9] = node.boundBox.maxX;
|
||||
nodeVertices[10] = node.offset;
|
||||
nodeVertices[11] = node.boundBox.minZ;
|
||||
} else {
|
||||
nodeVertices[0] = node.boundBox.minX;
|
||||
nodeVertices[1] = node.boundBox.minY;
|
||||
nodeVertices[2] = node.offset;
|
||||
|
||||
nodeVertices[3] = node.boundBox.maxX;
|
||||
nodeVertices[4] = node.boundBox.minY;
|
||||
nodeVertices[5] = node.offset;
|
||||
|
||||
nodeVertices[6] = node.boundBox.maxX;
|
||||
nodeVertices[7] = node.boundBox.maxY;
|
||||
nodeVertices[8] = node.offset;
|
||||
|
||||
nodeVertices[9] = node.boundBox.minX;
|
||||
nodeVertices[10] = node.boundBox.maxY;
|
||||
nodeVertices[11] = node.offset;
|
||||
}
|
||||
object.cameraMatrix.transformVectors(nodeVertices, nodeVertices);
|
||||
var i:int;
|
||||
for (i = 0; i < 12; i += 3) {
|
||||
if (nodeVertices[int(i + 2)] <= 0) break;
|
||||
}
|
||||
if (i == 12) {
|
||||
Utils3D.projectVectors(camera.projectionMatrix, nodeVertices, nodeProjectedVertices, nodeUVTs);
|
||||
canvas.gfx.lineStyle(0, node.normalX ? 0xFF0000 : (node.normalY ? 0x00FF00 : 0x0000FF));
|
||||
canvas.gfx.moveTo(nodeProjectedVertices[0], nodeProjectedVertices[1]);
|
||||
canvas.gfx.lineTo(nodeProjectedVertices[2], nodeProjectedVertices[3]);
|
||||
canvas.gfx.lineTo(nodeProjectedVertices[4], nodeProjectedVertices[5]);
|
||||
canvas.gfx.lineTo(nodeProjectedVertices[6], nodeProjectedVertices[7]);
|
||||
canvas.gfx.lineTo(nodeProjectedVertices[0], nodeProjectedVertices[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function createTree(staticObjects:Vector.<Object3D>, boundBox:BoundBox = null):void {
|
||||
var numStaticChildren:int = staticObjects.length;
|
||||
if (numStaticChildren > 0) {
|
||||
// Создаём корневую ноду
|
||||
rootNode = new Node();
|
||||
rootNode.objects = new Vector.<Object3D>();
|
||||
rootNode.bounds = new Vector.<BoundBox>();
|
||||
rootNode.numObjects = 0;
|
||||
// Расчитываем баунды объектов и рутовой ноды
|
||||
rootNode.boundBox = (boundBox != null) ? boundBox : new BoundBox();
|
||||
// Сначала добавляем не окклюдеры
|
||||
var staticOccluders:Vector.<Object3D> = new Vector.<Object3D>();
|
||||
var staticOccludersLength:int = 0;
|
||||
var object:Object3D;
|
||||
var objectBoundBox:BoundBox;
|
||||
for (var i:int = 0; i < numStaticChildren; i++) {
|
||||
object = staticObjects[i];
|
||||
// Поиск оригинального объекта
|
||||
var source:Object3D = object;
|
||||
while (source is Reference) {
|
||||
source = (source as Reference).referenceObject;
|
||||
}
|
||||
// Если окклюдер
|
||||
if (source is Occluder) {
|
||||
staticOccluders[staticOccludersLength++] = object;
|
||||
} else {
|
||||
objectBoundBox = object.calculateBoundBox(object.matrix);
|
||||
rootNode.objects[rootNode.numObjects] = object;
|
||||
rootNode.bounds[rootNode.numObjects++] = objectBoundBox;
|
||||
rootNode.boundBox.addBoundBox(objectBoundBox);
|
||||
}
|
||||
}
|
||||
// Добавляем окклюдеры
|
||||
for (i = 0; i < staticOccludersLength; i++) {
|
||||
object = staticOccluders[i];
|
||||
objectBoundBox = object.calculateBoundBox(object.matrix);
|
||||
rootNode.objects[rootNode.numObjects] = object;
|
||||
rootNode.bounds[rootNode.numObjects++] = objectBoundBox;
|
||||
rootNode.boundBox.addBoundBox(objectBoundBox);
|
||||
}
|
||||
// Разделяем рутовую ноду
|
||||
splitNode(rootNode);
|
||||
}
|
||||
}
|
||||
|
||||
private var splitAxis:int;
|
||||
private var splitCoord:Number;
|
||||
private var splitCost:Number;
|
||||
static private const nodeBoundBoxThreshold:BoundBox = new BoundBox();
|
||||
static private const splitCoordsX:Vector.<Number> = new Vector.<Number>();
|
||||
static private const splitCoordsY:Vector.<Number> = new Vector.<Number>();
|
||||
static private const splitCoordsZ:Vector.<Number> = new Vector.<Number>();
|
||||
private function splitNode(node:Node):void {
|
||||
|
||||
var object:Object3D, boundBox:BoundBox, i:int, j:int, k:int, c1:Number, c2:Number, coordMin:Number, coordMax:Number, area:Number, areaNegative:Number, areaPositive:Number, numNegative:int, numPositive:int, conflict:Boolean, cost:Number;
|
||||
var nodeBoundBox:BoundBox = node.boundBox;
|
||||
|
||||
// Подготовка баунда с погрешностями
|
||||
nodeBoundBoxThreshold.minX = nodeBoundBox.minX + threshold;
|
||||
nodeBoundBoxThreshold.minY = nodeBoundBox.minY + threshold;
|
||||
nodeBoundBoxThreshold.minZ = nodeBoundBox.minZ + threshold;
|
||||
nodeBoundBoxThreshold.maxX = nodeBoundBox.maxX - threshold;
|
||||
nodeBoundBoxThreshold.maxY = nodeBoundBox.maxY - threshold;
|
||||
nodeBoundBoxThreshold.maxZ = nodeBoundBox.maxZ - threshold;
|
||||
var doubleThreshold:Number = threshold + threshold;
|
||||
|
||||
// Собираем опорные координаты
|
||||
var numSplitCoordsX:int = 0, numSplitCoordsY:int = 0, numSplitCoordsZ:int = 0;
|
||||
for (i = 0; i < node.numObjects; i++) {
|
||||
boundBox = node.bounds[i];
|
||||
if (boundBox.maxX - boundBox.minX <= doubleThreshold) {
|
||||
if (boundBox.minX <= nodeBoundBoxThreshold.minX) splitCoordsX[numSplitCoordsX++] = nodeBoundBox.minX;
|
||||
else if (boundBox.maxX >= nodeBoundBoxThreshold.maxX) splitCoordsX[numSplitCoordsX++] = nodeBoundBox.maxX;
|
||||
else splitCoordsX[numSplitCoordsX++] = (boundBox.minX + boundBox.maxX)*0.5;
|
||||
} else {
|
||||
if (boundBox.minX > nodeBoundBoxThreshold.minX) splitCoordsX[numSplitCoordsX++] = boundBox.minX;
|
||||
if (boundBox.maxX < nodeBoundBoxThreshold.maxX) splitCoordsX[numSplitCoordsX++] = boundBox.maxX;
|
||||
}
|
||||
if (boundBox.maxY - boundBox.minY <= doubleThreshold) {
|
||||
if (boundBox.minY <= nodeBoundBoxThreshold.minY) splitCoordsY[numSplitCoordsY++] = nodeBoundBox.minY;
|
||||
else if (boundBox.maxY >= nodeBoundBoxThreshold.maxY) splitCoordsY[numSplitCoordsY++] = nodeBoundBox.maxY;
|
||||
else splitCoordsY[numSplitCoordsY++] = (boundBox.minY + boundBox.maxY)*0.5;
|
||||
} else {
|
||||
if (boundBox.minY > nodeBoundBoxThreshold.minY) splitCoordsY[numSplitCoordsY++] = boundBox.minY;
|
||||
if (boundBox.maxY < nodeBoundBoxThreshold.maxY) splitCoordsY[numSplitCoordsY++] = boundBox.maxY;
|
||||
}
|
||||
if (boundBox.maxZ - boundBox.minZ <= doubleThreshold) {
|
||||
if (boundBox.minZ <= nodeBoundBoxThreshold.minZ) splitCoordsZ[numSplitCoordsZ++] = nodeBoundBox.minZ;
|
||||
else if (boundBox.maxZ >= nodeBoundBoxThreshold.maxZ) splitCoordsZ[numSplitCoordsZ++] = nodeBoundBox.maxZ;
|
||||
else splitCoordsZ[numSplitCoordsZ++] = (boundBox.minZ + boundBox.maxZ)*0.5;
|
||||
} else {
|
||||
if (boundBox.minZ > nodeBoundBoxThreshold.minZ) splitCoordsZ[numSplitCoordsZ++] = boundBox.minZ;
|
||||
if (boundBox.maxZ < nodeBoundBoxThreshold.maxZ) splitCoordsZ[numSplitCoordsZ++] = boundBox.maxZ;
|
||||
}
|
||||
}
|
||||
|
||||
// Убираем дубликаты координат, ищем наилучший сплит
|
||||
splitAxis = -1; splitCost = Number.MAX_VALUE;
|
||||
i = 0; area = (nodeBoundBox.maxY - nodeBoundBox.minY)*(nodeBoundBox.maxZ - nodeBoundBox.minZ);
|
||||
while (i < numSplitCoordsX) {
|
||||
if (!isNaN(c1 = splitCoordsX[i++])) {
|
||||
coordMin = c1 - threshold;
|
||||
coordMax = c1 + threshold;
|
||||
areaNegative = area*(c1 - nodeBoundBox.minX);
|
||||
areaPositive = area*(nodeBoundBox.maxX - c1);
|
||||
numNegative = numPositive = 0;
|
||||
conflict = false;
|
||||
// Проверяем объекты
|
||||
for (j = 0; j < node.numObjects; j++) {
|
||||
boundBox = node.bounds[j];
|
||||
if (boundBox.maxX <= coordMax) {
|
||||
if (boundBox.minX < coordMin) numNegative++;
|
||||
} else {
|
||||
if (boundBox.minX >= coordMin) numPositive++; else {conflict = true; break;}
|
||||
}
|
||||
}
|
||||
// Если хороший сплит, сохраняем
|
||||
if (!conflict && (cost = areaNegative*numNegative + areaPositive*numPositive) < splitCost) {
|
||||
splitCost = cost;
|
||||
splitAxis = 0;
|
||||
splitCoord = c1;
|
||||
}
|
||||
j = i;
|
||||
while (++j < numSplitCoordsX) if ((c2 = splitCoordsX[j]) >= c1 - threshold && c2 <= c1 + threshold) splitCoordsX[j] = NaN;
|
||||
}
|
||||
}
|
||||
i = 0; area = (nodeBoundBox.maxX - nodeBoundBox.minX)*(nodeBoundBox.maxZ - nodeBoundBox.minZ);
|
||||
while (i < numSplitCoordsY) {
|
||||
if (!isNaN(c1 = splitCoordsY[i++])) {
|
||||
coordMin = c1 - threshold;
|
||||
coordMax = c1 + threshold;
|
||||
areaNegative = area*(c1 - nodeBoundBox.minY);
|
||||
areaPositive = area*(nodeBoundBox.maxY - c1);
|
||||
numNegative = numPositive = 0;
|
||||
conflict = false;
|
||||
// Проверяем объекты
|
||||
for (j = 0; j < node.numObjects; j++) {
|
||||
boundBox = node.bounds[j];
|
||||
if (boundBox.maxY <= coordMax) {
|
||||
if (boundBox.minY < coordMin) numNegative++;
|
||||
} else {
|
||||
if (boundBox.minY >= coordMin) numPositive++; else {conflict = true; break;}
|
||||
}
|
||||
}
|
||||
// Если хороший сплит, сохраняем
|
||||
if (!conflict && (cost = areaNegative*numNegative + areaPositive*numPositive) < splitCost) {
|
||||
splitCost = cost;
|
||||
splitAxis = 1;
|
||||
splitCoord = c1;
|
||||
}
|
||||
j = i;
|
||||
while (++j < numSplitCoordsY) if ((c2 = splitCoordsY[j]) >= c1 - threshold && c2 <= c1 + threshold) splitCoordsY[j] = NaN;
|
||||
}
|
||||
}
|
||||
i = 0; area = (nodeBoundBox.maxX - nodeBoundBox.minX)*(nodeBoundBox.maxY - nodeBoundBox.minY);
|
||||
while (i < numSplitCoordsZ) {
|
||||
if (!isNaN(c1 = splitCoordsZ[i++])) {
|
||||
coordMin = c1 - threshold;
|
||||
coordMax = c1 + threshold;
|
||||
areaNegative = area*(c1 - nodeBoundBox.minZ);
|
||||
areaPositive = area*(nodeBoundBox.maxZ - c1);
|
||||
numNegative = numPositive = 0;
|
||||
conflict = false;
|
||||
// Проверяем объекты
|
||||
for (j = 0; j < node.numObjects; j++) {
|
||||
boundBox = node.bounds[j];
|
||||
if (boundBox.maxZ <= coordMax) {
|
||||
if (boundBox.minZ < coordMin) numNegative++;
|
||||
} else {
|
||||
if (boundBox.minZ >= coordMin) numPositive++; else {conflict = true; break;}
|
||||
}
|
||||
}
|
||||
// Если хороший сплит, сохраняем
|
||||
if (!conflict && (cost = areaNegative*numNegative + areaPositive*numPositive) < splitCost) {
|
||||
splitCost = cost;
|
||||
splitAxis = 2;
|
||||
splitCoord = c1;
|
||||
}
|
||||
j = i;
|
||||
while (++j < numSplitCoordsZ) if ((c2 = splitCoordsZ[j]) >= c1 - threshold && c2 <= c1 + threshold) splitCoordsZ[j] = NaN;
|
||||
}
|
||||
}
|
||||
|
||||
// Если сплит не найден, выходим
|
||||
if (splitAxis < 0) {
|
||||
// Находим, откуда начинаются окклюдеры
|
||||
for (i = 0; i < node.numObjects; i++) {
|
||||
object = node.objects[i];
|
||||
// Поиск оригинального объекта
|
||||
while (object is Reference) object = (object as Reference).referenceObject;
|
||||
if (object is Occluder) break;
|
||||
}
|
||||
node.numNonOccluders = i;
|
||||
return;
|
||||
}
|
||||
|
||||
// Разделяем ноду
|
||||
if (splitAxis == 0) {
|
||||
node.normalX = 1;
|
||||
node.normalY = 0;
|
||||
node.normalZ = 0;
|
||||
} else if (splitAxis == 1) {
|
||||
node.normalX = 0;
|
||||
node.normalY = 1;
|
||||
node.normalZ = 0;
|
||||
} else {
|
||||
node.normalX = 0;
|
||||
node.normalY = 0;
|
||||
node.normalZ = 1;
|
||||
}
|
||||
node.offset = splitCoord;
|
||||
node.offsetMin = splitCoord - threshold;
|
||||
node.offsetMax = splitCoord + threshold;
|
||||
|
||||
// Создаём дочерние ноды
|
||||
node.negative = new Node();
|
||||
node.positive = new Node();
|
||||
node.negative.boundBox = nodeBoundBox.clone();
|
||||
node.positive.boundBox = nodeBoundBox.clone();
|
||||
node.negative.numObjects = 0;
|
||||
node.positive.numObjects = 0;
|
||||
if (node.normalX) {
|
||||
node.negative.boundBox.maxX = node.positive.boundBox.minX = splitCoord;
|
||||
} else if (node.normalY) {
|
||||
node.negative.boundBox.maxY = node.positive.boundBox.minY = splitCoord;
|
||||
} else {
|
||||
node.negative.boundBox.maxZ = node.positive.boundBox.minZ = splitCoord;
|
||||
}
|
||||
// Распределяем объекты по дочерним нодам
|
||||
for (i = 0; i < node.numObjects; i++) {
|
||||
object = node.objects[i];
|
||||
boundBox = node.bounds[i];
|
||||
var min:Number = node.normalX ? boundBox.minX : (node.normalY ? boundBox.minY : boundBox.minZ);
|
||||
var max:Number = node.normalX ? boundBox.maxX : (node.normalY ? boundBox.maxY : boundBox.maxZ);
|
||||
if (max <= node.offsetMax) {
|
||||
if (min < node.offsetMin) {
|
||||
// Объект в негативной стороне
|
||||
if (node.negative.objects == null) node.negative.objects = new Vector.<Object3D>(), node.negative.bounds = new Vector.<BoundBox>();
|
||||
node.negative.objects[node.negative.numObjects] = object, node.negative.bounds[node.negative.numObjects++] = boundBox;
|
||||
node.objects[i] = null, node.bounds[i] = null;
|
||||
} else {
|
||||
// Остаётся в ноде
|
||||
}
|
||||
} else {
|
||||
if (min >= node.offsetMin) {
|
||||
// Объект в положительной стороне
|
||||
if (node.positive.objects == null) node.positive.objects = new Vector.<Object3D>(), node.positive.bounds = new Vector.<BoundBox>();
|
||||
node.positive.objects[node.positive.numObjects] = object, node.positive.bounds[node.positive.numObjects++] = boundBox;
|
||||
node.objects[i] = null, node.bounds[i] = null;
|
||||
} else {
|
||||
// Распилился
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Очистка списка объектов
|
||||
for (i = 0, j = 0; i < node.numObjects; i++) if (node.objects[i] != null) node.objects[j] = node.objects[i], node.bounds[j++] = node.bounds[i];
|
||||
if (j > 0) {
|
||||
node.numObjects = node.objects.length = node.bounds.length = j;
|
||||
// Находим, откуда начинаются окклюдеры
|
||||
for (i = 0; i < node.numObjects; i++) {
|
||||
object = node.objects[i];
|
||||
// Поиск оригинального объекта
|
||||
while (object is Reference) object = (object as Reference).referenceObject;
|
||||
if (object is Occluder) break;
|
||||
}
|
||||
node.numNonOccluders = i;
|
||||
} else {
|
||||
node.numObjects = node.numNonOccluders = 0, node.objects = null, node.bounds = null;
|
||||
}
|
||||
|
||||
// Разделение дочерних нод
|
||||
if (node.negative.objects != null) splitNode(node.negative);
|
||||
if (node.positive.objects != null) splitNode(node.positive);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.core.Object3DContainer;
|
||||
import alternativa.engine3d.objects.Mesh;
|
||||
|
||||
import flash.display.BitmapData;
|
||||
|
||||
public class SkyBox extends Object3DContainer {
|
||||
|
||||
private var backPlane:Mesh;
|
||||
private var frontPlane:Mesh;
|
||||
private var topPlane:Mesh;
|
||||
private var bottomPlane:Mesh;
|
||||
private var leftPlane:Mesh;
|
||||
private var rightPlane:Mesh;
|
||||
|
||||
public function SkyBox(size:Number = 1000):void {
|
||||
backPlane = new Mesh();
|
||||
frontPlane = new Mesh();
|
||||
topPlane = new Mesh();
|
||||
bottomPlane = new Mesh();
|
||||
leftPlane = new Mesh();
|
||||
rightPlane = new Mesh();
|
||||
|
||||
backPlane.clipping = 2;
|
||||
frontPlane.clipping = 2;
|
||||
topPlane.clipping = 2;
|
||||
bottomPlane.clipping = 2;
|
||||
leftPlane.clipping = 2;
|
||||
rightPlane.clipping = 2;
|
||||
|
||||
backPlane.vertices = Vector.<Number>([
|
||||
-size, -size, -size,
|
||||
-size, -size, size,
|
||||
size, -size, size,
|
||||
size, -size, -size,
|
||||
]);
|
||||
frontPlane.vertices = Vector.<Number>([
|
||||
size, size, -size,
|
||||
size, size, size,
|
||||
-size, size, size,
|
||||
-size, size, -size,
|
||||
]);
|
||||
topPlane.vertices = Vector.<Number>([
|
||||
size, size, size,
|
||||
size, -size, size,
|
||||
-size, -size, size,
|
||||
-size, size, size,
|
||||
]);
|
||||
bottomPlane.vertices = Vector.<Number>([
|
||||
size, -size, -size,
|
||||
size, size, -size,
|
||||
-size, size, -size,
|
||||
-size, -size, -size,
|
||||
]);
|
||||
leftPlane.vertices = Vector.<Number>([
|
||||
-size, size, -size,
|
||||
-size, size, size,
|
||||
-size, -size, size,
|
||||
-size, -size, -size,
|
||||
]);
|
||||
rightPlane.vertices = Vector.<Number>([
|
||||
size, -size, -size,
|
||||
size, -size, size,
|
||||
size, size, size,
|
||||
size, size, -size,
|
||||
]);
|
||||
|
||||
var uvts:Vector.<Number> = Vector.<Number>([1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0]);
|
||||
backPlane.uvts = uvts;
|
||||
frontPlane.uvts = uvts;
|
||||
topPlane.uvts = uvts;
|
||||
bottomPlane.uvts = uvts;
|
||||
leftPlane.uvts = uvts;
|
||||
rightPlane.uvts = uvts;
|
||||
|
||||
var indices:Vector.<int> = Vector.<int>([4, 0, 1, 2, 3]);
|
||||
backPlane.indices = indices;
|
||||
frontPlane.indices = indices;
|
||||
topPlane.indices = indices;
|
||||
bottomPlane.indices = indices;
|
||||
leftPlane.indices = indices;
|
||||
rightPlane.indices = indices;
|
||||
|
||||
backPlane.numVertices = 4;
|
||||
frontPlane.numVertices = 4;
|
||||
topPlane.numVertices = 4;
|
||||
bottomPlane.numVertices = 4;
|
||||
leftPlane.numVertices = 4;
|
||||
rightPlane.numVertices = 4;
|
||||
|
||||
backPlane.numFaces = 1;
|
||||
frontPlane.numFaces = 1;
|
||||
topPlane.numFaces = 1;
|
||||
bottomPlane.numFaces = 1;
|
||||
leftPlane.numFaces = 1;
|
||||
rightPlane.numFaces = 1;
|
||||
|
||||
backPlane.poly = true;
|
||||
frontPlane.poly = true;
|
||||
topPlane.poly = true;
|
||||
bottomPlane.poly = true;
|
||||
leftPlane.poly = true;
|
||||
rightPlane.poly = true;
|
||||
|
||||
addChild(backPlane);
|
||||
addChild(frontPlane);
|
||||
addChild(topPlane);
|
||||
addChild(bottomPlane);
|
||||
addChild(leftPlane);
|
||||
addChild(rightPlane);
|
||||
}
|
||||
|
||||
public function set backTexture(value:BitmapData):void {
|
||||
backPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set frontTexture(value:BitmapData):void {
|
||||
frontPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set topTexture(value:BitmapData):void {
|
||||
topPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set bottomTexture(value:BitmapData):void {
|
||||
bottomPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set leftTexture(value:BitmapData):void {
|
||||
leftPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set rightTexture(value:BitmapData):void {
|
||||
rightPlane.texture = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Canvas;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
import alternativa.engine3d.core.Object3DContainer;
|
||||
|
||||
import flash.geom.Matrix3D;
|
||||
import flash.geom.Vector3D;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class SplitContainer extends Object3DContainer {
|
||||
|
||||
public var splitPlane:Vector3D = new Vector3D(0, 0, 1, 0);
|
||||
static private const invertCameraMatrix:Matrix3D = new Matrix3D();
|
||||
static private const cameraPosition:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
static private const invertCameraPosition:Vector.<Number> = new Vector.<Number>(3, true);
|
||||
|
||||
override protected function drawVisibleChildren(camera:Camera3D, object:Object3D, canvas:Canvas):void {
|
||||
var i:int;
|
||||
var child:Object3D;
|
||||
invertCameraMatrix.identity();
|
||||
invertCameraMatrix.prepend(object.cameraMatrix);
|
||||
invertCameraMatrix.invert();
|
||||
invertCameraMatrix.transformVectors(cameraPosition, invertCameraPosition);
|
||||
if (invertCameraPosition[0]*splitPlane.x + invertCameraPosition[1]*splitPlane.y + invertCameraPosition[2]*splitPlane.z < splitPlane.w) {
|
||||
for (i = 0; i < numVisibleChildren; i++) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
} else {
|
||||
for (i = numVisibleChildren - 1; i >= 0; i--) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Canvas;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
import alternativa.engine3d.core.Object3DContainer;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Контейнер, дочерние объекты которого отрисовываются по удалённости от камеры
|
||||
*/
|
||||
public class AverageZContainer extends Object3DContainer {
|
||||
|
||||
static private const averageZ:Vector.<Number> = new Vector.<Number>();
|
||||
static private const center:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
static private const cameraCenter:Vector.<Number> = new Vector.<Number>(3, true);
|
||||
static private const sortingStack:Vector.<int> = new Vector.<int>();
|
||||
|
||||
override protected function drawVisibleChildren(camera:Camera3D, object:Object3D, canvas:Canvas):void {
|
||||
var i:int;
|
||||
var j:int;
|
||||
var l:int = 0;
|
||||
var r:int = numVisibleChildren - 1;
|
||||
var child:Object3D;
|
||||
var sortingStackIndex:int;
|
||||
var sortingLeft:Number;
|
||||
var sortingMedian:Number;
|
||||
var sortingRight:Number;
|
||||
var sortingChild:Object3D;
|
||||
// Сортировка
|
||||
for (i = 0; i < numVisibleChildren; i++) {
|
||||
child = visibleChildren[i];
|
||||
child.cameraMatrix.transformVectors(center, cameraCenter);
|
||||
averageZ[i] = cameraCenter[0]*cameraCenter[0] + cameraCenter[1]*cameraCenter[1] + cameraCenter[2]*cameraCenter[2];
|
||||
}
|
||||
sortingStack[0] = l;
|
||||
sortingStack[1] = r;
|
||||
sortingStackIndex = 2;
|
||||
while (sortingStackIndex > 0) {
|
||||
j = r = sortingStack[--sortingStackIndex];
|
||||
i = l = sortingStack[--sortingStackIndex];
|
||||
sortingMedian = averageZ[(r + l) >> 1];
|
||||
do {
|
||||
while ((sortingLeft = averageZ[i]) > sortingMedian) i++;
|
||||
while ((sortingRight = averageZ[j]) < sortingMedian) j--;
|
||||
if (i <= j) {
|
||||
sortingChild = visibleChildren[i];
|
||||
visibleChildren[i] = visibleChildren[j];
|
||||
visibleChildren[j] = sortingChild;
|
||||
averageZ[i++] = sortingRight;
|
||||
averageZ[j--] = sortingLeft;
|
||||
}
|
||||
} while (i <= j);
|
||||
if (l < j) {
|
||||
sortingStack[sortingStackIndex++] = l;
|
||||
sortingStack[sortingStackIndex++] = j;
|
||||
}
|
||||
if (i < r) {
|
||||
sortingStack[sortingStackIndex++] = i;
|
||||
sortingStack[sortingStackIndex++] = r;
|
||||
}
|
||||
}
|
||||
// Отрисовка
|
||||
for (i = numVisibleChildren - 1; i >= 0; i--) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class BSPTree extends ConflictContainer {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Canvas;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
import alternativa.engine3d.core.Object3DContainer;
|
||||
|
||||
import flash.geom.Vector3D;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class DirectionContainer extends Object3DContainer {
|
||||
|
||||
public var direction:Vector3D = new Vector3D(0, 0, -1);
|
||||
|
||||
override protected function drawVisibleChildren(camera:Camera3D, object:Object3D, canvas:Canvas):void {
|
||||
var i:int;
|
||||
var child:Object3D;
|
||||
if (Vector3D.Z_AXIS.dotProduct(object.cameraMatrix.deltaTransformVector(direction)) < 0) {
|
||||
for (i = 0; i < numVisibleChildren; i++) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
} else {
|
||||
for (i = numVisibleChildren - 1; i >= 0; i--) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,826 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
import alternativa.engine3d.core.BoundBox;
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Canvas;
|
||||
import alternativa.engine3d.core.Debug;
|
||||
import alternativa.engine3d.core.Geometry;
|
||||
import alternativa.engine3d.core.Node;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
import alternativa.engine3d.objects.Occluder;
|
||||
import alternativa.engine3d.objects.Reference;
|
||||
|
||||
import flash.geom.Utils3D;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Контейнер, дочерние объекты которого помещены в бинарную древовидную структуру.
|
||||
* Для построения дерева нужно добавить статические дочерние объекты
|
||||
* с помощью addStaticChild(), затем вызвать createTree(). По баундам статических объектов
|
||||
* построится ориентированная по осям бинарная древовидная структура (KD - частный случай BSP).
|
||||
* Динамические объекты, можно в любое время добавлять addDynamicChild() и удалять removeDynamicChild().
|
||||
* Объекты, добавленные с помощью addChild() будут отрисовываться поверх всего в порядке добавления.
|
||||
*/
|
||||
public class KDTree extends ConflictContainer {
|
||||
|
||||
public var debugAlphaFade:Number = 0.8;
|
||||
|
||||
private var rootNode:Node;
|
||||
|
||||
override alternativa3d function get canDraw():Boolean {
|
||||
return _numChildren > 0 || rootNode != null;
|
||||
}
|
||||
|
||||
override alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
||||
// Если есть корневая нода
|
||||
if (rootNode != null) {
|
||||
// Расчёт инверсной матрицы камеры и позицци камеры в контейнере
|
||||
calculateInverseCameraMatrix(object.cameraMatrix);
|
||||
// Расчёт плоскостей камеры в контейнере
|
||||
calculateCameraPlanes(camera);
|
||||
// Проверка на видимость рутовой ноды
|
||||
var culling:int = cullingInContainer(camera, rootNode.boundBox, object.culling);
|
||||
if (culling >= 0) {
|
||||
// Подготовка канваса
|
||||
var canvas:Canvas = parentCanvas.getChildCanvas(false, true, object.alpha, object.blendMode, object.colorTransform, object.filters);
|
||||
canvas.numDraws = 0;
|
||||
// Окклюдеры
|
||||
numOccluders = 0;
|
||||
if (camera.numOccluders > 0) {
|
||||
updateOccluders(camera);
|
||||
}
|
||||
// Сбор видимой геометрии
|
||||
var geometry:Geometry = getGeometry(camera, object);
|
||||
var current:Geometry = geometry;
|
||||
while (current != null) {
|
||||
current.vertices.length = current.verticesLength;
|
||||
inverseCameraMatrix.transformVectors(current.vertices, current.vertices);
|
||||
current.calculateAABB();
|
||||
current = current.next;
|
||||
}
|
||||
// Отрисовка дерева
|
||||
drawNode(rootNode, culling, camera, object, canvas, geometry);
|
||||
// Если была отрисовка
|
||||
if (canvas.numDraws > 0) {
|
||||
canvas.removeChildren(canvas.numDraws);
|
||||
} else {
|
||||
parentCanvas.numDraws--;
|
||||
}
|
||||
} else {
|
||||
super.draw(camera, object, parentCanvas);
|
||||
}
|
||||
} else {
|
||||
super.draw(camera, object, parentCanvas);
|
||||
}
|
||||
}
|
||||
|
||||
override alternativa3d function debug(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
||||
var debugResult:int = camera.checkInDebug(this);
|
||||
if (debugResult == 0) return;
|
||||
var canvas:Canvas = parentCanvas.getChildCanvas(true, false);
|
||||
// Ноды
|
||||
if (debugResult & Debug.NODES) {
|
||||
if (rootNode != null) {
|
||||
var culling:int = cullingInContainer(camera, rootNode.boundBox, object.culling);
|
||||
if (culling >= 0) {
|
||||
debugNode(rootNode, culling, camera, object, canvas, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Оси, центры, имена, баунды
|
||||
if (debugResult & Debug.AXES) object.drawAxes(camera, canvas);
|
||||
if (debugResult & Debug.CENTERS) object.drawCenter(camera, canvas);
|
||||
if (debugResult & Debug.NAMES) object.drawName(camera, canvas);
|
||||
if (debugResult & Debug.BOUNDS) object.drawBoundBox(camera, canvas);
|
||||
}
|
||||
|
||||
// Отрисовка ноды
|
||||
private function drawNode(node:Node, culling:int, camera:Camera3D, object:Object3D, canvas:Canvas, geometry:Geometry):void {
|
||||
var i:int;
|
||||
var next:Geometry;
|
||||
var negative:Geometry;
|
||||
var middle:Geometry;
|
||||
var positive:Geometry;
|
||||
var negativePart:Geometry;
|
||||
var positivePart:Geometry;
|
||||
if (camera.occludedAll) {
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
geometry.destroy();
|
||||
geometry = next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var nodeObjects:Vector.<Object3D> = node.objects;
|
||||
var nodeNumObjects:int = node.numObjects;
|
||||
var nodeNumNonOccluders:int = node.numNonOccluders;
|
||||
var staticChild:Object3D;
|
||||
// Узловая нода
|
||||
if (node.negative != null) {
|
||||
var negativeCulling:int = (culling > 0 || numOccluders > 0) ? cullingInContainer(camera, node.negative.boundBox, culling) : 0;
|
||||
var positiveCulling:int = (culling > 0 || numOccluders > 0) ? cullingInContainer(camera, node.positive.boundBox, culling) : 0;
|
||||
var axisX:Boolean = node.normalX != 0;
|
||||
var axisY:Boolean = node.normalY != 0;
|
||||
var min:Number;
|
||||
var max:Number;
|
||||
// Если видны обе дочерние ноды
|
||||
if (negativeCulling >= 0 && positiveCulling >= 0) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
min = axisX ? geometry.minX : (axisY ? geometry.minY : geometry.minZ);
|
||||
max = axisX ? geometry.maxX : (axisY ? geometry.maxY : geometry.maxZ);
|
||||
if (max <= node.offsetMax) {
|
||||
if (min < node.offsetMin) {
|
||||
geometry.next = negative;
|
||||
negative = geometry;
|
||||
} else {
|
||||
geometry.next = middle;
|
||||
middle = geometry;
|
||||
}
|
||||
} else {
|
||||
if (min >= node.offsetMin) {
|
||||
geometry.next = positive;
|
||||
positive = geometry;
|
||||
} else {
|
||||
negativePart = geometry.create();
|
||||
positivePart = geometry.create();
|
||||
geometry.split(axisX, axisY, node.offset, threshold, negativePart, positivePart);
|
||||
geometry.destroy();
|
||||
// Если негативный не пустой
|
||||
if (negativePart.fragment != null) {
|
||||
negativePart.next = negative;
|
||||
negative = negativePart;
|
||||
} else {
|
||||
negativePart.destroy();
|
||||
}
|
||||
// Если позитивный не пустой
|
||||
if (positivePart.fragment != null) {
|
||||
positivePart.next = positive;
|
||||
positive = positivePart;
|
||||
} else {
|
||||
positivePart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Отрисовка дочерних нод и объектов в плоскости
|
||||
if (axisX && cameraX > node.offset || axisY && cameraY > node.offset || !axisX && !axisY && cameraZ > node.offset) {
|
||||
// Отрисовка позитивной ноды
|
||||
drawNode(node.positive, positiveCulling, camera, object, canvas, positive);
|
||||
// Отрисовка динамических объектов в ноде
|
||||
while (middle != null) {
|
||||
next = middle.next;
|
||||
// Проверка с окклюдерами и отрисовка
|
||||
if (middle.numOccluders >= numOccluders || !occludeGeometry(camera, middle)) {
|
||||
if (camera.debugMode) middle.debug(camera, object, canvas, threshold, 1, object.cameraMatrix);
|
||||
middle.draw(camera, canvas, threshold, object.cameraMatrix);
|
||||
}
|
||||
middle.destroy();
|
||||
middle = next;
|
||||
}
|
||||
// Отрисовка плоских статических объектов в ноде
|
||||
for (i = 0; i < nodeNumObjects; i++) {
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw && ((staticChild.culling = culling) == 0 && numOccluders == 0 || (staticChild.culling = cullingInContainer(camera, node.bounds[i], culling)) >= 0)) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
if (camera.debugMode) staticChild.debug(camera, staticChild, canvas);
|
||||
staticChild.draw(camera, staticChild, canvas);
|
||||
}
|
||||
}
|
||||
// Обновление окклюдеров
|
||||
if (nodeNumObjects > nodeNumNonOccluders) {
|
||||
updateOccluders(camera);
|
||||
}
|
||||
// Отрисовка негативной ноды
|
||||
drawNode(node.negative, negativeCulling, camera, object, canvas, negative);
|
||||
} else {
|
||||
// Отрисовка негативной ноды
|
||||
drawNode(node.negative, negativeCulling, camera, object, canvas, negative);
|
||||
// Отрисовка динамических объектов в ноде
|
||||
while (middle != null) {
|
||||
next = middle.next;
|
||||
// Проверка с окклюдерами и отрисовка
|
||||
if (middle.numOccluders >= numOccluders || !occludeGeometry(camera, middle)) {
|
||||
if (camera.debugMode) middle.debug(camera, object, canvas, threshold, 1, object.cameraMatrix);
|
||||
middle.draw(camera, canvas, threshold, object.cameraMatrix);
|
||||
}
|
||||
middle.destroy();
|
||||
middle = next;
|
||||
}
|
||||
// Отрисовка статических объектов в ноде
|
||||
for (i = 0; i < nodeNumObjects; i++) {
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw && ((staticChild.culling = culling) == 0 && numOccluders == 0 || (staticChild.culling = cullingInContainer(camera, node.bounds[i], culling)) >= 0)) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
if (camera.debugMode) staticChild.debug(camera, staticChild, canvas);
|
||||
staticChild.draw(camera, staticChild, canvas);
|
||||
}
|
||||
}
|
||||
// Обновление окклюдеров
|
||||
if (nodeNumObjects > nodeNumNonOccluders) {
|
||||
updateOccluders(camera);
|
||||
}
|
||||
// Отрисовка позитивной ноды
|
||||
drawNode(node.positive, positiveCulling, camera, object, canvas, positive);
|
||||
}
|
||||
// Если видна только негативная
|
||||
} else if (negativeCulling >= 0) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
min = axisX ? geometry.minX : (axisY ? geometry.minY : geometry.minZ);
|
||||
max = axisX ? geometry.maxX : (axisY ? geometry.maxY : geometry.maxZ);
|
||||
if (max <= node.offsetMax) {
|
||||
geometry.next = negative;
|
||||
negative = geometry;
|
||||
} else if (min < node.offsetMin) {
|
||||
negativePart = geometry.create();
|
||||
geometry.split(axisX, axisY, node.offset, threshold, negativePart, null);
|
||||
geometry.destroy();
|
||||
// Если негативный не пустой
|
||||
if (negativePart.fragment != null) {
|
||||
negativePart.next = negative;
|
||||
negative = negativePart;
|
||||
} else {
|
||||
negativePart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Отрисовка негативной ноды
|
||||
drawNode(node.negative, negativeCulling, camera, object, canvas, negative);
|
||||
// Если видна только позитивная
|
||||
} else if (positiveCulling >= 0) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
min = axisX ? geometry.minX : (axisY ? geometry.minY : geometry.minZ);
|
||||
max = axisX ? geometry.maxX : (axisY ? geometry.maxY : geometry.maxZ);
|
||||
if (min >= node.offsetMin) {
|
||||
geometry.next = positive;
|
||||
positive = geometry;
|
||||
} else if (max > node.offsetMax) {
|
||||
positivePart = geometry.create();
|
||||
geometry.split(axisX, axisY, node.offset, threshold, null, positivePart);
|
||||
geometry.destroy();
|
||||
// Если позитивный не пустой
|
||||
if (positivePart.fragment != null) {
|
||||
positivePart.next = positive;
|
||||
positive = positivePart;
|
||||
} else {
|
||||
positivePart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Отрисовка позитивной ноды
|
||||
drawNode(node.positive, positiveCulling, camera, object, canvas, positive);
|
||||
}
|
||||
// Конечная нода
|
||||
} else {
|
||||
// Если есть статические объекты, не считая окклюдеры
|
||||
if (nodeNumNonOccluders > 0) {
|
||||
// Если есть конфликт
|
||||
if (nodeNumNonOccluders > 1 || geometry != null) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
geometry.next = middle;
|
||||
middle = geometry;
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Превращение статиков в геометрию
|
||||
for (i = 0; i < nodeNumNonOccluders; i++) {
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw && ((staticChild.culling = culling) == 0 && numOccluders == 0 || (staticChild.culling = cullingInContainer(camera, node.bounds[i], culling)) >= 0)) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
geometry = staticChild.getGeometry(camera, staticChild);
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
geometry.next = middle;
|
||||
middle = geometry;
|
||||
geometry = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Разруливаем конфликт
|
||||
if (middle != null) {
|
||||
if (middle.next != null) {
|
||||
drawConflictGeometry(camera, object, canvas, middle);
|
||||
} else {
|
||||
if (camera.debugMode) middle.debug(camera, object, canvas, threshold, 1);
|
||||
middle.draw(camera, canvas, threshold);
|
||||
middle.destroy();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Если только один статик
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
staticChild.culling = culling;
|
||||
if (camera.debugMode) staticChild.debug(camera, staticChild, canvas);
|
||||
staticChild.draw(camera, staticChild, canvas);
|
||||
}
|
||||
}
|
||||
// Если нет статических объектов
|
||||
} else {
|
||||
// Если есть динамические объекты
|
||||
if (geometry != null) {
|
||||
// Если динамических объектов несколько
|
||||
if (geometry.next != null) {
|
||||
// Если есть окклюдеры
|
||||
if (numOccluders > 0) {
|
||||
// Перебор динамиков
|
||||
while (geometry != null) {
|
||||
next = geometry.next;
|
||||
// Проверка с окклюдерами
|
||||
if (geometry.numOccluders < numOccluders && occludeGeometry(camera, geometry)) {
|
||||
geometry.destroy();
|
||||
} else {
|
||||
geometry.next = middle;
|
||||
middle = geometry;
|
||||
}
|
||||
geometry = next;
|
||||
}
|
||||
// Если остались объекты
|
||||
if (middle != null) {
|
||||
if (middle.next != null) {
|
||||
// Разруливание
|
||||
if (resolveByAABB) {
|
||||
drawAABBGeometry(camera, object, canvas, middle);
|
||||
} else if (resolveByOOBB) {
|
||||
geometry = middle;
|
||||
while (geometry != null) {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
if (!geometry.viewAligned) {
|
||||
geometry.calculateOOBB();
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
drawOOBBGeometry(camera, object, canvas, middle);
|
||||
} else {
|
||||
geometry = middle;
|
||||
while (geometry != null) {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
geometry = geometry.next;
|
||||
}
|
||||
drawConflictGeometry(camera, object, canvas, middle);
|
||||
}
|
||||
} else {
|
||||
if (camera.debugMode) middle.debug(camera, object, canvas, threshold, 1, object.cameraMatrix);
|
||||
middle.draw(camera, canvas, threshold, object.cameraMatrix);
|
||||
middle.destroy();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Разруливание
|
||||
middle = geometry;
|
||||
if (resolveByAABB) {
|
||||
drawAABBGeometry(camera, object, canvas, middle);
|
||||
} else if (resolveByOOBB) {
|
||||
geometry = middle;
|
||||
while (geometry != null) {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
if (!geometry.viewAligned) {
|
||||
geometry.calculateOOBB();
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
drawOOBBGeometry(camera, object, canvas, middle);
|
||||
} else {
|
||||
geometry = middle;
|
||||
while (geometry != null) {
|
||||
geometry.vertices.length = geometry.verticesLength;
|
||||
object.cameraMatrix.transformVectors(geometry.vertices, geometry.vertices);
|
||||
geometry = geometry.next;
|
||||
}
|
||||
drawConflictGeometry(camera, object, canvas, middle);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Проверка с окклюдерами и отрисовка
|
||||
if (geometry.numOccluders >= numOccluders || !occludeGeometry(camera, geometry)) {
|
||||
if (camera.debugMode) geometry.debug(camera, object, canvas, threshold, 1, object.cameraMatrix);
|
||||
geometry.draw(camera, canvas, threshold, object.cameraMatrix);
|
||||
}
|
||||
geometry.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Если в ноде есть окклюдеры
|
||||
if (nodeNumObjects > nodeNumNonOccluders) {
|
||||
for (i = nodeNumNonOccluders; i < nodeNumObjects; i++) {
|
||||
staticChild = nodeObjects[i];
|
||||
if (staticChild.visible && staticChild.canDraw && ((staticChild.culling = culling) == 0 && numOccluders == 0 || (staticChild.culling = cullingInContainer(camera, node.bounds[i], culling)) >= 0)) {
|
||||
staticChild.cameraMatrix.identity();
|
||||
staticChild.cameraMatrix.prepend(object.cameraMatrix);
|
||||
staticChild.cameraMatrix.prepend(staticChild.matrix);
|
||||
if (camera.debugMode) staticChild.debug(camera, staticChild, canvas);
|
||||
staticChild.draw(camera, staticChild, canvas);
|
||||
}
|
||||
}
|
||||
// Обновление окклюдеров
|
||||
updateOccluders(camera);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private const nodeVertices:Vector.<Number> = new Vector.<Number>(12, true);
|
||||
static private const nodeProjectedVertices:Vector.<Number> = new Vector.<Number>(8, true);
|
||||
static private const nodeUVTs:Vector.<Number> = new Vector.<Number>(12, true);
|
||||
|
||||
private function debugNode(node:Node, culling:int, camera:Camera3D, object:Object3D, canvas:Canvas, alpha:Number):void {
|
||||
if (node.negative != null) {
|
||||
var negativeCulling:int = (culling > 0) ? cullingInContainer(camera, node.negative.boundBox, culling) : 0;
|
||||
var positiveCulling:int = (culling > 0) ? cullingInContainer(camera, node.positive.boundBox, culling) : 0;
|
||||
if (negativeCulling >= 0) {
|
||||
debugNode(node.negative, negativeCulling, camera, object, canvas, alpha*debugAlphaFade);
|
||||
}
|
||||
if (positiveCulling >= 0) {
|
||||
debugNode(node.positive, positiveCulling, camera, object, canvas, alpha*debugAlphaFade);
|
||||
}
|
||||
|
||||
if (node.normalX) {
|
||||
nodeVertices[0] = node.offset;
|
||||
nodeVertices[1] = node.boundBox.minY;
|
||||
nodeVertices[2] = node.boundBox.maxZ;
|
||||
|
||||
nodeVertices[3] = node.offset;
|
||||
nodeVertices[4] = node.boundBox.maxY;
|
||||
nodeVertices[5] = node.boundBox.maxZ;
|
||||
|
||||
nodeVertices[6] = node.offset;
|
||||
nodeVertices[7] = node.boundBox.maxY;
|
||||
nodeVertices[8] = node.boundBox.minZ;
|
||||
|
||||
nodeVertices[9] = node.offset;
|
||||
nodeVertices[10] = node.boundBox.minY;
|
||||
nodeVertices[11] = node.boundBox.minZ;
|
||||
} else if (node.normalY) {
|
||||
nodeVertices[0] = node.boundBox.maxX;
|
||||
nodeVertices[1] = node.offset;
|
||||
nodeVertices[2] = node.boundBox.maxZ;
|
||||
|
||||
nodeVertices[3] = node.boundBox.minX;
|
||||
nodeVertices[4] = node.offset;
|
||||
nodeVertices[5] = node.boundBox.maxZ;
|
||||
|
||||
nodeVertices[6] = node.boundBox.minX;
|
||||
nodeVertices[7] = node.offset;
|
||||
nodeVertices[8] = node.boundBox.minZ;
|
||||
|
||||
nodeVertices[9] = node.boundBox.maxX;
|
||||
nodeVertices[10] = node.offset;
|
||||
nodeVertices[11] = node.boundBox.minZ;
|
||||
} else {
|
||||
nodeVertices[0] = node.boundBox.minX;
|
||||
nodeVertices[1] = node.boundBox.minY;
|
||||
nodeVertices[2] = node.offset;
|
||||
|
||||
nodeVertices[3] = node.boundBox.maxX;
|
||||
nodeVertices[4] = node.boundBox.minY;
|
||||
nodeVertices[5] = node.offset;
|
||||
|
||||
nodeVertices[6] = node.boundBox.maxX;
|
||||
nodeVertices[7] = node.boundBox.maxY;
|
||||
nodeVertices[8] = node.offset;
|
||||
|
||||
nodeVertices[9] = node.boundBox.minX;
|
||||
nodeVertices[10] = node.boundBox.maxY;
|
||||
nodeVertices[11] = node.offset;
|
||||
}
|
||||
object.cameraMatrix.transformVectors(nodeVertices, nodeVertices);
|
||||
var i:int;
|
||||
for (i = 0; i < 12; i += 3) {
|
||||
if (nodeVertices[int(i + 2)] <= 0) break;
|
||||
}
|
||||
if (i == 12) {
|
||||
Utils3D.projectVectors(camera.projectionMatrix, nodeVertices, nodeProjectedVertices, nodeUVTs);
|
||||
canvas.gfx.lineStyle(0, node.normalX ? 0xFF0000 : (node.normalY ? 0x00FF00 : 0x0000FF));
|
||||
canvas.gfx.moveTo(nodeProjectedVertices[0], nodeProjectedVertices[1]);
|
||||
canvas.gfx.lineTo(nodeProjectedVertices[2], nodeProjectedVertices[3]);
|
||||
canvas.gfx.lineTo(nodeProjectedVertices[4], nodeProjectedVertices[5]);
|
||||
canvas.gfx.lineTo(nodeProjectedVertices[6], nodeProjectedVertices[7]);
|
||||
canvas.gfx.lineTo(nodeProjectedVertices[0], nodeProjectedVertices[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function createTree(staticObjects:Vector.<Object3D>, boundBox:BoundBox = null):void {
|
||||
var numStaticChildren:int = staticObjects.length;
|
||||
if (numStaticChildren > 0) {
|
||||
// Создаём корневую ноду
|
||||
rootNode = new Node();
|
||||
rootNode.objects = new Vector.<Object3D>();
|
||||
rootNode.bounds = new Vector.<BoundBox>();
|
||||
rootNode.numObjects = 0;
|
||||
// Расчитываем баунды объектов и рутовой ноды
|
||||
rootNode.boundBox = (boundBox != null) ? boundBox : new BoundBox();
|
||||
// Сначала добавляем не окклюдеры
|
||||
var staticOccluders:Vector.<Object3D> = new Vector.<Object3D>();
|
||||
var staticOccludersLength:int = 0;
|
||||
var object:Object3D;
|
||||
var objectBoundBox:BoundBox;
|
||||
for (var i:int = 0; i < numStaticChildren; i++) {
|
||||
object = staticObjects[i];
|
||||
// Поиск оригинального объекта
|
||||
var source:Object3D = object;
|
||||
while (source is Reference) {
|
||||
source = (source as Reference).referenceObject;
|
||||
}
|
||||
// Если окклюдер
|
||||
if (source is Occluder) {
|
||||
staticOccluders[staticOccludersLength++] = object;
|
||||
} else {
|
||||
objectBoundBox = object.calculateBoundBox(object.matrix);
|
||||
rootNode.objects[rootNode.numObjects] = object;
|
||||
rootNode.bounds[rootNode.numObjects++] = objectBoundBox;
|
||||
rootNode.boundBox.addBoundBox(objectBoundBox);
|
||||
}
|
||||
}
|
||||
// Добавляем окклюдеры
|
||||
for (i = 0; i < staticOccludersLength; i++) {
|
||||
object = staticOccluders[i];
|
||||
objectBoundBox = object.calculateBoundBox(object.matrix);
|
||||
rootNode.objects[rootNode.numObjects] = object;
|
||||
rootNode.bounds[rootNode.numObjects++] = objectBoundBox;
|
||||
rootNode.boundBox.addBoundBox(objectBoundBox);
|
||||
}
|
||||
// Разделяем рутовую ноду
|
||||
splitNode(rootNode);
|
||||
}
|
||||
}
|
||||
|
||||
private var splitAxis:int;
|
||||
private var splitCoord:Number;
|
||||
private var splitCost:Number;
|
||||
static private const nodeBoundBoxThreshold:BoundBox = new BoundBox();
|
||||
static private const splitCoordsX:Vector.<Number> = new Vector.<Number>();
|
||||
static private const splitCoordsY:Vector.<Number> = new Vector.<Number>();
|
||||
static private const splitCoordsZ:Vector.<Number> = new Vector.<Number>();
|
||||
private function splitNode(node:Node):void {
|
||||
|
||||
var object:Object3D, boundBox:BoundBox, i:int, j:int, k:int, c1:Number, c2:Number, coordMin:Number, coordMax:Number, area:Number, areaNegative:Number, areaPositive:Number, numNegative:int, numPositive:int, conflict:Boolean, cost:Number;
|
||||
var nodeBoundBox:BoundBox = node.boundBox;
|
||||
|
||||
// Подготовка баунда с погрешностями
|
||||
nodeBoundBoxThreshold.minX = nodeBoundBox.minX + threshold;
|
||||
nodeBoundBoxThreshold.minY = nodeBoundBox.minY + threshold;
|
||||
nodeBoundBoxThreshold.minZ = nodeBoundBox.minZ + threshold;
|
||||
nodeBoundBoxThreshold.maxX = nodeBoundBox.maxX - threshold;
|
||||
nodeBoundBoxThreshold.maxY = nodeBoundBox.maxY - threshold;
|
||||
nodeBoundBoxThreshold.maxZ = nodeBoundBox.maxZ - threshold;
|
||||
var doubleThreshold:Number = threshold + threshold;
|
||||
|
||||
// Собираем опорные координаты
|
||||
var numSplitCoordsX:int = 0, numSplitCoordsY:int = 0, numSplitCoordsZ:int = 0;
|
||||
for (i = 0; i < node.numObjects; i++) {
|
||||
boundBox = node.bounds[i];
|
||||
if (boundBox.maxX - boundBox.minX <= doubleThreshold) {
|
||||
if (boundBox.minX <= nodeBoundBoxThreshold.minX) splitCoordsX[numSplitCoordsX++] = nodeBoundBox.minX;
|
||||
else if (boundBox.maxX >= nodeBoundBoxThreshold.maxX) splitCoordsX[numSplitCoordsX++] = nodeBoundBox.maxX;
|
||||
else splitCoordsX[numSplitCoordsX++] = (boundBox.minX + boundBox.maxX)*0.5;
|
||||
} else {
|
||||
if (boundBox.minX > nodeBoundBoxThreshold.minX) splitCoordsX[numSplitCoordsX++] = boundBox.minX;
|
||||
if (boundBox.maxX < nodeBoundBoxThreshold.maxX) splitCoordsX[numSplitCoordsX++] = boundBox.maxX;
|
||||
}
|
||||
if (boundBox.maxY - boundBox.minY <= doubleThreshold) {
|
||||
if (boundBox.minY <= nodeBoundBoxThreshold.minY) splitCoordsY[numSplitCoordsY++] = nodeBoundBox.minY;
|
||||
else if (boundBox.maxY >= nodeBoundBoxThreshold.maxY) splitCoordsY[numSplitCoordsY++] = nodeBoundBox.maxY;
|
||||
else splitCoordsY[numSplitCoordsY++] = (boundBox.minY + boundBox.maxY)*0.5;
|
||||
} else {
|
||||
if (boundBox.minY > nodeBoundBoxThreshold.minY) splitCoordsY[numSplitCoordsY++] = boundBox.minY;
|
||||
if (boundBox.maxY < nodeBoundBoxThreshold.maxY) splitCoordsY[numSplitCoordsY++] = boundBox.maxY;
|
||||
}
|
||||
if (boundBox.maxZ - boundBox.minZ <= doubleThreshold) {
|
||||
if (boundBox.minZ <= nodeBoundBoxThreshold.minZ) splitCoordsZ[numSplitCoordsZ++] = nodeBoundBox.minZ;
|
||||
else if (boundBox.maxZ >= nodeBoundBoxThreshold.maxZ) splitCoordsZ[numSplitCoordsZ++] = nodeBoundBox.maxZ;
|
||||
else splitCoordsZ[numSplitCoordsZ++] = (boundBox.minZ + boundBox.maxZ)*0.5;
|
||||
} else {
|
||||
if (boundBox.minZ > nodeBoundBoxThreshold.minZ) splitCoordsZ[numSplitCoordsZ++] = boundBox.minZ;
|
||||
if (boundBox.maxZ < nodeBoundBoxThreshold.maxZ) splitCoordsZ[numSplitCoordsZ++] = boundBox.maxZ;
|
||||
}
|
||||
}
|
||||
|
||||
// Убираем дубликаты координат, ищем наилучший сплит
|
||||
splitAxis = -1; splitCost = Number.MAX_VALUE;
|
||||
i = 0; area = (nodeBoundBox.maxY - nodeBoundBox.minY)*(nodeBoundBox.maxZ - nodeBoundBox.minZ);
|
||||
while (i < numSplitCoordsX) {
|
||||
if (!isNaN(c1 = splitCoordsX[i++])) {
|
||||
coordMin = c1 - threshold;
|
||||
coordMax = c1 + threshold;
|
||||
areaNegative = area*(c1 - nodeBoundBox.minX);
|
||||
areaPositive = area*(nodeBoundBox.maxX - c1);
|
||||
numNegative = numPositive = 0;
|
||||
conflict = false;
|
||||
// Проверяем объекты
|
||||
for (j = 0; j < node.numObjects; j++) {
|
||||
boundBox = node.bounds[j];
|
||||
if (boundBox.maxX <= coordMax) {
|
||||
if (boundBox.minX < coordMin) numNegative++;
|
||||
} else {
|
||||
if (boundBox.minX >= coordMin) numPositive++; else {conflict = true; break;}
|
||||
}
|
||||
}
|
||||
// Если хороший сплит, сохраняем
|
||||
if (!conflict && (cost = areaNegative*numNegative + areaPositive*numPositive) < splitCost) {
|
||||
splitCost = cost;
|
||||
splitAxis = 0;
|
||||
splitCoord = c1;
|
||||
}
|
||||
j = i;
|
||||
while (++j < numSplitCoordsX) if ((c2 = splitCoordsX[j]) >= c1 - threshold && c2 <= c1 + threshold) splitCoordsX[j] = NaN;
|
||||
}
|
||||
}
|
||||
i = 0; area = (nodeBoundBox.maxX - nodeBoundBox.minX)*(nodeBoundBox.maxZ - nodeBoundBox.minZ);
|
||||
while (i < numSplitCoordsY) {
|
||||
if (!isNaN(c1 = splitCoordsY[i++])) {
|
||||
coordMin = c1 - threshold;
|
||||
coordMax = c1 + threshold;
|
||||
areaNegative = area*(c1 - nodeBoundBox.minY);
|
||||
areaPositive = area*(nodeBoundBox.maxY - c1);
|
||||
numNegative = numPositive = 0;
|
||||
conflict = false;
|
||||
// Проверяем объекты
|
||||
for (j = 0; j < node.numObjects; j++) {
|
||||
boundBox = node.bounds[j];
|
||||
if (boundBox.maxY <= coordMax) {
|
||||
if (boundBox.minY < coordMin) numNegative++;
|
||||
} else {
|
||||
if (boundBox.minY >= coordMin) numPositive++; else {conflict = true; break;}
|
||||
}
|
||||
}
|
||||
// Если хороший сплит, сохраняем
|
||||
if (!conflict && (cost = areaNegative*numNegative + areaPositive*numPositive) < splitCost) {
|
||||
splitCost = cost;
|
||||
splitAxis = 1;
|
||||
splitCoord = c1;
|
||||
}
|
||||
j = i;
|
||||
while (++j < numSplitCoordsY) if ((c2 = splitCoordsY[j]) >= c1 - threshold && c2 <= c1 + threshold) splitCoordsY[j] = NaN;
|
||||
}
|
||||
}
|
||||
i = 0; area = (nodeBoundBox.maxX - nodeBoundBox.minX)*(nodeBoundBox.maxY - nodeBoundBox.minY);
|
||||
while (i < numSplitCoordsZ) {
|
||||
if (!isNaN(c1 = splitCoordsZ[i++])) {
|
||||
coordMin = c1 - threshold;
|
||||
coordMax = c1 + threshold;
|
||||
areaNegative = area*(c1 - nodeBoundBox.minZ);
|
||||
areaPositive = area*(nodeBoundBox.maxZ - c1);
|
||||
numNegative = numPositive = 0;
|
||||
conflict = false;
|
||||
// Проверяем объекты
|
||||
for (j = 0; j < node.numObjects; j++) {
|
||||
boundBox = node.bounds[j];
|
||||
if (boundBox.maxZ <= coordMax) {
|
||||
if (boundBox.minZ < coordMin) numNegative++;
|
||||
} else {
|
||||
if (boundBox.minZ >= coordMin) numPositive++; else {conflict = true; break;}
|
||||
}
|
||||
}
|
||||
// Если хороший сплит, сохраняем
|
||||
if (!conflict && (cost = areaNegative*numNegative + areaPositive*numPositive) < splitCost) {
|
||||
splitCost = cost;
|
||||
splitAxis = 2;
|
||||
splitCoord = c1;
|
||||
}
|
||||
j = i;
|
||||
while (++j < numSplitCoordsZ) if ((c2 = splitCoordsZ[j]) >= c1 - threshold && c2 <= c1 + threshold) splitCoordsZ[j] = NaN;
|
||||
}
|
||||
}
|
||||
|
||||
// Если сплит не найден, выходим
|
||||
if (splitAxis < 0) {
|
||||
// Находим, откуда начинаются окклюдеры
|
||||
for (i = 0; i < node.numObjects; i++) {
|
||||
object = node.objects[i];
|
||||
// Поиск оригинального объекта
|
||||
while (object is Reference) object = (object as Reference).referenceObject;
|
||||
if (object is Occluder) break;
|
||||
}
|
||||
node.numNonOccluders = i;
|
||||
return;
|
||||
}
|
||||
|
||||
// Разделяем ноду
|
||||
if (splitAxis == 0) {
|
||||
node.normalX = 1;
|
||||
node.normalY = 0;
|
||||
node.normalZ = 0;
|
||||
} else if (splitAxis == 1) {
|
||||
node.normalX = 0;
|
||||
node.normalY = 1;
|
||||
node.normalZ = 0;
|
||||
} else {
|
||||
node.normalX = 0;
|
||||
node.normalY = 0;
|
||||
node.normalZ = 1;
|
||||
}
|
||||
node.offset = splitCoord;
|
||||
node.offsetMin = splitCoord - threshold;
|
||||
node.offsetMax = splitCoord + threshold;
|
||||
|
||||
// Создаём дочерние ноды
|
||||
node.negative = new Node();
|
||||
node.positive = new Node();
|
||||
node.negative.boundBox = nodeBoundBox.clone();
|
||||
node.positive.boundBox = nodeBoundBox.clone();
|
||||
node.negative.numObjects = 0;
|
||||
node.positive.numObjects = 0;
|
||||
if (node.normalX) {
|
||||
node.negative.boundBox.maxX = node.positive.boundBox.minX = splitCoord;
|
||||
} else if (node.normalY) {
|
||||
node.negative.boundBox.maxY = node.positive.boundBox.minY = splitCoord;
|
||||
} else {
|
||||
node.negative.boundBox.maxZ = node.positive.boundBox.minZ = splitCoord;
|
||||
}
|
||||
// Распределяем объекты по дочерним нодам
|
||||
for (i = 0; i < node.numObjects; i++) {
|
||||
object = node.objects[i];
|
||||
boundBox = node.bounds[i];
|
||||
var min:Number = node.normalX ? boundBox.minX : (node.normalY ? boundBox.minY : boundBox.minZ);
|
||||
var max:Number = node.normalX ? boundBox.maxX : (node.normalY ? boundBox.maxY : boundBox.maxZ);
|
||||
if (max <= node.offsetMax) {
|
||||
if (min < node.offsetMin) {
|
||||
// Объект в негативной стороне
|
||||
if (node.negative.objects == null) node.negative.objects = new Vector.<Object3D>(), node.negative.bounds = new Vector.<BoundBox>();
|
||||
node.negative.objects[node.negative.numObjects] = object, node.negative.bounds[node.negative.numObjects++] = boundBox;
|
||||
node.objects[i] = null, node.bounds[i] = null;
|
||||
} else {
|
||||
// Остаётся в ноде
|
||||
}
|
||||
} else {
|
||||
if (min >= node.offsetMin) {
|
||||
// Объект в положительной стороне
|
||||
if (node.positive.objects == null) node.positive.objects = new Vector.<Object3D>(), node.positive.bounds = new Vector.<BoundBox>();
|
||||
node.positive.objects[node.positive.numObjects] = object, node.positive.bounds[node.positive.numObjects++] = boundBox;
|
||||
node.objects[i] = null, node.bounds[i] = null;
|
||||
} else {
|
||||
// Распилился
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Очистка списка объектов
|
||||
for (i = 0, j = 0; i < node.numObjects; i++) if (node.objects[i] != null) node.objects[j] = node.objects[i], node.bounds[j++] = node.bounds[i];
|
||||
if (j > 0) {
|
||||
node.numObjects = node.objects.length = node.bounds.length = j;
|
||||
// Находим, откуда начинаются окклюдеры
|
||||
for (i = 0; i < node.numObjects; i++) {
|
||||
object = node.objects[i];
|
||||
// Поиск оригинального объекта
|
||||
while (object is Reference) object = (object as Reference).referenceObject;
|
||||
if (object is Occluder) break;
|
||||
}
|
||||
node.numNonOccluders = i;
|
||||
} else {
|
||||
node.numObjects = node.numNonOccluders = 0, node.objects = null, node.bounds = null;
|
||||
}
|
||||
|
||||
// Разделение дочерних нод
|
||||
if (node.negative.objects != null) splitNode(node.negative);
|
||||
if (node.positive.objects != null) splitNode(node.positive);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.core.Object3DContainer;
|
||||
import alternativa.engine3d.objects.Mesh;
|
||||
|
||||
import flash.display.BitmapData;
|
||||
|
||||
public class SkyBox extends Object3DContainer {
|
||||
|
||||
private var backPlane:Mesh;
|
||||
private var frontPlane:Mesh;
|
||||
private var topPlane:Mesh;
|
||||
private var bottomPlane:Mesh;
|
||||
private var leftPlane:Mesh;
|
||||
private var rightPlane:Mesh;
|
||||
|
||||
public function SkyBox(size:Number = 1000):void {
|
||||
backPlane = new Mesh();
|
||||
frontPlane = new Mesh();
|
||||
topPlane = new Mesh();
|
||||
bottomPlane = new Mesh();
|
||||
leftPlane = new Mesh();
|
||||
rightPlane = new Mesh();
|
||||
|
||||
backPlane.clipping = 2;
|
||||
frontPlane.clipping = 2;
|
||||
topPlane.clipping = 2;
|
||||
bottomPlane.clipping = 2;
|
||||
leftPlane.clipping = 2;
|
||||
rightPlane.clipping = 2;
|
||||
|
||||
backPlane.vertices = Vector.<Number>([
|
||||
-size, -size, -size,
|
||||
-size, -size, size,
|
||||
size, -size, size,
|
||||
size, -size, -size,
|
||||
]);
|
||||
frontPlane.vertices = Vector.<Number>([
|
||||
size, size, -size,
|
||||
size, size, size,
|
||||
-size, size, size,
|
||||
-size, size, -size,
|
||||
]);
|
||||
topPlane.vertices = Vector.<Number>([
|
||||
size, size, size,
|
||||
size, -size, size,
|
||||
-size, -size, size,
|
||||
-size, size, size,
|
||||
]);
|
||||
bottomPlane.vertices = Vector.<Number>([
|
||||
size, -size, -size,
|
||||
size, size, -size,
|
||||
-size, size, -size,
|
||||
-size, -size, -size,
|
||||
]);
|
||||
leftPlane.vertices = Vector.<Number>([
|
||||
-size, size, -size,
|
||||
-size, size, size,
|
||||
-size, -size, size,
|
||||
-size, -size, -size,
|
||||
]);
|
||||
rightPlane.vertices = Vector.<Number>([
|
||||
size, -size, -size,
|
||||
size, -size, size,
|
||||
size, size, size,
|
||||
size, size, -size,
|
||||
]);
|
||||
|
||||
var uvts:Vector.<Number> = Vector.<Number>([1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0]);
|
||||
backPlane.uvts = uvts;
|
||||
frontPlane.uvts = uvts;
|
||||
topPlane.uvts = uvts;
|
||||
bottomPlane.uvts = uvts;
|
||||
leftPlane.uvts = uvts;
|
||||
rightPlane.uvts = uvts;
|
||||
|
||||
var indices:Vector.<int> = Vector.<int>([4, 0, 1, 2, 3]);
|
||||
backPlane.indices = indices;
|
||||
frontPlane.indices = indices;
|
||||
topPlane.indices = indices;
|
||||
bottomPlane.indices = indices;
|
||||
leftPlane.indices = indices;
|
||||
rightPlane.indices = indices;
|
||||
|
||||
backPlane.numVertices = 4;
|
||||
frontPlane.numVertices = 4;
|
||||
topPlane.numVertices = 4;
|
||||
bottomPlane.numVertices = 4;
|
||||
leftPlane.numVertices = 4;
|
||||
rightPlane.numVertices = 4;
|
||||
|
||||
backPlane.numFaces = 1;
|
||||
frontPlane.numFaces = 1;
|
||||
topPlane.numFaces = 1;
|
||||
bottomPlane.numFaces = 1;
|
||||
leftPlane.numFaces = 1;
|
||||
rightPlane.numFaces = 1;
|
||||
|
||||
backPlane.poly = true;
|
||||
frontPlane.poly = true;
|
||||
topPlane.poly = true;
|
||||
bottomPlane.poly = true;
|
||||
leftPlane.poly = true;
|
||||
rightPlane.poly = true;
|
||||
|
||||
addChild(backPlane);
|
||||
addChild(frontPlane);
|
||||
addChild(topPlane);
|
||||
addChild(bottomPlane);
|
||||
addChild(leftPlane);
|
||||
addChild(rightPlane);
|
||||
}
|
||||
|
||||
public function set backTexture(value:BitmapData):void {
|
||||
backPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set frontTexture(value:BitmapData):void {
|
||||
frontPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set topTexture(value:BitmapData):void {
|
||||
topPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set bottomTexture(value:BitmapData):void {
|
||||
bottomPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set leftTexture(value:BitmapData):void {
|
||||
leftPlane.texture = value;
|
||||
}
|
||||
|
||||
public function set rightTexture(value:BitmapData):void {
|
||||
rightPlane.texture = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package alternativa.engine3d.containers {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Canvas;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
import alternativa.engine3d.core.Object3DContainer;
|
||||
|
||||
import flash.geom.Matrix3D;
|
||||
import flash.geom.Vector3D;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class SplitContainer extends Object3DContainer {
|
||||
|
||||
public var splitPlane:Vector3D = new Vector3D(0, 0, 1, 0);
|
||||
static private const invertCameraMatrix:Matrix3D = new Matrix3D();
|
||||
static private const cameraPosition:Vector.<Number> = Vector.<Number>([0, 0, 0]);
|
||||
static private const invertCameraPosition:Vector.<Number> = new Vector.<Number>(3, true);
|
||||
|
||||
override protected function drawVisibleChildren(camera:Camera3D, object:Object3D, canvas:Canvas):void {
|
||||
var i:int;
|
||||
var child:Object3D;
|
||||
invertCameraMatrix.identity();
|
||||
invertCameraMatrix.prepend(object.cameraMatrix);
|
||||
invertCameraMatrix.invert();
|
||||
invertCameraMatrix.transformVectors(cameraPosition, invertCameraPosition);
|
||||
if (invertCameraPosition[0]*splitPlane.x + invertCameraPosition[1]*splitPlane.y + invertCameraPosition[2]*splitPlane.z < splitPlane.w) {
|
||||
for (i = 0; i < numVisibleChildren; i++) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
} else {
|
||||
for (i = numVisibleChildren - 1; i >= 0; i--) {
|
||||
child = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 109
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/controllers
|
||||
END
|
||||
SimpleObjectController.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 135
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/controllers/SimpleObjectController.as
|
||||
END
|
||||
@@ -0,0 +1,40 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/controllers
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-07-09T12:53:17.549217Z
|
||||
16221
|
||||
int
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
SimpleObjectController.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
850afc2a3acec3ceff3924b122dabc29
|
||||
2009-07-09T12:53:17.549217Z
|
||||
16221
|
||||
int
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,454 @@
|
||||
package alternativa.engine3d.controllers {
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
|
||||
import flash.display.InteractiveObject;
|
||||
import flash.events.KeyboardEvent;
|
||||
import flash.events.MouseEvent;
|
||||
import flash.geom.Point;
|
||||
import flash.geom.Vector3D;
|
||||
import flash.ui.Keyboard;
|
||||
import flash.utils.getTimer;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SimpleObjectController {
|
||||
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения вперёд.
|
||||
*/
|
||||
public static const ACTION_FORWARD:String = "ACTION_FORWARD";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения назад.
|
||||
*/
|
||||
public static const ACTION_BACK:String = "ACTION_BACK";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения влево.
|
||||
*/
|
||||
public static const ACTION_LEFT:String = "ACTION_LEFT";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения вправо.
|
||||
*/
|
||||
public static const ACTION_RIGHT:String = "ACTION_RIGHT";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения вверх.
|
||||
*/
|
||||
public static const ACTION_UP:String = "ACTION_UP";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения вниз.
|
||||
*/
|
||||
public static const ACTION_DOWN:String = "ACTION_DOWN";
|
||||
/**
|
||||
* Имя действия для привязки клавиш поворота вверх.
|
||||
*/
|
||||
public static const ACTION_PITCH_UP:String = "ACTION_PITCH_UP";
|
||||
/**
|
||||
* Имя действия для привязки клавиш поворота вниз.
|
||||
*/
|
||||
public static const ACTION_PITCH_DOWN:String = "ACTION_PITCH_DOWN";
|
||||
/**
|
||||
* Имя действия для привязки клавиш поворота налево.
|
||||
*/
|
||||
public static const ACTION_YAW_LEFT:String = "ACTION_YAW_LEFT";
|
||||
/**
|
||||
* Имя действия для привязки клавиш поворота направо.
|
||||
*/
|
||||
public static const ACTION_YAW_RIGHT:String = "ACTION_YAW_RIGHT";
|
||||
/**
|
||||
* Имя действия для привязки клавиш увеличения скорости.
|
||||
*/
|
||||
public static const ACTION_ACCELERATE:String = "ACTION_ACCELERATE";
|
||||
/**
|
||||
* Имя действия для привязки клавиш активации обзора мышью.
|
||||
*/
|
||||
public static const ACTION_MOUSE_LOOK:String = "ACTION_MOUSE_LOOK";
|
||||
|
||||
|
||||
public var speed:Number;
|
||||
public var speedMultiplier:Number;
|
||||
public var mouseSensitivity:Number;
|
||||
public var maxPitch:Number = Number.MAX_VALUE;
|
||||
public var minPitch:Number = -Number.MAX_VALUE;
|
||||
|
||||
private var eventSource:InteractiveObject;
|
||||
private var _object:Object3D;
|
||||
|
||||
private var _up:Boolean;
|
||||
private var _down:Boolean;
|
||||
private var _forward:Boolean;
|
||||
private var _back:Boolean;
|
||||
private var _left:Boolean;
|
||||
private var _right:Boolean;
|
||||
private var _accelerate:Boolean;
|
||||
|
||||
private var displacement:Vector3D = new Vector3D();
|
||||
private var mousePoint:Point = new Point();
|
||||
private var mouseLook:Boolean;
|
||||
private var objectTransform:Vector.<Vector3D>;
|
||||
|
||||
private var time:int;
|
||||
|
||||
/**
|
||||
* Ассоциативный массив, связывающий имена команд с реализующими их функциями. Функции должны иметь вид
|
||||
* function(value:Boolean):void. Значение параметра <code>value</code> указывает, нажата или отпущена соответсвующая команде
|
||||
* клавиша.
|
||||
*/
|
||||
private var actionBindings:Object = {};
|
||||
/**
|
||||
* Ассоциативный массив, связывающий коды клавиатурных клавиш с именами команд.
|
||||
*/
|
||||
protected var keyBindings:Object = {};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param eventSource источник событий для контроллера
|
||||
* @param speed скорость поступательного перемещения объекта
|
||||
* @param mouseSensitivity чувствительность мыши - количество градусов поворота на один пиксель перемещения мыши
|
||||
*/
|
||||
public function SimpleObjectController(eventSource:InteractiveObject, object:Object3D, speed:Number, speedMultiplier:Number = 3, mouseSensitivity:Number = 1) {
|
||||
this.eventSource = eventSource;
|
||||
this.object = object;
|
||||
this.speed = speed;
|
||||
this.speedMultiplier = speedMultiplier;
|
||||
this.mouseSensitivity = mouseSensitivity;
|
||||
|
||||
actionBindings[ACTION_FORWARD] = moveForward;
|
||||
actionBindings[ACTION_BACK] = moveBack;
|
||||
actionBindings[ACTION_LEFT] = moveLeft;
|
||||
actionBindings[ACTION_RIGHT] = moveRight;
|
||||
actionBindings[ACTION_UP] = moveUp;
|
||||
actionBindings[ACTION_DOWN] = moveDown;
|
||||
actionBindings[ACTION_ACCELERATE] = accelerate;
|
||||
|
||||
setDefaultBindings();
|
||||
|
||||
enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Активирует контроллер.
|
||||
*/
|
||||
public function enable():void {
|
||||
eventSource.addEventListener(KeyboardEvent.KEY_DOWN, onKey);
|
||||
eventSource.addEventListener(KeyboardEvent.KEY_UP, onKey);
|
||||
eventSource.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
|
||||
eventSource.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Дективирует контроллер.
|
||||
*/
|
||||
public function disable():void {
|
||||
eventSource.removeEventListener(KeyboardEvent.KEY_DOWN, onKey);
|
||||
eventSource.removeEventListener(KeyboardEvent.KEY_UP, onKey);
|
||||
eventSource.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
|
||||
eventSource.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
|
||||
stopMouseLook();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function onMouseDown(e:MouseEvent):void {
|
||||
startMouseLook();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function onMouseUp(e:MouseEvent):void {
|
||||
stopMouseLook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Включает режим взгляда мышью.
|
||||
*/
|
||||
public function startMouseLook():void {
|
||||
mousePoint.x = eventSource.mouseX;
|
||||
mousePoint.y = eventSource.mouseY;
|
||||
mouseLook = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отключает режим взгляда мышью.
|
||||
*/
|
||||
public function stopMouseLook():void {
|
||||
mouseLook = false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function onKey(e:KeyboardEvent):void {
|
||||
var method:Function = keyBindings[e.keyCode];
|
||||
if (method != null) method.call(this, e.type == KeyboardEvent.KEY_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Управляемый объект.
|
||||
*/
|
||||
public function set object(value:Object3D):void {
|
||||
_object = value;
|
||||
updateObjectTransform();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function get object():Object3D {
|
||||
return _object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет инофрмацию о трансформации объекта. Метод следует вызывать после изменения матрицы объекта вне контролллера.
|
||||
*/
|
||||
public function updateObjectTransform():void {
|
||||
if (_object != null) objectTransform = _object.matrix.decompose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Вычисляет новое положение объекта, используя внутренний счётчик времени.
|
||||
*/
|
||||
public function update():void {
|
||||
if (_object == null) return;
|
||||
|
||||
var frameTime:Number = time;
|
||||
time = getTimer();
|
||||
frameTime = 0.001*(time - frameTime);
|
||||
if (frameTime > 0.1) frameTime = 0.1;
|
||||
|
||||
var moved:Boolean = false;
|
||||
|
||||
if (mouseLook) {
|
||||
var dx:Number = eventSource.mouseX - mousePoint.x;
|
||||
var dy:Number = eventSource.mouseY - mousePoint.y;
|
||||
mousePoint.x = eventSource.mouseX;
|
||||
mousePoint.y = eventSource.mouseY;
|
||||
var v:Vector3D = objectTransform[1];
|
||||
v.x -= dy*Math.PI/180*mouseSensitivity;
|
||||
if (v.x > maxPitch) v.x = maxPitch;
|
||||
if (v.x < minPitch) v.x = minPitch;
|
||||
v.z -= dx*Math.PI/180*mouseSensitivity;
|
||||
moved = true;
|
||||
}
|
||||
|
||||
displacement.x = _right ? 1 : (_left ? -1 : 0);
|
||||
displacement.y = _forward ? 1 : (_back ? -1 : 0);
|
||||
displacement.z = _up ? 1 : (_down ? -1 : 0);
|
||||
if (displacement.lengthSquared > 0) {
|
||||
if (_object is Camera3D) {
|
||||
var tmp:Number = displacement.z;
|
||||
displacement.z = displacement.y;
|
||||
displacement.y = -tmp;
|
||||
}
|
||||
deltaTransformVector(displacement);
|
||||
if (_accelerate) displacement.scaleBy(speedMultiplier*speed*frameTime/displacement.length);
|
||||
else displacement.scaleBy(speed*frameTime/displacement.length);
|
||||
(objectTransform[0] as Vector3D).incrementBy(displacement);
|
||||
moved = true;
|
||||
}
|
||||
|
||||
if (moved) _object.matrix.recompose(objectTransform);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pos
|
||||
*/
|
||||
public function setObjectPos(pos:Vector3D):void {
|
||||
if (_object != null) {
|
||||
var v:Vector3D = objectTransform[0];
|
||||
v.x = pos.x;
|
||||
v.y = pos.y;
|
||||
v.z = pos.z;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pos
|
||||
*/
|
||||
public function setObjectPosXYZ(x:Number, y:Number, z:Number):void {
|
||||
if (_object != null) {
|
||||
var v:Vector3D = objectTransform[0];
|
||||
v.x = x;
|
||||
v.y = y;
|
||||
v.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param point
|
||||
*/
|
||||
public function lookAt(point:Vector3D):void {
|
||||
lookAtXYZ(point.x, point.y, point.z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public function lookAtXYZ(x:Number, y:Number, z:Number):void {
|
||||
if (_object == null) return;
|
||||
var v:Vector3D = objectTransform[0];
|
||||
var dx:Number = x - v.x;
|
||||
var dy:Number = y - v.y;
|
||||
var dz:Number = z - v.z;
|
||||
v = objectTransform[1];
|
||||
v.x = Math.atan2(dz, Math.sqrt(dx*dx + dy*dy));
|
||||
if (_object is Camera3D) v.x -= 0.5*Math.PI;
|
||||
v.y = 0;
|
||||
v.z = -Math.atan2(dx, dy);
|
||||
_object.matrix.recompose(objectTransform);
|
||||
}
|
||||
|
||||
private var _vin:Vector.<Number> = new Vector.<Number>(3);
|
||||
private var _vout:Vector.<Number> = new Vector.<Number>(3);
|
||||
|
||||
private function deltaTransformVector(v:Vector3D):void {
|
||||
_vin[0] = v.x;
|
||||
_vin[1] = v.y;
|
||||
_vin[2] = v.z;
|
||||
_object.matrix.transformVectors(_vin, _vout);
|
||||
var c:Vector3D = objectTransform[0];
|
||||
v.x = _vout[0] - c.x;
|
||||
v.y = _vout[1] - c.y;
|
||||
v.z = _vout[2] - c.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения вперёд.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveForward(value:Boolean):void {
|
||||
_forward = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения назад.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveBack(value:Boolean):void {
|
||||
_back = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения влево.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveLeft(value:Boolean):void {
|
||||
_left = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения вправо.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveRight(value:Boolean):void {
|
||||
_right = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения вверх.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveUp(value:Boolean):void {
|
||||
_up = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения вниз.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveDown(value:Boolean):void {
|
||||
_down = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация режима увеличенной скорости.
|
||||
*
|
||||
* @param value <code>true</code> для включения ускорения, <code>false</code> для выключения
|
||||
*/
|
||||
public function accelerate(value:Boolean):void {
|
||||
_accelerate = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод выполняет привязку клавиши к действию. Одной клавише может быть назначено только одно действие.
|
||||
*
|
||||
* @param keyCode код клавиши
|
||||
* @param action наименование действия
|
||||
*
|
||||
* @see #unbindKey()
|
||||
* @see #unbindAll()
|
||||
*/
|
||||
public function bindKey(keyCode:uint, action:String):void {
|
||||
var method:Function = actionBindings[action];
|
||||
if (method != null) keyBindings[keyCode] = method;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function bindKeys(bindings:Array):void {
|
||||
for (var i:int = 0; i < bindings.length; i += 2) bindKey(bindings[i], bindings[i + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Очистка привязки клавиши.
|
||||
*
|
||||
* @param keyCode код клавиши
|
||||
*
|
||||
* @see #bindKey()
|
||||
* @see #unbindAll()
|
||||
*/
|
||||
public function unbindKey(keyCode:uint):void {
|
||||
delete keyBindings[keyCode];
|
||||
}
|
||||
|
||||
/**
|
||||
* Очистка привязки всех клавиш.
|
||||
*
|
||||
* @see #bindKey()
|
||||
* @see #unbindKey()
|
||||
*/
|
||||
public function unbindAll():void {
|
||||
for (var key:* in keyBindings) delete keyBindings[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод устанавливает привязки клавиш по умолчанию. Реализация по умолчанию не делает ничего.
|
||||
*
|
||||
* @see #bindKey()
|
||||
* @see #unbindKey()
|
||||
* @see #unbindAll()
|
||||
*/
|
||||
public function setDefaultBindings():void {
|
||||
bindKey(87, ACTION_FORWARD);
|
||||
bindKey(83, ACTION_BACK);
|
||||
bindKey(65, ACTION_LEFT);
|
||||
bindKey(68, ACTION_RIGHT);
|
||||
bindKey(69, ACTION_UP);
|
||||
bindKey(67, ACTION_DOWN);
|
||||
bindKey(Keyboard.SHIFT, ACTION_ACCELERATE);
|
||||
|
||||
bindKey(Keyboard.UP, ACTION_FORWARD);
|
||||
bindKey(Keyboard.DOWN, ACTION_BACK);
|
||||
bindKey(Keyboard.LEFT, ACTION_LEFT);
|
||||
bindKey(Keyboard.RIGHT, ACTION_RIGHT);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,454 @@
|
||||
package alternativa.engine3d.controllers {
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.core.Camera3D;
|
||||
import alternativa.engine3d.core.Object3D;
|
||||
|
||||
import flash.display.InteractiveObject;
|
||||
import flash.events.KeyboardEvent;
|
||||
import flash.events.MouseEvent;
|
||||
import flash.geom.Point;
|
||||
import flash.geom.Vector3D;
|
||||
import flash.ui.Keyboard;
|
||||
import flash.utils.getTimer;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SimpleObjectController {
|
||||
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения вперёд.
|
||||
*/
|
||||
public static const ACTION_FORWARD:String = "ACTION_FORWARD";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения назад.
|
||||
*/
|
||||
public static const ACTION_BACK:String = "ACTION_BACK";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения влево.
|
||||
*/
|
||||
public static const ACTION_LEFT:String = "ACTION_LEFT";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения вправо.
|
||||
*/
|
||||
public static const ACTION_RIGHT:String = "ACTION_RIGHT";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения вверх.
|
||||
*/
|
||||
public static const ACTION_UP:String = "ACTION_UP";
|
||||
/**
|
||||
* Имя действия для привязки клавиш движения вниз.
|
||||
*/
|
||||
public static const ACTION_DOWN:String = "ACTION_DOWN";
|
||||
/**
|
||||
* Имя действия для привязки клавиш поворота вверх.
|
||||
*/
|
||||
public static const ACTION_PITCH_UP:String = "ACTION_PITCH_UP";
|
||||
/**
|
||||
* Имя действия для привязки клавиш поворота вниз.
|
||||
*/
|
||||
public static const ACTION_PITCH_DOWN:String = "ACTION_PITCH_DOWN";
|
||||
/**
|
||||
* Имя действия для привязки клавиш поворота налево.
|
||||
*/
|
||||
public static const ACTION_YAW_LEFT:String = "ACTION_YAW_LEFT";
|
||||
/**
|
||||
* Имя действия для привязки клавиш поворота направо.
|
||||
*/
|
||||
public static const ACTION_YAW_RIGHT:String = "ACTION_YAW_RIGHT";
|
||||
/**
|
||||
* Имя действия для привязки клавиш увеличения скорости.
|
||||
*/
|
||||
public static const ACTION_ACCELERATE:String = "ACTION_ACCELERATE";
|
||||
/**
|
||||
* Имя действия для привязки клавиш активации обзора мышью.
|
||||
*/
|
||||
public static const ACTION_MOUSE_LOOK:String = "ACTION_MOUSE_LOOK";
|
||||
|
||||
|
||||
public var speed:Number;
|
||||
public var speedMultiplier:Number;
|
||||
public var mouseSensitivity:Number;
|
||||
public var maxPitch:Number = Number.MAX_VALUE;
|
||||
public var minPitch:Number = -Number.MAX_VALUE;
|
||||
|
||||
private var eventSource:InteractiveObject;
|
||||
private var _object:Object3D;
|
||||
|
||||
private var _up:Boolean;
|
||||
private var _down:Boolean;
|
||||
private var _forward:Boolean;
|
||||
private var _back:Boolean;
|
||||
private var _left:Boolean;
|
||||
private var _right:Boolean;
|
||||
private var _accelerate:Boolean;
|
||||
|
||||
private var displacement:Vector3D = new Vector3D();
|
||||
private var mousePoint:Point = new Point();
|
||||
private var mouseLook:Boolean;
|
||||
private var objectTransform:Vector.<Vector3D>;
|
||||
|
||||
private var time:int;
|
||||
|
||||
/**
|
||||
* Ассоциативный массив, связывающий имена команд с реализующими их функциями. Функции должны иметь вид
|
||||
* function(value:Boolean):void. Значение параметра <code>value</code> указывает, нажата или отпущена соответсвующая команде
|
||||
* клавиша.
|
||||
*/
|
||||
private var actionBindings:Object = {};
|
||||
/**
|
||||
* Ассоциативный массив, связывающий коды клавиатурных клавиш с именами команд.
|
||||
*/
|
||||
protected var keyBindings:Object = {};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param eventSource источник событий для контроллера
|
||||
* @param speed скорость поступательного перемещения объекта
|
||||
* @param mouseSensitivity чувствительность мыши - количество градусов поворота на один пиксель перемещения мыши
|
||||
*/
|
||||
public function SimpleObjectController(eventSource:InteractiveObject, object:Object3D, speed:Number, speedMultiplier:Number = 3, mouseSensitivity:Number = 1) {
|
||||
this.eventSource = eventSource;
|
||||
this.object = object;
|
||||
this.speed = speed;
|
||||
this.speedMultiplier = speedMultiplier;
|
||||
this.mouseSensitivity = mouseSensitivity;
|
||||
|
||||
actionBindings[ACTION_FORWARD] = moveForward;
|
||||
actionBindings[ACTION_BACK] = moveBack;
|
||||
actionBindings[ACTION_LEFT] = moveLeft;
|
||||
actionBindings[ACTION_RIGHT] = moveRight;
|
||||
actionBindings[ACTION_UP] = moveUp;
|
||||
actionBindings[ACTION_DOWN] = moveDown;
|
||||
actionBindings[ACTION_ACCELERATE] = accelerate;
|
||||
|
||||
setDefaultBindings();
|
||||
|
||||
enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Активирует контроллер.
|
||||
*/
|
||||
public function enable():void {
|
||||
eventSource.addEventListener(KeyboardEvent.KEY_DOWN, onKey);
|
||||
eventSource.addEventListener(KeyboardEvent.KEY_UP, onKey);
|
||||
eventSource.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
|
||||
eventSource.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Дективирует контроллер.
|
||||
*/
|
||||
public function disable():void {
|
||||
eventSource.removeEventListener(KeyboardEvent.KEY_DOWN, onKey);
|
||||
eventSource.removeEventListener(KeyboardEvent.KEY_UP, onKey);
|
||||
eventSource.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
|
||||
eventSource.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
|
||||
stopMouseLook();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function onMouseDown(e:MouseEvent):void {
|
||||
startMouseLook();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function onMouseUp(e:MouseEvent):void {
|
||||
stopMouseLook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Включает режим взгляда мышью.
|
||||
*/
|
||||
public function startMouseLook():void {
|
||||
mousePoint.x = eventSource.mouseX;
|
||||
mousePoint.y = eventSource.mouseY;
|
||||
mouseLook = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отключает режим взгляда мышью.
|
||||
*/
|
||||
public function stopMouseLook():void {
|
||||
mouseLook = false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function onKey(e:KeyboardEvent):void {
|
||||
var method:Function = keyBindings[e.keyCode];
|
||||
if (method != null) method.call(this, e.type == KeyboardEvent.KEY_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Управляемый объект.
|
||||
*/
|
||||
public function set object(value:Object3D):void {
|
||||
_object = value;
|
||||
updateObjectTransform();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function get object():Object3D {
|
||||
return _object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет инофрмацию о трансформации объекта. Метод следует вызывать после изменения матрицы объекта вне контролллера.
|
||||
*/
|
||||
public function updateObjectTransform():void {
|
||||
if (_object != null) objectTransform = _object.matrix.decompose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Вычисляет новое положение объекта, используя внутренний счётчик времени.
|
||||
*/
|
||||
public function update():void {
|
||||
if (_object == null) return;
|
||||
|
||||
var frameTime:Number = time;
|
||||
time = getTimer();
|
||||
frameTime = 0.001*(time - frameTime);
|
||||
if (frameTime > 0.1) frameTime = 0.1;
|
||||
|
||||
var moved:Boolean = false;
|
||||
|
||||
if (mouseLook) {
|
||||
var dx:Number = eventSource.mouseX - mousePoint.x;
|
||||
var dy:Number = eventSource.mouseY - mousePoint.y;
|
||||
mousePoint.x = eventSource.mouseX;
|
||||
mousePoint.y = eventSource.mouseY;
|
||||
var v:Vector3D = objectTransform[1];
|
||||
v.x -= dy*Math.PI/180*mouseSensitivity;
|
||||
if (v.x > maxPitch) v.x = maxPitch;
|
||||
if (v.x < minPitch) v.x = minPitch;
|
||||
v.z -= dx*Math.PI/180*mouseSensitivity;
|
||||
moved = true;
|
||||
}
|
||||
|
||||
displacement.x = _right ? 1 : (_left ? -1 : 0);
|
||||
displacement.y = _forward ? 1 : (_back ? -1 : 0);
|
||||
displacement.z = _up ? 1 : (_down ? -1 : 0);
|
||||
if (displacement.lengthSquared > 0) {
|
||||
if (_object is Camera3D) {
|
||||
var tmp:Number = displacement.z;
|
||||
displacement.z = displacement.y;
|
||||
displacement.y = -tmp;
|
||||
}
|
||||
deltaTransformVector(displacement);
|
||||
if (_accelerate) displacement.scaleBy(speedMultiplier*speed*frameTime/displacement.length);
|
||||
else displacement.scaleBy(speed*frameTime/displacement.length);
|
||||
(objectTransform[0] as Vector3D).incrementBy(displacement);
|
||||
moved = true;
|
||||
}
|
||||
|
||||
if (moved) _object.matrix.recompose(objectTransform);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pos
|
||||
*/
|
||||
public function setObjectPos(pos:Vector3D):void {
|
||||
if (_object != null) {
|
||||
var v:Vector3D = objectTransform[0];
|
||||
v.x = pos.x;
|
||||
v.y = pos.y;
|
||||
v.z = pos.z;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pos
|
||||
*/
|
||||
public function setObjectPosXYZ(x:Number, y:Number, z:Number):void {
|
||||
if (_object != null) {
|
||||
var v:Vector3D = objectTransform[0];
|
||||
v.x = x;
|
||||
v.y = y;
|
||||
v.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param point
|
||||
*/
|
||||
public function lookAt(point:Vector3D):void {
|
||||
lookAtXYZ(point.x, point.y, point.z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public function lookAtXYZ(x:Number, y:Number, z:Number):void {
|
||||
if (_object == null) return;
|
||||
var v:Vector3D = objectTransform[0];
|
||||
var dx:Number = x - v.x;
|
||||
var dy:Number = y - v.y;
|
||||
var dz:Number = z - v.z;
|
||||
v = objectTransform[1];
|
||||
v.x = Math.atan2(dz, Math.sqrt(dx*dx + dy*dy));
|
||||
if (_object is Camera3D) v.x -= 0.5*Math.PI;
|
||||
v.y = 0;
|
||||
v.z = -Math.atan2(dx, dy);
|
||||
_object.matrix.recompose(objectTransform);
|
||||
}
|
||||
|
||||
private var _vin:Vector.<Number> = new Vector.<Number>(3);
|
||||
private var _vout:Vector.<Number> = new Vector.<Number>(3);
|
||||
|
||||
private function deltaTransformVector(v:Vector3D):void {
|
||||
_vin[0] = v.x;
|
||||
_vin[1] = v.y;
|
||||
_vin[2] = v.z;
|
||||
_object.matrix.transformVectors(_vin, _vout);
|
||||
var c:Vector3D = objectTransform[0];
|
||||
v.x = _vout[0] - c.x;
|
||||
v.y = _vout[1] - c.y;
|
||||
v.z = _vout[2] - c.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения вперёд.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveForward(value:Boolean):void {
|
||||
_forward = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения назад.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveBack(value:Boolean):void {
|
||||
_back = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения влево.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveLeft(value:Boolean):void {
|
||||
_left = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения вправо.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveRight(value:Boolean):void {
|
||||
_right = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения вверх.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveUp(value:Boolean):void {
|
||||
_up = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация движения вниз.
|
||||
*
|
||||
* @param value <code>true</code> для начала движения, <code>false</code> для окончания
|
||||
*/
|
||||
public function moveDown(value:Boolean):void {
|
||||
_down = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация режима увеличенной скорости.
|
||||
*
|
||||
* @param value <code>true</code> для включения ускорения, <code>false</code> для выключения
|
||||
*/
|
||||
public function accelerate(value:Boolean):void {
|
||||
_accelerate = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод выполняет привязку клавиши к действию. Одной клавише может быть назначено только одно действие.
|
||||
*
|
||||
* @param keyCode код клавиши
|
||||
* @param action наименование действия
|
||||
*
|
||||
* @see #unbindKey()
|
||||
* @see #unbindAll()
|
||||
*/
|
||||
public function bindKey(keyCode:uint, action:String):void {
|
||||
var method:Function = actionBindings[action];
|
||||
if (method != null) keyBindings[keyCode] = method;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function bindKeys(bindings:Array):void {
|
||||
for (var i:int = 0; i < bindings.length; i += 2) bindKey(bindings[i], bindings[i + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Очистка привязки клавиши.
|
||||
*
|
||||
* @param keyCode код клавиши
|
||||
*
|
||||
* @see #bindKey()
|
||||
* @see #unbindAll()
|
||||
*/
|
||||
public function unbindKey(keyCode:uint):void {
|
||||
delete keyBindings[keyCode];
|
||||
}
|
||||
|
||||
/**
|
||||
* Очистка привязки всех клавиш.
|
||||
*
|
||||
* @see #bindKey()
|
||||
* @see #unbindKey()
|
||||
*/
|
||||
public function unbindAll():void {
|
||||
for (var key:* in keyBindings) delete keyBindings[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод устанавливает привязки клавиш по умолчанию. Реализация по умолчанию не делает ничего.
|
||||
*
|
||||
* @see #bindKey()
|
||||
* @see #unbindKey()
|
||||
* @see #unbindAll()
|
||||
*/
|
||||
public function setDefaultBindings():void {
|
||||
bindKey(87, ACTION_FORWARD);
|
||||
bindKey(83, ACTION_BACK);
|
||||
bindKey(65, ACTION_LEFT);
|
||||
bindKey(68, ACTION_RIGHT);
|
||||
bindKey(69, ACTION_UP);
|
||||
bindKey(67, ACTION_DOWN);
|
||||
bindKey(Keyboard.SHIFT, ACTION_ACCELERATE);
|
||||
|
||||
bindKey(Keyboard.UP, ACTION_FORWARD);
|
||||
bindKey(Keyboard.DOWN, ACTION_BACK);
|
||||
bindKey(Keyboard.LEFT, ACTION_LEFT);
|
||||
bindKey(Keyboard.RIGHT, ACTION_RIGHT);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 102
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core
|
||||
END
|
||||
BackfaceCulling.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 121
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/BackfaceCulling.as
|
||||
END
|
||||
Object3D.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 114
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Object3D.as
|
||||
END
|
||||
Camera3D.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 114
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Camera3D.as
|
||||
END
|
||||
BoundBox.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 114
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/BoundBox.as
|
||||
END
|
||||
Object3DContainer.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 123
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Object3DContainer.as
|
||||
END
|
||||
MipMapping.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 116
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/MipMapping.as
|
||||
END
|
||||
Fragment.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 114
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Fragment.as
|
||||
END
|
||||
MipMap.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 112
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/MipMap.as
|
||||
END
|
||||
Clipping.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 114
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Clipping.as
|
||||
END
|
||||
Node.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 110
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Node.as
|
||||
END
|
||||
Sorting.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 113
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Sorting.as
|
||||
END
|
||||
Debug.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 111
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Debug.as
|
||||
END
|
||||
Canvas.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 112
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Canvas.as
|
||||
END
|
||||
Geometry.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 114
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core/Geometry.as
|
||||
END
|
||||
200
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/.svn/entries
Normal file
200
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/.svn/entries
Normal file
@@ -0,0 +1,200 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/core
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-10-19T11:39:18.186364Z
|
||||
22296
|
||||
int
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
BackfaceCulling.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
7bea5cb8c30609d1e38c7511b4bb29f4
|
||||
2009-10-16T12:40:21.746295Z
|
||||
22165
|
||||
int
|
||||
|
||||
Object3D.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
2bdfdaa15f7c223f49895e000158fd7f
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
has-props
|
||||
|
||||
Camera3D.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
d239950295dbf063016f345efb243b2e
|
||||
2009-10-15T16:06:18.552844Z
|
||||
22065
|
||||
int
|
||||
|
||||
BoundBox.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
7c4d9b43878d419d034e6d20484b9564
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
has-props
|
||||
|
||||
Object3DContainer.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
7e7d9af7577428ba82dfa9655ce6265f
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
|
||||
MipMapping.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
bc8aa0796ff6fe7bc165e58e3c81f4a7
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
|
||||
Fragment.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
0766b94a07ef7298ece02c2161616871
|
||||
2009-10-18T13:22:08.786837Z
|
||||
22234
|
||||
int
|
||||
|
||||
MipMap.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
257d1c88bd8bf829ecb9c9d1a9349e99
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
|
||||
Clipping.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
9e7c045c894b1c0f59c244baa23319c6
|
||||
2009-10-16T11:48:05.744366Z
|
||||
22160
|
||||
int
|
||||
|
||||
Node.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
0808882f8440b9c9e5e0488afc181bbd
|
||||
2009-10-19T11:39:18.186364Z
|
||||
22296
|
||||
int
|
||||
has-props
|
||||
|
||||
Sorting.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
72006aa7f32e39a9d7b5693042c1c903
|
||||
2009-10-16T11:48:05.744366Z
|
||||
22160
|
||||
int
|
||||
|
||||
Debug.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
4d8de4fb9b1c0b0683861df1042fcc13
|
||||
2009-10-15T16:00:46.512753Z
|
||||
22064
|
||||
int
|
||||
|
||||
Canvas.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
0a3bab96a01540f24aea3a9381b37c3a
|
||||
2009-10-18T09:57:48.052564Z
|
||||
22208
|
||||
int
|
||||
has-props
|
||||
|
||||
Geometry.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
6eed84f0a8ff5f7851c2de69863ea27a
|
||||
2009-10-18T15:44:36.557045Z
|
||||
22247
|
||||
int
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,11 @@
|
||||
K 13
|
||||
svn:mergeinfo
|
||||
V 842
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0/src/alternativa/engine3d/bounds/BoundBox.as:5796-7235
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0.2/src/alternativa/engine3d/core/BoundBox.as:17447,17456-18883
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4/alternativa/engine3d/bounds/BoundBox.as:304-463
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.MouseEvents/src/alternativa/engine3d/bounds/BoundBox.as:1556-1900
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.SingularMapping/src/alternativa/engine3d/bounds/BoundBox.as:2042-2060
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk/alternativa/engine3d/bounds/BoundBox.as:304-494
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk/src/alternativa/engine3d/bounds/BoundBox.as:1465-2616,2621-2676,2680-2696,2710-2743,2778-2783
|
||||
END
|
||||
@@ -0,0 +1,5 @@
|
||||
K 13
|
||||
svn:mergeinfo
|
||||
V 119
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0.2/src/alternativa/engine3d/core/Canvas.as:17447,17456-18883
|
||||
END
|
||||
@@ -0,0 +1,11 @@
|
||||
K 13
|
||||
svn:mergeinfo
|
||||
V 816
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0/src/alternativa/engine3d/core/KDNode.as:5796-7235
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0.2/src/alternativa/engine3d/core/KDNode.as:17447,17456-18883
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4/alternativa/engine3d/core/KDNode.as:304-463
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.MouseEvents/src/alternativa/engine3d/core/KDNode.as:1556-1900
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.SingularMapping/src/alternativa/engine3d/core/KDNode.as:2042-2060
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk/alternativa/engine3d/core/KDNode.as:304-494
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk/src/alternativa/engine3d/core/KDNode.as:1465-2616,2621-2676,2680-2696,2710-2743,2778-2783
|
||||
END
|
||||
@@ -0,0 +1,10 @@
|
||||
K 13
|
||||
svn:mergeinfo
|
||||
V 718
|
||||
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0.2/src/alternativa/engine3d/core/Object3D.as:17447,17456-18883
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4/alternativa/engine3d/core/Object3D.as:304-463
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.MouseEvents/src/alternativa/engine3d/core/Object3D.as:1556-1900
|
||||
/platform/clients/fp9/libraries/Alternativa3D/branches/5.4.SingularMapping/src/alternativa/engine3d/core/Object3D.as:2042-2060
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk/alternativa/engine3d/core/Object3D.as:304-494
|
||||
/platform/clients/fp9/libraries/Alternativa3D/trunk/src/alternativa/engine3d/core/Object3D.as:1465-2616,2621-2676,2680-2696,2710-2743,2778-2783
|
||||
END
|
||||
@@ -0,0 +1,15 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class BackfaceCulling {
|
||||
|
||||
/**
|
||||
* Отсечение по динамически расчитываемым нормалям.
|
||||
*/
|
||||
static public const DYNAMIC_NORMALS:int = 0;
|
||||
/**
|
||||
* Отсечение по предрасчитанным нормалям.
|
||||
*/
|
||||
static public const STATIC_NORMALS:int = 1;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
import flash.geom.Matrix3D;
|
||||
|
||||
public class BoundBox {
|
||||
|
||||
public var minX:Number = Number.MAX_VALUE;
|
||||
public var minY:Number = Number.MAX_VALUE;
|
||||
public var minZ:Number = Number.MAX_VALUE;
|
||||
public var maxX:Number = -Number.MAX_VALUE;
|
||||
public var maxY:Number = -Number.MAX_VALUE;
|
||||
public var maxZ:Number = -Number.MAX_VALUE;
|
||||
|
||||
public function setSize(minX:Number, minY:Number, minZ:Number, maxX:Number, maxY:Number, maxZ:Number):void {
|
||||
this.minX = minX;
|
||||
this.minY = minY;
|
||||
this.minZ = minZ;
|
||||
this.maxX = maxX;
|
||||
this.maxY = maxY;
|
||||
this.maxZ = maxZ;
|
||||
}
|
||||
|
||||
public function addBoundBox(boundBox:BoundBox):void {
|
||||
minX = (boundBox.minX < minX) ? boundBox.minX : minX;
|
||||
minY = (boundBox.minY < minY) ? boundBox.minY : minY;
|
||||
minZ = (boundBox.minZ < minZ) ? boundBox.minZ : minZ;
|
||||
maxX = (boundBox.maxX > maxX) ? boundBox.maxX : maxX;
|
||||
maxY = (boundBox.maxY > maxY) ? boundBox.maxY : maxY;
|
||||
maxZ = (boundBox.maxZ > maxZ) ? boundBox.maxZ : maxZ;
|
||||
}
|
||||
|
||||
public function addPoint(x:Number, y:Number, z:Number):void {
|
||||
if (x < minX) minX = x;
|
||||
if (x > maxX) maxX = x;
|
||||
if (y < minY) minY = y;
|
||||
if (y > maxY) maxY = y;
|
||||
if (z < minZ) minZ = z;
|
||||
if (z > maxZ) maxZ = z;
|
||||
}
|
||||
|
||||
public function infinity():void {
|
||||
minX = minY = minZ = Number.MAX_VALUE;
|
||||
maxX = maxY = maxZ = -Number.MAX_VALUE;
|
||||
}
|
||||
|
||||
public function copyFrom(boundBox:BoundBox):void {
|
||||
minX = boundBox.minX;
|
||||
minY = boundBox.minY;
|
||||
minZ = boundBox.minZ;
|
||||
maxX = boundBox.maxX;
|
||||
maxY = boundBox.maxY;
|
||||
maxZ = boundBox.maxZ;
|
||||
}
|
||||
|
||||
public function clone():BoundBox {
|
||||
var clone:BoundBox = new BoundBox();
|
||||
clone.copyFrom(this);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
return "BoundBox [" + minX.toFixed(2) + ", " + minY.toFixed(2) + ", " + minZ.toFixed(2) + " - " + maxX.toFixed(2) + ", " + maxY.toFixed(2) + ", " + maxZ.toFixed(2) + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,414 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.display.Bitmap;
|
||||
import flash.display.BitmapData;
|
||||
import flash.display.Sprite;
|
||||
import flash.display.StageAlign;
|
||||
import flash.events.Event;
|
||||
import flash.geom.Matrix3D;
|
||||
import flash.geom.Point;
|
||||
import flash.geom.Rectangle;
|
||||
import flash.geom.Vector3D;
|
||||
import flash.system.System;
|
||||
import flash.text.TextField;
|
||||
import flash.text.TextFieldAutoSize;
|
||||
import flash.text.TextFormat;
|
||||
import flash.utils.Dictionary;
|
||||
import flash.utils.getDefinitionByName;
|
||||
import flash.utils.getQualifiedClassName;
|
||||
import flash.utils.getQualifiedSuperclassName;
|
||||
import flash.utils.getTimer;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class Camera3D extends Object3D {
|
||||
|
||||
/**
|
||||
* Вьюпорт камеры.
|
||||
*/
|
||||
public var canvas:Canvas;
|
||||
public var fov:Number = Math.PI/2;
|
||||
/**
|
||||
* Ширина вьюпорта.
|
||||
*/
|
||||
public var width:Number = 500;
|
||||
/**
|
||||
* Высота вьюпорта.
|
||||
*/
|
||||
public var height:Number = 500;
|
||||
|
||||
public var nearClipping:Number = 0;
|
||||
public var farClipping:Number = 5000;
|
||||
public var farFalloff:Number = 4000;
|
||||
|
||||
// Матрица проецирования
|
||||
alternativa3d var projectionMatrix:Matrix3D;
|
||||
alternativa3d var projectionMatrixData:Vector.<Number> = new Vector.<Number>(16, true);
|
||||
// Параметры перспективы
|
||||
alternativa3d var viewSize:Number;
|
||||
alternativa3d var viewSizeX:Number;
|
||||
alternativa3d var viewSizeY:Number;
|
||||
alternativa3d var perspectiveScaleX:Number;
|
||||
alternativa3d var perspectiveScaleY:Number;
|
||||
alternativa3d var focalLength:Number;
|
||||
// Перекрытия
|
||||
alternativa3d var occlusionPlanes:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
|
||||
alternativa3d var occlusionEdges:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
|
||||
alternativa3d var numOccluders:int;
|
||||
alternativa3d var occludedAll:Boolean;
|
||||
|
||||
public function Camera3D() {
|
||||
updateProjection();
|
||||
}
|
||||
|
||||
override alternativa3d function get canDraw():Boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отрисовка иерархии объектов, в которой находится камера.
|
||||
* Перед render(), если менялись параметры камеры, нужно вызвать updateProjection().
|
||||
*/
|
||||
public function render():void {
|
||||
// Расчёт матрицы перевода из рута в камеру
|
||||
cameraMatrix.identity();
|
||||
var object:Object3D = this;
|
||||
while (object._parent != null) {
|
||||
cameraMatrix.append(object.matrix);
|
||||
object = object._parent;
|
||||
}
|
||||
cameraMatrix.invert();
|
||||
cameraMatrix.appendScale(perspectiveScaleX, perspectiveScaleY, 1);
|
||||
|
||||
numOccluders = 0;
|
||||
occludedAll = false;
|
||||
|
||||
numTriangles = 0;
|
||||
|
||||
// Отрисовка
|
||||
if (object.visible && object.canDraw) {
|
||||
object.cameraMatrix.identity();
|
||||
object.cameraMatrix.prepend(cameraMatrix);
|
||||
object.cameraMatrix.prepend(object.matrix);
|
||||
if (object.cullingInCamera(this, 63) >= 0) {
|
||||
// Отрисовка объекта
|
||||
canvas.numDraws = 0;
|
||||
if (debugMode) object.debug(this, object, canvas);
|
||||
object.draw(this, object, canvas);
|
||||
// Зачистка ненужных канвасов
|
||||
canvas.removeChildren(canvas.numDraws);
|
||||
} else {
|
||||
// Если отсеклось, зачищаем рутовый канвас
|
||||
canvas.removeChildren(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* После изменения параметров fov, width, height нужно вызвать этот метод.
|
||||
*/
|
||||
public function updateProjection():void {
|
||||
// Расчёт параметров перспективы
|
||||
viewSize = Math.sqrt(width*width + height*height)*0.5;
|
||||
focalLength = viewSize/Math.tan(fov*0.5);
|
||||
viewSizeX = width*0.5;
|
||||
viewSizeY = height*0.5;
|
||||
perspectiveScaleX = focalLength/viewSizeX;
|
||||
perspectiveScaleY = focalLength/viewSizeY;
|
||||
// Подготовка матрицы проецирования
|
||||
projectionMatrixData[0] = viewSizeX;
|
||||
projectionMatrixData[5] = viewSizeY;
|
||||
projectionMatrixData[10] = 1;
|
||||
projectionMatrixData[11] = 1;
|
||||
projectionMatrix = new Matrix3D(projectionMatrixData);
|
||||
}
|
||||
|
||||
private static var _tmpv:Vector.<Number> = new Vector.<Number>(3);
|
||||
|
||||
/**
|
||||
* @param v
|
||||
* @param result
|
||||
*/
|
||||
public function projectGlobal(v:Vector3D, result:Vector3D):void {
|
||||
_tmpv[0] = v.x; _tmpv[1] = v.y; _tmpv[2] = v.z;
|
||||
cameraMatrix.transformVectors(_tmpv, _tmpv);
|
||||
projectionMatrix.transformVectors(_tmpv, _tmpv);
|
||||
result.z = _tmpv[2];
|
||||
result.x = _tmpv[0]/result.z;
|
||||
result.y = _tmpv[1]/result.z;
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
|
||||
// Режим отладки
|
||||
public var debugMode:Boolean = false;
|
||||
|
||||
// Список объектов дебага
|
||||
private var debugSet:Object = new Object();
|
||||
|
||||
// Добавить в дебаг
|
||||
public function addToDebug(debug:int, ... rest):void {
|
||||
if (!debugSet[debug]) debugSet[debug] = new Dictionary();
|
||||
for (var i:int = 0; i < rest.length;) debugSet[debug][rest[i++]] = true;
|
||||
}
|
||||
|
||||
// Убрать из дебага
|
||||
public function removeFromDebug(debug:int, ... rest):void {
|
||||
if (debugSet[debug]) {
|
||||
for (var i:int = 0; i < rest.length;) delete debugSet[debug][rest[i++]];
|
||||
for (var key:* in debugSet[debug]);
|
||||
if (!key) delete debugSet[debug];
|
||||
}
|
||||
}
|
||||
|
||||
// Проверка, находится ли объект или один из классов, от которых он нследован, в дебаге
|
||||
alternativa3d function checkInDebug(object:Object3D):int {
|
||||
var res:int = 0;
|
||||
for (var debug:int = 1; debug <= 256; debug = debug << 1) {
|
||||
if (debugSet[debug]) {
|
||||
if (debugSet[debug][Object3D] || debugSet[debug][object]) {
|
||||
res |= debug;
|
||||
} else {
|
||||
var objectClass:Class = getDefinitionByName(getQualifiedClassName(object)) as Class;
|
||||
while (objectClass != Object3D) {
|
||||
if (debugSet[debug][objectClass]) {
|
||||
res |= debug;
|
||||
break;
|
||||
}
|
||||
objectClass = Class(getDefinitionByName(getQualifiedSuperclassName(objectClass)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public var diagram:Sprite = createDiagram();
|
||||
|
||||
private var fpsTextField:TextField;
|
||||
private var memoryTextField:TextField;
|
||||
private var trianglesTextField:TextField;
|
||||
private var timerTextField:TextField;
|
||||
private var graph:Bitmap;
|
||||
private var rect:Rectangle;
|
||||
|
||||
private var _diagramAlign:String = "TR";
|
||||
private var _diagramHorizontalMargin:Number = 2;
|
||||
private var _diagramVerticalMargin:Number = 2;
|
||||
|
||||
public var fpsUpdatePeriod:int = 10;
|
||||
private var fpsUpdateCounter:int;
|
||||
private var previousFrameTime:int;
|
||||
private var previousPeriodTime:int;
|
||||
|
||||
private var maxMemory:int;
|
||||
alternativa3d var numTriangles:int;
|
||||
|
||||
public var timerUpdatePeriod:int = 10;
|
||||
private var timerUpdateCounter:int;
|
||||
private var timeSum:int;
|
||||
private var timeCount:int;
|
||||
private var timer:int;
|
||||
|
||||
private function createDiagram():Sprite {
|
||||
var diagram:Sprite = new Sprite();
|
||||
diagram.mouseEnabled = false;
|
||||
diagram.mouseChildren = false;
|
||||
// Инициализация диаграммы
|
||||
diagram.addEventListener(Event.ADDED_TO_STAGE, function():void {
|
||||
// FPS
|
||||
fpsTextField = new TextField();
|
||||
fpsTextField.defaultTextFormat = new TextFormat("Tahoma", 10, 0xCCCCCC);
|
||||
fpsTextField.autoSize = TextFieldAutoSize.LEFT;
|
||||
fpsTextField.text = "FPS: " + Number(diagram.stage.frameRate).toFixed(2);
|
||||
fpsTextField.selectable = false;
|
||||
fpsTextField.x = -3;
|
||||
fpsTextField.y = -5;
|
||||
diagram.addChild(fpsTextField);
|
||||
// Память
|
||||
memoryTextField = new TextField();
|
||||
memoryTextField.defaultTextFormat = new TextFormat("Tahoma", 10, 0xCCCC00);
|
||||
memoryTextField.autoSize = TextFieldAutoSize.LEFT;
|
||||
memoryTextField.text = "MEM: " + bytesToString(System.totalMemory);
|
||||
memoryTextField.selectable = false;
|
||||
memoryTextField.x = -3;
|
||||
memoryTextField.y = 4;
|
||||
diagram.addChild(memoryTextField);
|
||||
// Треугольники
|
||||
trianglesTextField = new TextField();
|
||||
trianglesTextField.defaultTextFormat = new TextFormat("Tahoma", 10, 0xFF6600);
|
||||
trianglesTextField.autoSize = TextFieldAutoSize.LEFT;
|
||||
trianglesTextField.text = "TRI: " + 0;
|
||||
trianglesTextField.selectable = false;
|
||||
trianglesTextField.x = -2;
|
||||
trianglesTextField.y = 13;
|
||||
diagram.addChild(trianglesTextField);
|
||||
// Время выполнения метода
|
||||
timerTextField = new TextField();
|
||||
timerTextField.defaultTextFormat = new TextFormat("Tahoma", 10, 0x0066FF);
|
||||
timerTextField.autoSize = TextFieldAutoSize.LEFT;
|
||||
timerTextField.text = "TMR:";
|
||||
timerTextField.selectable = false;
|
||||
timerTextField.x = -2;
|
||||
timerTextField.y = 13 + 9;
|
||||
diagram.addChild(timerTextField);
|
||||
// График
|
||||
graph = new Bitmap(new BitmapData(60, 40, true, 0x20FFFFFF));
|
||||
rect = new Rectangle(0, 0, 1, 40)
|
||||
graph.x = 0;
|
||||
graph.y = 27 + 9;
|
||||
diagram.addChild(graph);
|
||||
// Сброс параметров
|
||||
previousFrameTime = previousPeriodTime = getTimer();
|
||||
fpsUpdateCounter = 0;
|
||||
maxMemory = 0;
|
||||
timerUpdateCounter = 0;
|
||||
timeSum = 0;
|
||||
timeCount = 0;
|
||||
// Подписка
|
||||
diagram.stage.addEventListener(Event.ENTER_FRAME, updateDiagram, false, -1000);
|
||||
diagram.stage.addEventListener(Event.RESIZE, resizeDiagram, false, -1000);
|
||||
resizeDiagram();
|
||||
});
|
||||
// Деинициализация диаграммы
|
||||
diagram.addEventListener(Event.REMOVED_FROM_STAGE, function():void {
|
||||
// Обнуление
|
||||
diagram.removeChild(fpsTextField);
|
||||
diagram.removeChild(memoryTextField);
|
||||
diagram.removeChild(trianglesTextField);
|
||||
diagram.removeChild(graph);
|
||||
fpsTextField = null;
|
||||
memoryTextField = null;
|
||||
trianglesTextField = null;
|
||||
timerTextField = null;
|
||||
graph.bitmapData.dispose();
|
||||
graph = null;
|
||||
rect = null;
|
||||
// Отписка
|
||||
diagram.stage.removeEventListener(Event.ENTER_FRAME, updateDiagram);
|
||||
diagram.stage.removeEventListener(Event.RESIZE, resizeDiagram);
|
||||
});
|
||||
return diagram;
|
||||
}
|
||||
|
||||
private function resizeDiagram(e:Event = null):void {
|
||||
if (diagram.stage != null) {
|
||||
var coord:Point = diagram.parent.globalToLocal(new Point());
|
||||
if (_diagramAlign == StageAlign.TOP_LEFT || _diagramAlign == StageAlign.LEFT || _diagramAlign == StageAlign.BOTTOM_LEFT) {
|
||||
diagram.x = Math.round(coord.x + _diagramHorizontalMargin);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.TOP || _diagramAlign == StageAlign.BOTTOM) {
|
||||
diagram.x = Math.round(coord.x + diagram.stage.stageWidth/2 - graph.width/2);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.TOP_RIGHT || _diagramAlign == StageAlign.RIGHT || _diagramAlign == StageAlign.BOTTOM_RIGHT) {
|
||||
diagram.x = Math.round(coord.x + diagram.stage.stageWidth - _diagramHorizontalMargin - graph.width);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.TOP_LEFT || _diagramAlign == StageAlign.TOP || _diagramAlign == StageAlign.TOP_RIGHT) {
|
||||
diagram.y = Math.round(coord.y + _diagramVerticalMargin);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.LEFT || _diagramAlign == StageAlign.RIGHT) {
|
||||
diagram.y = Math.round(coord.y + diagram.stage.stageHeight/2 - (graph.y + graph.height)/2);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.BOTTOM_LEFT || _diagramAlign == StageAlign.BOTTOM || _diagramAlign == StageAlign.BOTTOM_RIGHT) {
|
||||
diagram.y = Math.round(coord.y + diagram.stage.stageHeight - _diagramVerticalMargin - graph.y - graph.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function updateDiagram(e:Event):void {
|
||||
var fps:Number;
|
||||
var mod:int;
|
||||
var time:int = getTimer();
|
||||
var stageFrameRate:int = diagram.stage.frameRate;
|
||||
|
||||
// FPS текст
|
||||
if (++fpsUpdateCounter == fpsUpdatePeriod) {
|
||||
fps = 1000*fpsUpdatePeriod/(time - previousPeriodTime);
|
||||
if (fps > stageFrameRate) fps = stageFrameRate;
|
||||
mod = fps*100 % 100;
|
||||
fpsTextField.text = "FPS: " + int(fps) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00"));
|
||||
previousPeriodTime = time;
|
||||
fpsUpdateCounter = 0;
|
||||
}
|
||||
// FPS график
|
||||
fps = 1000/(time - previousFrameTime);
|
||||
if (fps > stageFrameRate) fps = stageFrameRate;
|
||||
graph.bitmapData.scroll(1, 0);
|
||||
graph.bitmapData.fillRect(rect, 0x20FFFFFF);
|
||||
graph.bitmapData.setPixel32(0, 40*(1 - fps/stageFrameRate), 0xFFCCCCCC);
|
||||
previousFrameTime = time;
|
||||
|
||||
// Память текст
|
||||
var memory:int = System.totalMemory;
|
||||
memoryTextField.text = "MEM: " + bytesToString(memory);
|
||||
// Память график
|
||||
if (memory > maxMemory) maxMemory = memory;
|
||||
graph.bitmapData.setPixel32(0, 40*(1 - memory/maxMemory), 0xFFCCCC00);
|
||||
|
||||
// Треугольники текст
|
||||
trianglesTextField.text = "TRI: " + numTriangles;
|
||||
|
||||
// Время текст
|
||||
if (++timerUpdateCounter == timerUpdatePeriod) {
|
||||
if (timeCount > 0) {
|
||||
fps = timeSum/timeCount;
|
||||
mod = fps*100 % 100;
|
||||
timerTextField.text = "TMR: " + int(fps) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00"));
|
||||
} else {
|
||||
timerTextField.text = "TMR:";
|
||||
}
|
||||
timerUpdateCounter = 0;
|
||||
timeSum = 0;
|
||||
timeCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function startTimer():void {
|
||||
timer = getTimer();
|
||||
}
|
||||
|
||||
public function stopTimer():void {
|
||||
timeSum += getTimer() - timer;
|
||||
timeCount++;
|
||||
}
|
||||
|
||||
public function get diagramAlign():String {
|
||||
return _diagramAlign;
|
||||
}
|
||||
public function set diagramAlign(value:String):void {
|
||||
_diagramAlign = value;
|
||||
resizeDiagram();
|
||||
}
|
||||
|
||||
public function get diagramHorizontalMargin():Number {
|
||||
return _diagramHorizontalMargin;
|
||||
}
|
||||
public function set diagramHorizontalMargin(value:Number):void {
|
||||
_diagramHorizontalMargin = value;
|
||||
resizeDiagram();
|
||||
}
|
||||
|
||||
public function get diagramVerticalMargin():Number {
|
||||
return _diagramVerticalMargin;
|
||||
}
|
||||
public function set diagramVerticalMargin(value:Number):void {
|
||||
_diagramVerticalMargin = value;
|
||||
resizeDiagram();
|
||||
}
|
||||
|
||||
private function bytesToString(bytes:int):String {
|
||||
if (bytes < 1024) return bytes + "b";
|
||||
else if (bytes < 10240) return (bytes/1024).toFixed(2) + "kb";
|
||||
else if (bytes < 102400) return (bytes/1024).toFixed(1) + "kb";
|
||||
else if (bytes < 1048576) return (bytes >> 10) + "kb";
|
||||
else if (bytes < 10485760) return (bytes/1048576).toFixed(2) + "mb";
|
||||
else if (bytes < 104857600) return (bytes/1048576).toFixed(1) + "mb";
|
||||
else return (bytes >> 20) + "mb";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
import flash.display.Graphics;
|
||||
import flash.display.Sprite;
|
||||
import flash.geom.ColorTransform;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class Canvas extends Sprite {
|
||||
|
||||
static private const defaultColorTransform:ColorTransform = new ColorTransform();
|
||||
static private const collector:Vector.<Canvas> = new Vector.<Canvas>();
|
||||
static private var collectorLength:int = 0;
|
||||
|
||||
alternativa3d var gfx:Graphics = graphics;
|
||||
|
||||
private var modifiedGraphics:Boolean;
|
||||
private var modifiedAlpha:Boolean;
|
||||
private var modifiedBlendMode:Boolean;
|
||||
private var modifiedColorTransform:Boolean;
|
||||
private var modifiedFilters:Boolean;
|
||||
|
||||
alternativa3d var _numChildren:int = 0;
|
||||
alternativa3d var numDraws:int = 0;
|
||||
|
||||
public function Canvas() {
|
||||
mouseEnabled = false;
|
||||
mouseChildren = false;
|
||||
}
|
||||
|
||||
alternativa3d function getChildCanvas(useGraphics:Boolean, useChildren:Boolean, alpha:Number = 1, blendMode:String = "normal", colorTransform:ColorTransform = null, filters:Array = null):Canvas {
|
||||
var canvas:Canvas;
|
||||
var displayObject:DisplayObject;
|
||||
// Зачистка не канвасов
|
||||
while (_numChildren > numDraws && !((displayObject = getChildAt(_numChildren - 1 - numDraws)) is Canvas)) {
|
||||
removeChild(displayObject);
|
||||
_numChildren--;
|
||||
}
|
||||
// Получение канваса
|
||||
if (_numChildren > numDraws++) {
|
||||
canvas = displayObject as Canvas;
|
||||
// Зачистка
|
||||
canvas.gfx.clear();
|
||||
if (canvas._numChildren > 0 && !useChildren) {
|
||||
canvas.removeChildren(0);
|
||||
}
|
||||
} else {
|
||||
canvas = (collectorLength > 0) ? collector[--collectorLength] : new Canvas();
|
||||
addChildAt(canvas, 0);
|
||||
_numChildren++;
|
||||
}
|
||||
// Пометка о том, что в graphics будет что-то нарисовано
|
||||
canvas.modifiedGraphics = useGraphics;
|
||||
// Установка свойств
|
||||
if (alpha != 1) {
|
||||
canvas.alpha = alpha;
|
||||
canvas.modifiedAlpha = true;
|
||||
} else if (canvas.modifiedAlpha) {
|
||||
canvas.alpha = 1;
|
||||
canvas.modifiedAlpha = false;
|
||||
}
|
||||
if (blendMode != "normal") {
|
||||
canvas.blendMode = blendMode;
|
||||
canvas.modifiedBlendMode = true;
|
||||
} else if (canvas.modifiedBlendMode) {
|
||||
canvas.blendMode = "normal";
|
||||
canvas.modifiedBlendMode = false;
|
||||
}
|
||||
if (colorTransform != null) {
|
||||
colorTransform.alphaMultiplier = alpha;
|
||||
canvas.transform.colorTransform = colorTransform;
|
||||
canvas.modifiedColorTransform = true;
|
||||
} else if (canvas.modifiedColorTransform) {
|
||||
defaultColorTransform.alphaMultiplier = alpha;
|
||||
canvas.transform.colorTransform = defaultColorTransform;
|
||||
canvas.modifiedColorTransform = false;
|
||||
}
|
||||
if (filters != null) {
|
||||
canvas.filters = filters;
|
||||
canvas.modifiedFilters = true;
|
||||
} else if (canvas.modifiedFilters) {
|
||||
canvas.filters = null;
|
||||
canvas.modifiedFilters = false;
|
||||
}
|
||||
return canvas;
|
||||
}
|
||||
|
||||
alternativa3d function removeChildren(keep:int):void {
|
||||
for (var canvas:Canvas; _numChildren > keep; _numChildren--) {
|
||||
if ((canvas = removeChildAt(0) as Canvas) != null) {
|
||||
if (canvas.modifiedGraphics) canvas.gfx.clear();
|
||||
if (canvas._numChildren > 0) canvas.removeChildren(0);
|
||||
collector[collectorLength++] = canvas;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class Clipping {
|
||||
|
||||
/**
|
||||
* Объект отсекается целиком, если он полностью вне пирамиды видимости или пересекает nearClipping камеры.
|
||||
*/
|
||||
static public const BOUND_CULLING:int = 0;
|
||||
/**
|
||||
* Грань отсекается целиком, если она полностью вне пирамиды видимости или пересекает nearClipping камеры.
|
||||
*/
|
||||
static public const FACE_CULLING:int = 1;
|
||||
/**
|
||||
* Грань подрезается пирамидой видимости камеры.
|
||||
*/
|
||||
static public const FACE_CLIPPING:int = 2;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class Debug {
|
||||
|
||||
static public const NAMES:int = 1;
|
||||
static public const AXES:int = 2;
|
||||
static public const CENTERS:int = 4;
|
||||
static public const BOUNDS:int = 8;
|
||||
|
||||
static public const EDGES:int = 16;
|
||||
static public const VERTICES:int = 32;
|
||||
static public const NORMALS:int = 64;
|
||||
|
||||
static public const NODES:int = 128;
|
||||
static public const SPLITS:int = 256;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
public class Fragment {
|
||||
|
||||
static private var collector:Fragment;
|
||||
|
||||
public var next:Fragment;
|
||||
|
||||
public var negative:Fragment;
|
||||
public var positive:Fragment;
|
||||
|
||||
public var geometry:Geometry;
|
||||
|
||||
public var indices:Vector.<int> = new Vector.<int>();
|
||||
public var num:int = 0;
|
||||
|
||||
public var normalX:Number;
|
||||
public var normalY:Number;
|
||||
public var normalZ:Number;
|
||||
public var offset:Number;
|
||||
|
||||
static public function create():Fragment {
|
||||
if (collector != null) {
|
||||
var res:Fragment = collector;
|
||||
collector = collector.next;
|
||||
res.next = null;
|
||||
return res;
|
||||
} else {
|
||||
return new Fragment();
|
||||
}
|
||||
}
|
||||
|
||||
public function create():Fragment {
|
||||
if (collector != null) {
|
||||
var res:Fragment = collector;
|
||||
collector = collector.next;
|
||||
res.next = null;
|
||||
return res;
|
||||
} else {
|
||||
return new Fragment();
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy():void {
|
||||
num = 0;
|
||||
next = collector;
|
||||
collector = this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,73 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.display.BitmapData;
|
||||
import flash.filters.ConvolutionFilter;
|
||||
import flash.geom.Matrix;
|
||||
import flash.geom.Point;
|
||||
import flash.geom.Rectangle;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Объект, представляющий текстуру в виде последовательности её уменьшенных копий.
|
||||
* Каждая следующая в два раза меньше предыдущей. Последняя имеет размер 1х1 пиксел.
|
||||
* Чем дальше от камеры отрисовываемый объект, тем меньшая текстура выбирается.
|
||||
* Это позволяет получить лучший визуальный результат и большую производительность.
|
||||
*/
|
||||
public class MipMap {
|
||||
|
||||
/**
|
||||
* Мип-текстуры
|
||||
*/
|
||||
public var textures:Vector.<BitmapData> = new Vector.<BitmapData>();
|
||||
/**
|
||||
* Количество мип-текстур
|
||||
*/
|
||||
public var num:int;
|
||||
/**
|
||||
* Отношение размера пиксела текстуры к единице измерения трёхмерного пространства
|
||||
*/
|
||||
public var resolution:Number;
|
||||
|
||||
static private const filter:ConvolutionFilter = new ConvolutionFilter(2, 2, [1, 1, 1, 1], 4, 0, false, true);
|
||||
static private const point:Point = new Point();
|
||||
static private const matrix:Matrix = new Matrix();
|
||||
static private const rect:Rectangle = new Rectangle();
|
||||
public function MipMap(texture:BitmapData, resolution:Number = 1) {
|
||||
var bmp:BitmapData = new BitmapData(texture.width, texture.height, texture.transparent);
|
||||
var current:BitmapData = textures[num++] = texture;
|
||||
filter.preserveAlpha = !texture.transparent;
|
||||
var w:Number = rect.width = texture.width, h:Number = rect.height = texture.height;
|
||||
while (w > 1 && h > 1 && rect.width > 1 && rect.height > 1) {
|
||||
bmp.applyFilter(current, rect, point, filter);
|
||||
rect.width = w >> 1;
|
||||
rect.height = h >> 1;
|
||||
matrix.a = rect.width/w;
|
||||
matrix.d = rect.height/h;
|
||||
w *= 0.5;
|
||||
h *= 0.5;
|
||||
current = new BitmapData(rect.width, rect.height, texture.transparent, 0);
|
||||
current.draw(bmp, matrix, null, null, null, false);
|
||||
textures[num++] = current;
|
||||
}
|
||||
bmp.dispose();
|
||||
this.resolution = resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение мип-уровня в зависимости от удалённости объекта от камеры
|
||||
* @param distance Z-координата объекта в пространстве камеры
|
||||
* @param camera Камера
|
||||
* @return Индекс в списке мип-текстур textures
|
||||
*/
|
||||
public function getLevel(distance:Number, camera:Camera3D):int {
|
||||
var level:int = Math.log(distance/(camera.focalLength*resolution))*1.442695040888963387;
|
||||
if (level < 0) return 0; else if (level >= num) return num - 1;
|
||||
return level;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class MipMapping {
|
||||
|
||||
/**
|
||||
* Нет мипмаппинга.
|
||||
*/
|
||||
static public const NONE:int = 0;
|
||||
/**
|
||||
* Мипмаппинг по удалённости объекта от камеры.
|
||||
*/
|
||||
static public const PER_OBJECT:int = 1;
|
||||
|
||||
//static public const PER_POLYGON:int = 2;
|
||||
//static public const PER_PIXEL:int = 3;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
public final class Node {
|
||||
|
||||
public var positive:Node;
|
||||
public var negative:Node;
|
||||
|
||||
public var normalX:Number;
|
||||
public var normalY:Number;
|
||||
public var normalZ:Number;
|
||||
|
||||
public var offset:Number;
|
||||
public var offsetMin:Number;
|
||||
public var offsetMax:Number;
|
||||
|
||||
public var boundBox:BoundBox;
|
||||
|
||||
public var objects:Vector.<Object3D>;
|
||||
public var bounds:Vector.<BoundBox>;
|
||||
|
||||
public var numObjects:int = 0;
|
||||
public var numNonOccluders:int = 0;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.geom.ColorTransform;
|
||||
import flash.geom.Matrix3D;
|
||||
import flash.geom.Utils3D;
|
||||
import flash.utils.getQualifiedClassName;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Базовый трёхмерный объект
|
||||
*/
|
||||
public class Object3D {
|
||||
|
||||
public var name:String;
|
||||
/**
|
||||
* Матрица трансформации. Управлять трансформацией объекта можно только через это свойство
|
||||
* путём назначения новой матрицы или с помощью методов матрицы.
|
||||
*/
|
||||
public var matrix:Matrix3D = new Matrix3D();
|
||||
public var visible:Boolean = true;
|
||||
|
||||
public var alpha:Number = 1;
|
||||
public var blendMode:String = "normal";
|
||||
public var colorTransform:ColorTransform = null;
|
||||
public var filters:Array = null;
|
||||
|
||||
alternativa3d var _parent:Object3DContainer;
|
||||
|
||||
alternativa3d var _boundBox:BoundBox;
|
||||
|
||||
alternativa3d var culling:int = 0;
|
||||
|
||||
alternativa3d var cameraMatrix:Matrix3D = new Matrix3D();
|
||||
|
||||
static private const boundBoxVertices:Vector.<Number> = new Vector.<Number>(24, true);
|
||||
|
||||
alternativa3d function get canDraw():Boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {}
|
||||
|
||||
alternativa3d function debug(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
||||
var debugResult:int = camera.checkInDebug(this);
|
||||
if (debugResult == 0) return;
|
||||
var canvas:Canvas = parentCanvas.getChildCanvas(true, false);
|
||||
if (debugResult & Debug.AXES) object.drawAxes(camera, canvas);
|
||||
if (debugResult & Debug.CENTERS) object.drawCenter(camera, canvas);
|
||||
if (debugResult & Debug.NAMES) object.drawName(camera, canvas);
|
||||
if (debugResult & Debug.BOUNDS) object.drawBoundBox(camera, canvas);
|
||||
}
|
||||
|
||||
alternativa3d function getGeometry(camera:Camera3D, object:Object3D):Geometry {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function get boundBox():BoundBox {
|
||||
return _boundBox;
|
||||
}
|
||||
|
||||
public function set boundBox(value:BoundBox):void {
|
||||
_boundBox = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Расчёт баунда
|
||||
* @param matrix Трансформация пространства, в системе которого расчитывается баунд.
|
||||
* Если этот параметр не указан, баунд расчитается в локальных координатах объекта.
|
||||
* @param boundBox Баунд, в который записывается результат.
|
||||
* Если этот параметр не указан, создаётся новый экземпляр.
|
||||
* @return Расчитанный баунд.
|
||||
*/
|
||||
public function calculateBoundBox(matrix:Matrix3D = null, boundBox:BoundBox = null):BoundBox {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function get parent():Object3DContainer {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
alternativa3d function cullingInCamera(camera:Camera3D, parentCulling:int):int {
|
||||
if (camera.occludedAll) return -1;
|
||||
culling = parentCulling;
|
||||
var i:int, infront:Boolean, behind:Boolean, boundBox:BoundBox = this.boundBox, numOccluders:int = camera.numOccluders, cull:Boolean = culling > 0 && boundBox != null, occlude:Boolean = numOccluders > 0 && boundBox != null;
|
||||
// Расчёт точек баунда в координатах камеры
|
||||
if (cull || occlude) boundBoxVertices[0] = boundBoxVertices[3] = boundBoxVertices[6] = boundBoxVertices[9] = boundBox.minX, boundBoxVertices[1] = boundBoxVertices[4] = boundBoxVertices[13] = boundBoxVertices[16] = boundBox.minY, boundBoxVertices[2] = boundBoxVertices[8] = boundBoxVertices[14] = boundBoxVertices[20] = boundBox.minZ, boundBoxVertices[12] = boundBoxVertices[15] = boundBoxVertices[18] = boundBoxVertices[21] = boundBox.maxX, boundBoxVertices[7] = boundBoxVertices[10] = boundBoxVertices[19] = boundBoxVertices[22] = boundBox.maxY, boundBoxVertices[5] = boundBoxVertices[11] = boundBoxVertices[17] = boundBoxVertices[23] = boundBox.maxZ, cameraMatrix.transformVectors(boundBoxVertices, boundBoxVertices);
|
||||
// Куллинг
|
||||
if (cull) {
|
||||
if (culling & 1) {
|
||||
for (i = 2, infront = false, behind = false; i <= 23; i += 3) {
|
||||
if (boundBoxVertices[i] > camera.nearClipping) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
// TODO: проверка не нужна
|
||||
if (infront) culling &= 62;
|
||||
}
|
||||
}
|
||||
if (culling & 2) {
|
||||
for (i = 2, infront = false, behind = false; i <= 23; i += 3) {
|
||||
if (boundBoxVertices[i] < camera.farClipping) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 61;
|
||||
}
|
||||
}
|
||||
if (culling & 4) {
|
||||
for (i = 0, infront = false, behind = false; i <= 21; i += 3) {
|
||||
if (-boundBoxVertices[i] < boundBoxVertices[int(i + 2)]) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 59;
|
||||
}
|
||||
}
|
||||
if (culling & 8) {
|
||||
for (i = 0, infront = false, behind = false; i <= 21; i += 3) {
|
||||
if (boundBoxVertices[i] < boundBoxVertices[int(i + 2)]) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 55;
|
||||
}
|
||||
}
|
||||
if (culling & 16) {
|
||||
for (i = 1, infront = false, behind = false; i <= 22; i += 3) {
|
||||
if (-boundBoxVertices[i] < boundBoxVertices[int(i + 1)]) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 47;
|
||||
}
|
||||
}
|
||||
if (culling & 32) {
|
||||
for (i = 1, infront = false, behind = false; i <= 22; i += 3) {
|
||||
if (boundBoxVertices[i] < boundBoxVertices[int(i + 1)]) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 31;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Окклюдинг
|
||||
if (occlude) {
|
||||
for (var o:int = 0; o < numOccluders; o++) {
|
||||
var planeOccluder:Vector.<Number> = camera.occlusionPlanes[o], planeOccluderLength:int = planeOccluder.length;
|
||||
for (var ni:int = 0; ni < planeOccluderLength; ni += 3) {
|
||||
var nx:Number = planeOccluder[ni], ny:Number = planeOccluder[int(ni + 1)], nz:Number = planeOccluder[int(ni + 2)];
|
||||
for (i = 0; i < 24; i += 3) if (nx*boundBoxVertices[i] + ny*boundBoxVertices[int(i + 1)] + nz*boundBoxVertices[int(i + 2)] >= 0) break;
|
||||
if (i < 24) break;
|
||||
}
|
||||
if (ni == planeOccluderLength) return -1;
|
||||
}
|
||||
}
|
||||
return culling;
|
||||
}
|
||||
|
||||
alternativa3d function drawAxes(camera:Camera3D, canvas:Canvas):void {
|
||||
|
||||
}
|
||||
|
||||
alternativa3d function drawCenter(camera:Camera3D, canvas:Canvas):void {
|
||||
|
||||
}
|
||||
|
||||
alternativa3d function drawName(camera:Camera3D, canvas:Canvas):void {
|
||||
|
||||
}
|
||||
|
||||
static private const boundBoxProjectedVertices:Vector.<Number> = new Vector.<Number>(16, true);
|
||||
static private const boundBoxUVTs:Vector.<Number> = new Vector.<Number>(24, true);
|
||||
alternativa3d function drawBoundBox(camera:Camera3D, canvas:Canvas, color:int = -1):void {
|
||||
|
||||
var boundBox:BoundBox = this.boundBox;
|
||||
if (boundBox == null) return;
|
||||
|
||||
boundBoxVertices[0] = boundBoxVertices[3] = boundBoxVertices[6] = boundBoxVertices[9] = boundBox.minX;
|
||||
boundBoxVertices[1] = boundBoxVertices[4] = boundBoxVertices[13] = boundBoxVertices[16] = boundBox.minY;
|
||||
boundBoxVertices[2] = boundBoxVertices[8] = boundBoxVertices[14] = boundBoxVertices[20] = boundBox.minZ;
|
||||
|
||||
boundBoxVertices[12] = boundBoxVertices[15] = boundBoxVertices[18] = boundBoxVertices[21] = boundBox.maxX;
|
||||
boundBoxVertices[7] = boundBoxVertices[10] = boundBoxVertices[19] = boundBoxVertices[22] = boundBox.maxY;
|
||||
boundBoxVertices[5] = boundBoxVertices[11] = boundBoxVertices[17] = boundBoxVertices[23] = boundBox.maxZ;
|
||||
|
||||
cameraMatrix.transformVectors(boundBoxVertices, boundBoxVertices);
|
||||
for (var i:int = 0; i < 8; i++) {
|
||||
if (boundBoxVertices[int(i*3 +2)] <= 0) return;
|
||||
}
|
||||
Utils3D.projectVectors(camera.projectionMatrix, boundBoxVertices, boundBoxProjectedVertices, boundBoxUVTs);
|
||||
canvas.gfx.endFill();
|
||||
canvas.gfx.lineStyle(0, (color < 0) ? ((culling > 0) ? 0xFFFF00 : 0x00FF00) : color);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[0], boundBoxProjectedVertices[1]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[2], boundBoxProjectedVertices[3]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[6], boundBoxProjectedVertices[7]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[4], boundBoxProjectedVertices[5]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[0], boundBoxProjectedVertices[1]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[8], boundBoxProjectedVertices[9]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[10], boundBoxProjectedVertices[11]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[14], boundBoxProjectedVertices[15]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[12], boundBoxProjectedVertices[13]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[8], boundBoxProjectedVertices[9]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[0], boundBoxProjectedVertices[1]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[8], boundBoxProjectedVertices[9]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[2], boundBoxProjectedVertices[3]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[10], boundBoxProjectedVertices[11]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[4], boundBoxProjectedVertices[5]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[12], boundBoxProjectedVertices[13]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[6], boundBoxProjectedVertices[7]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[14], boundBoxProjectedVertices[15]);
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
var className:String = getQualifiedClassName(this);
|
||||
return "[" + className.substr(className.indexOf("::") + 2) + " " + name + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.geom.ColorTransform;
|
||||
import flash.geom.Matrix3D;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Базовый контейнер трёхмерных объектов.
|
||||
* Логика контейнеров и child-parent-отношений идентична логике
|
||||
* displayObject'ов во Flash.
|
||||
*/
|
||||
public class Object3DContainer extends Object3D {
|
||||
|
||||
protected var children:Vector.<Object3D> = new Vector.<Object3D>();
|
||||
protected var _numChildren:int = 0;
|
||||
|
||||
protected var visibleChildren:Vector.<Object3D> = new Vector.<Object3D>();
|
||||
protected var numVisibleChildren:int = 0;
|
||||
|
||||
override alternativa3d function get canDraw():Boolean {
|
||||
return _numChildren > 0;
|
||||
}
|
||||
|
||||
override alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
||||
// Сбор видимых объектов
|
||||
numVisibleChildren = 0;
|
||||
for (var i:int = 0; i < _numChildren; i++) {
|
||||
var child:Object3D = children[i];
|
||||
if (child.visible && child.canDraw) {
|
||||
child.cameraMatrix.identity();
|
||||
child.cameraMatrix.prepend(object.cameraMatrix);
|
||||
child.cameraMatrix.prepend(child.matrix);
|
||||
if (child.cullingInCamera(camera, object.culling) >= 0) {
|
||||
visibleChildren[numVisibleChildren] = child;
|
||||
numVisibleChildren++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Если есть видимые объекты
|
||||
if (numVisibleChildren > 0) {
|
||||
// Подготовка канваса
|
||||
var canvas:Canvas = parentCanvas.getChildCanvas(false, true, object.alpha, object.blendMode, object.colorTransform, object.filters);
|
||||
canvas.numDraws = 0;
|
||||
// Отрисовка видимых объектов
|
||||
drawVisibleChildren(camera, object, canvas);
|
||||
// Если была отрисовка
|
||||
if (canvas.numDraws > 0) {
|
||||
canvas.removeChildren(canvas.numDraws);
|
||||
} else {
|
||||
parentCanvas.numDraws--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function drawVisibleChildren(camera:Camera3D, object:Object3D, canvas:Canvas):void {
|
||||
for (var i:int = numVisibleChildren - 1; i >= 0; i--) {
|
||||
var child:Object3D = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
override alternativa3d function getGeometry(camera:Camera3D, object:Object3D):Geometry {
|
||||
var i:int;
|
||||
var first:Geometry;
|
||||
var last:Geometry;
|
||||
var geometry:Geometry;
|
||||
for (i = 0; i < _numChildren; i++) {
|
||||
var child:Object3D = children[i];
|
||||
if (child.visible && child.canDraw) {
|
||||
child.cameraMatrix.identity();
|
||||
child.cameraMatrix.prepend(object.cameraMatrix);
|
||||
child.cameraMatrix.prepend(child.matrix);
|
||||
if (child.cullingInCamera(camera, object.culling) >= 0) {
|
||||
geometry = child.getGeometry(camera, child);
|
||||
if (geometry != null) {
|
||||
if (first != null) {
|
||||
last.next = geometry;
|
||||
} else {
|
||||
first = geometry;
|
||||
last = geometry;
|
||||
}
|
||||
while (last.next != null) {
|
||||
last = last.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (object.alpha != 1) {
|
||||
geometry = first;
|
||||
while (geometry != null) {
|
||||
geometry.alpha *= object.alpha;
|
||||
geometry = geometry.next;
|
||||
}
|
||||
}
|
||||
if (object.blendMode != "normal") {
|
||||
geometry = first;
|
||||
while (geometry != null) {
|
||||
if (geometry.blendMode == "normal") {
|
||||
geometry.blendMode = object.blendMode;
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
}
|
||||
if (object.colorTransform != null) {
|
||||
geometry = first;
|
||||
while (geometry != null) {
|
||||
if (geometry.colorTransform != null) {
|
||||
var ct:ColorTransform = new ColorTransform(object.colorTransform.redMultiplier, object.colorTransform.greenMultiplier, object.colorTransform.blueMultiplier, object.colorTransform.alphaMultiplier, object.colorTransform.redOffset, object.colorTransform.greenOffset, object.colorTransform.blueOffset, object.colorTransform.alphaOffset);
|
||||
ct.concat(geometry.colorTransform);
|
||||
geometry.colorTransform = ct;
|
||||
} else {
|
||||
geometry.colorTransform = object.colorTransform;
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
}
|
||||
if (object.filters != null) {
|
||||
geometry = first;
|
||||
while (geometry != null) {
|
||||
if (geometry.filters != null) {
|
||||
var fs:Array = new Array();
|
||||
var fsLength:int = 0;
|
||||
var num:int = geometry.filters.length;
|
||||
for (i = 0; i < num; i++) {
|
||||
fs[fsLength] = geometry.filters[i]; fsLength++;
|
||||
}
|
||||
num = object.filters.length;
|
||||
for (i = 0; i < num; i++) {
|
||||
fs[fsLength] = object.filters[i]; fsLength++;
|
||||
}
|
||||
geometry.filters = fs;
|
||||
} else {
|
||||
geometry.filters = object.filters;
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
override public function calculateBoundBox(matrix:Matrix3D = null, boundBox:BoundBox = null):BoundBox {
|
||||
var m:Matrix3D = matrix != null ? matrix.clone() : new Matrix3D();
|
||||
// Если указан баунд-бокс
|
||||
if (boundBox != null) {
|
||||
boundBox.infinity();
|
||||
} else {
|
||||
boundBox = new BoundBox();
|
||||
}
|
||||
// Расчитываем баунды объектов
|
||||
var childBoundBox:BoundBox = new BoundBox();
|
||||
var childMatrix:Matrix3D = new Matrix3D();
|
||||
for (var i:int = 0; i < _numChildren; i++) {
|
||||
var child:Object3D = children[i];
|
||||
childMatrix.identity();
|
||||
childMatrix.prepend(m);
|
||||
childMatrix.prepend(child.matrix);
|
||||
child.calculateBoundBox(childMatrix, childBoundBox);
|
||||
boundBox.minX = (childBoundBox.minX < boundBox.minX) ? childBoundBox.minX : boundBox.minX;
|
||||
boundBox.minY = (childBoundBox.minY < boundBox.minY) ? childBoundBox.minY : boundBox.minY;
|
||||
boundBox.minZ = (childBoundBox.minZ < boundBox.minZ) ? childBoundBox.minZ : boundBox.minZ;
|
||||
boundBox.maxX = (childBoundBox.maxX > boundBox.maxX) ? childBoundBox.maxX : boundBox.maxX;
|
||||
boundBox.maxY = (childBoundBox.maxY > boundBox.maxY) ? childBoundBox.maxY : boundBox.maxY;
|
||||
boundBox.maxZ = (childBoundBox.maxZ > boundBox.maxZ) ? childBoundBox.maxZ : boundBox.maxZ;
|
||||
}
|
||||
return boundBox;
|
||||
}
|
||||
|
||||
public function addChild(child:Object3D):void {
|
||||
children[_numChildren++] = child;
|
||||
child._parent = this;
|
||||
}
|
||||
|
||||
public function removeChild(child:Object3D):void {
|
||||
var i:int = children.indexOf(child);
|
||||
if (i < 0) throw new ArgumentError("Child not found");
|
||||
_numChildren--;
|
||||
for (; i < _numChildren; i++) children[i] = children[int(i + 1)];
|
||||
children.length = _numChildren;
|
||||
child._parent = null;
|
||||
}
|
||||
|
||||
public function hasChild(child:Object3D):Boolean {
|
||||
return children.indexOf(child) > -1;
|
||||
}
|
||||
|
||||
public function getChildAt(index:uint):Object3D {
|
||||
return children[index];
|
||||
}
|
||||
|
||||
public function get numChildren():uint {
|
||||
return _numChildren;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class Sorting {
|
||||
|
||||
/**
|
||||
* Грани не сортируются.
|
||||
*/
|
||||
static public const NONE:int = 0;
|
||||
/**
|
||||
* Грани сортируются по средним Z.
|
||||
*/
|
||||
static public const AVERAGE_Z:int = 1;
|
||||
/**
|
||||
* Грани находятся в BSP-дереве.
|
||||
*/
|
||||
static public const STATIC_BSP:int = 2;
|
||||
/**
|
||||
* Грани при отрисовке образуют BSP-дерево.
|
||||
*/
|
||||
static public const DYNAMIC_BSP:int = 3;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class BackfaceCulling {
|
||||
|
||||
/**
|
||||
* Отсечение по динамически расчитываемым нормалям.
|
||||
*/
|
||||
static public const DYNAMIC_NORMALS:int = 0;
|
||||
/**
|
||||
* Отсечение по предрасчитанным нормалям.
|
||||
*/
|
||||
static public const STATIC_NORMALS:int = 1;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
import flash.geom.Matrix3D;
|
||||
|
||||
public class BoundBox {
|
||||
|
||||
public var minX:Number = Number.MAX_VALUE;
|
||||
public var minY:Number = Number.MAX_VALUE;
|
||||
public var minZ:Number = Number.MAX_VALUE;
|
||||
public var maxX:Number = -Number.MAX_VALUE;
|
||||
public var maxY:Number = -Number.MAX_VALUE;
|
||||
public var maxZ:Number = -Number.MAX_VALUE;
|
||||
|
||||
public function setSize(minX:Number, minY:Number, minZ:Number, maxX:Number, maxY:Number, maxZ:Number):void {
|
||||
this.minX = minX;
|
||||
this.minY = minY;
|
||||
this.minZ = minZ;
|
||||
this.maxX = maxX;
|
||||
this.maxY = maxY;
|
||||
this.maxZ = maxZ;
|
||||
}
|
||||
|
||||
public function addBoundBox(boundBox:BoundBox):void {
|
||||
minX = (boundBox.minX < minX) ? boundBox.minX : minX;
|
||||
minY = (boundBox.minY < minY) ? boundBox.minY : minY;
|
||||
minZ = (boundBox.minZ < minZ) ? boundBox.minZ : minZ;
|
||||
maxX = (boundBox.maxX > maxX) ? boundBox.maxX : maxX;
|
||||
maxY = (boundBox.maxY > maxY) ? boundBox.maxY : maxY;
|
||||
maxZ = (boundBox.maxZ > maxZ) ? boundBox.maxZ : maxZ;
|
||||
}
|
||||
|
||||
public function addPoint(x:Number, y:Number, z:Number):void {
|
||||
if (x < minX) minX = x;
|
||||
if (x > maxX) maxX = x;
|
||||
if (y < minY) minY = y;
|
||||
if (y > maxY) maxY = y;
|
||||
if (z < minZ) minZ = z;
|
||||
if (z > maxZ) maxZ = z;
|
||||
}
|
||||
|
||||
public function infinity():void {
|
||||
minX = minY = minZ = Number.MAX_VALUE;
|
||||
maxX = maxY = maxZ = -Number.MAX_VALUE;
|
||||
}
|
||||
|
||||
public function copyFrom(boundBox:BoundBox):void {
|
||||
minX = boundBox.minX;
|
||||
minY = boundBox.minY;
|
||||
minZ = boundBox.minZ;
|
||||
maxX = boundBox.maxX;
|
||||
maxY = boundBox.maxY;
|
||||
maxZ = boundBox.maxZ;
|
||||
}
|
||||
|
||||
public function clone():BoundBox {
|
||||
var clone:BoundBox = new BoundBox();
|
||||
clone.copyFrom(this);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
return "BoundBox [" + minX.toFixed(2) + ", " + minY.toFixed(2) + ", " + minZ.toFixed(2) + " - " + maxX.toFixed(2) + ", " + maxY.toFixed(2) + ", " + maxZ.toFixed(2) + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
414
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Camera3D.as
Normal file
414
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Camera3D.as
Normal file
@@ -0,0 +1,414 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.display.Bitmap;
|
||||
import flash.display.BitmapData;
|
||||
import flash.display.Sprite;
|
||||
import flash.display.StageAlign;
|
||||
import flash.events.Event;
|
||||
import flash.geom.Matrix3D;
|
||||
import flash.geom.Point;
|
||||
import flash.geom.Rectangle;
|
||||
import flash.geom.Vector3D;
|
||||
import flash.system.System;
|
||||
import flash.text.TextField;
|
||||
import flash.text.TextFieldAutoSize;
|
||||
import flash.text.TextFormat;
|
||||
import flash.utils.Dictionary;
|
||||
import flash.utils.getDefinitionByName;
|
||||
import flash.utils.getQualifiedClassName;
|
||||
import flash.utils.getQualifiedSuperclassName;
|
||||
import flash.utils.getTimer;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class Camera3D extends Object3D {
|
||||
|
||||
/**
|
||||
* Вьюпорт камеры.
|
||||
*/
|
||||
public var canvas:Canvas;
|
||||
public var fov:Number = Math.PI/2;
|
||||
/**
|
||||
* Ширина вьюпорта.
|
||||
*/
|
||||
public var width:Number = 500;
|
||||
/**
|
||||
* Высота вьюпорта.
|
||||
*/
|
||||
public var height:Number = 500;
|
||||
|
||||
public var nearClipping:Number = 0;
|
||||
public var farClipping:Number = 5000;
|
||||
public var farFalloff:Number = 4000;
|
||||
|
||||
// Матрица проецирования
|
||||
alternativa3d var projectionMatrix:Matrix3D;
|
||||
alternativa3d var projectionMatrixData:Vector.<Number> = new Vector.<Number>(16, true);
|
||||
// Параметры перспективы
|
||||
alternativa3d var viewSize:Number;
|
||||
alternativa3d var viewSizeX:Number;
|
||||
alternativa3d var viewSizeY:Number;
|
||||
alternativa3d var perspectiveScaleX:Number;
|
||||
alternativa3d var perspectiveScaleY:Number;
|
||||
alternativa3d var focalLength:Number;
|
||||
// Перекрытия
|
||||
alternativa3d var occlusionPlanes:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
|
||||
alternativa3d var occlusionEdges:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
|
||||
alternativa3d var numOccluders:int;
|
||||
alternativa3d var occludedAll:Boolean;
|
||||
|
||||
public function Camera3D() {
|
||||
updateProjection();
|
||||
}
|
||||
|
||||
override alternativa3d function get canDraw():Boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отрисовка иерархии объектов, в которой находится камера.
|
||||
* Перед render(), если менялись параметры камеры, нужно вызвать updateProjection().
|
||||
*/
|
||||
public function render():void {
|
||||
// Расчёт матрицы перевода из рута в камеру
|
||||
cameraMatrix.identity();
|
||||
var object:Object3D = this;
|
||||
while (object._parent != null) {
|
||||
cameraMatrix.append(object.matrix);
|
||||
object = object._parent;
|
||||
}
|
||||
cameraMatrix.invert();
|
||||
cameraMatrix.appendScale(perspectiveScaleX, perspectiveScaleY, 1);
|
||||
|
||||
numOccluders = 0;
|
||||
occludedAll = false;
|
||||
|
||||
numTriangles = 0;
|
||||
|
||||
// Отрисовка
|
||||
if (object.visible && object.canDraw) {
|
||||
object.cameraMatrix.identity();
|
||||
object.cameraMatrix.prepend(cameraMatrix);
|
||||
object.cameraMatrix.prepend(object.matrix);
|
||||
if (object.cullingInCamera(this, 63) >= 0) {
|
||||
// Отрисовка объекта
|
||||
canvas.numDraws = 0;
|
||||
if (debugMode) object.debug(this, object, canvas);
|
||||
object.draw(this, object, canvas);
|
||||
// Зачистка ненужных канвасов
|
||||
canvas.removeChildren(canvas.numDraws);
|
||||
} else {
|
||||
// Если отсеклось, зачищаем рутовый канвас
|
||||
canvas.removeChildren(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* После изменения параметров fov, width, height нужно вызвать этот метод.
|
||||
*/
|
||||
public function updateProjection():void {
|
||||
// Расчёт параметров перспективы
|
||||
viewSize = Math.sqrt(width*width + height*height)*0.5;
|
||||
focalLength = viewSize/Math.tan(fov*0.5);
|
||||
viewSizeX = width*0.5;
|
||||
viewSizeY = height*0.5;
|
||||
perspectiveScaleX = focalLength/viewSizeX;
|
||||
perspectiveScaleY = focalLength/viewSizeY;
|
||||
// Подготовка матрицы проецирования
|
||||
projectionMatrixData[0] = viewSizeX;
|
||||
projectionMatrixData[5] = viewSizeY;
|
||||
projectionMatrixData[10] = 1;
|
||||
projectionMatrixData[11] = 1;
|
||||
projectionMatrix = new Matrix3D(projectionMatrixData);
|
||||
}
|
||||
|
||||
private static var _tmpv:Vector.<Number> = new Vector.<Number>(3);
|
||||
|
||||
/**
|
||||
* @param v
|
||||
* @param result
|
||||
*/
|
||||
public function projectGlobal(v:Vector3D, result:Vector3D):void {
|
||||
_tmpv[0] = v.x; _tmpv[1] = v.y; _tmpv[2] = v.z;
|
||||
cameraMatrix.transformVectors(_tmpv, _tmpv);
|
||||
projectionMatrix.transformVectors(_tmpv, _tmpv);
|
||||
result.z = _tmpv[2];
|
||||
result.x = _tmpv[0]/result.z;
|
||||
result.y = _tmpv[1]/result.z;
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
|
||||
// Режим отладки
|
||||
public var debugMode:Boolean = false;
|
||||
|
||||
// Список объектов дебага
|
||||
private var debugSet:Object = new Object();
|
||||
|
||||
// Добавить в дебаг
|
||||
public function addToDebug(debug:int, ... rest):void {
|
||||
if (!debugSet[debug]) debugSet[debug] = new Dictionary();
|
||||
for (var i:int = 0; i < rest.length;) debugSet[debug][rest[i++]] = true;
|
||||
}
|
||||
|
||||
// Убрать из дебага
|
||||
public function removeFromDebug(debug:int, ... rest):void {
|
||||
if (debugSet[debug]) {
|
||||
for (var i:int = 0; i < rest.length;) delete debugSet[debug][rest[i++]];
|
||||
for (var key:* in debugSet[debug]);
|
||||
if (!key) delete debugSet[debug];
|
||||
}
|
||||
}
|
||||
|
||||
// Проверка, находится ли объект или один из классов, от которых он нследован, в дебаге
|
||||
alternativa3d function checkInDebug(object:Object3D):int {
|
||||
var res:int = 0;
|
||||
for (var debug:int = 1; debug <= 256; debug = debug << 1) {
|
||||
if (debugSet[debug]) {
|
||||
if (debugSet[debug][Object3D] || debugSet[debug][object]) {
|
||||
res |= debug;
|
||||
} else {
|
||||
var objectClass:Class = getDefinitionByName(getQualifiedClassName(object)) as Class;
|
||||
while (objectClass != Object3D) {
|
||||
if (debugSet[debug][objectClass]) {
|
||||
res |= debug;
|
||||
break;
|
||||
}
|
||||
objectClass = Class(getDefinitionByName(getQualifiedSuperclassName(objectClass)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public var diagram:Sprite = createDiagram();
|
||||
|
||||
private var fpsTextField:TextField;
|
||||
private var memoryTextField:TextField;
|
||||
private var trianglesTextField:TextField;
|
||||
private var timerTextField:TextField;
|
||||
private var graph:Bitmap;
|
||||
private var rect:Rectangle;
|
||||
|
||||
private var _diagramAlign:String = "TR";
|
||||
private var _diagramHorizontalMargin:Number = 2;
|
||||
private var _diagramVerticalMargin:Number = 2;
|
||||
|
||||
public var fpsUpdatePeriod:int = 10;
|
||||
private var fpsUpdateCounter:int;
|
||||
private var previousFrameTime:int;
|
||||
private var previousPeriodTime:int;
|
||||
|
||||
private var maxMemory:int;
|
||||
alternativa3d var numTriangles:int;
|
||||
|
||||
public var timerUpdatePeriod:int = 10;
|
||||
private var timerUpdateCounter:int;
|
||||
private var timeSum:int;
|
||||
private var timeCount:int;
|
||||
private var timer:int;
|
||||
|
||||
private function createDiagram():Sprite {
|
||||
var diagram:Sprite = new Sprite();
|
||||
diagram.mouseEnabled = false;
|
||||
diagram.mouseChildren = false;
|
||||
// Инициализация диаграммы
|
||||
diagram.addEventListener(Event.ADDED_TO_STAGE, function():void {
|
||||
// FPS
|
||||
fpsTextField = new TextField();
|
||||
fpsTextField.defaultTextFormat = new TextFormat("Tahoma", 10, 0xCCCCCC);
|
||||
fpsTextField.autoSize = TextFieldAutoSize.LEFT;
|
||||
fpsTextField.text = "FPS: " + Number(diagram.stage.frameRate).toFixed(2);
|
||||
fpsTextField.selectable = false;
|
||||
fpsTextField.x = -3;
|
||||
fpsTextField.y = -5;
|
||||
diagram.addChild(fpsTextField);
|
||||
// Память
|
||||
memoryTextField = new TextField();
|
||||
memoryTextField.defaultTextFormat = new TextFormat("Tahoma", 10, 0xCCCC00);
|
||||
memoryTextField.autoSize = TextFieldAutoSize.LEFT;
|
||||
memoryTextField.text = "MEM: " + bytesToString(System.totalMemory);
|
||||
memoryTextField.selectable = false;
|
||||
memoryTextField.x = -3;
|
||||
memoryTextField.y = 4;
|
||||
diagram.addChild(memoryTextField);
|
||||
// Треугольники
|
||||
trianglesTextField = new TextField();
|
||||
trianglesTextField.defaultTextFormat = new TextFormat("Tahoma", 10, 0xFF6600);
|
||||
trianglesTextField.autoSize = TextFieldAutoSize.LEFT;
|
||||
trianglesTextField.text = "TRI: " + 0;
|
||||
trianglesTextField.selectable = false;
|
||||
trianglesTextField.x = -2;
|
||||
trianglesTextField.y = 13;
|
||||
diagram.addChild(trianglesTextField);
|
||||
// Время выполнения метода
|
||||
timerTextField = new TextField();
|
||||
timerTextField.defaultTextFormat = new TextFormat("Tahoma", 10, 0x0066FF);
|
||||
timerTextField.autoSize = TextFieldAutoSize.LEFT;
|
||||
timerTextField.text = "TMR:";
|
||||
timerTextField.selectable = false;
|
||||
timerTextField.x = -2;
|
||||
timerTextField.y = 13 + 9;
|
||||
diagram.addChild(timerTextField);
|
||||
// График
|
||||
graph = new Bitmap(new BitmapData(60, 40, true, 0x20FFFFFF));
|
||||
rect = new Rectangle(0, 0, 1, 40)
|
||||
graph.x = 0;
|
||||
graph.y = 27 + 9;
|
||||
diagram.addChild(graph);
|
||||
// Сброс параметров
|
||||
previousFrameTime = previousPeriodTime = getTimer();
|
||||
fpsUpdateCounter = 0;
|
||||
maxMemory = 0;
|
||||
timerUpdateCounter = 0;
|
||||
timeSum = 0;
|
||||
timeCount = 0;
|
||||
// Подписка
|
||||
diagram.stage.addEventListener(Event.ENTER_FRAME, updateDiagram, false, -1000);
|
||||
diagram.stage.addEventListener(Event.RESIZE, resizeDiagram, false, -1000);
|
||||
resizeDiagram();
|
||||
});
|
||||
// Деинициализация диаграммы
|
||||
diagram.addEventListener(Event.REMOVED_FROM_STAGE, function():void {
|
||||
// Обнуление
|
||||
diagram.removeChild(fpsTextField);
|
||||
diagram.removeChild(memoryTextField);
|
||||
diagram.removeChild(trianglesTextField);
|
||||
diagram.removeChild(graph);
|
||||
fpsTextField = null;
|
||||
memoryTextField = null;
|
||||
trianglesTextField = null;
|
||||
timerTextField = null;
|
||||
graph.bitmapData.dispose();
|
||||
graph = null;
|
||||
rect = null;
|
||||
// Отписка
|
||||
diagram.stage.removeEventListener(Event.ENTER_FRAME, updateDiagram);
|
||||
diagram.stage.removeEventListener(Event.RESIZE, resizeDiagram);
|
||||
});
|
||||
return diagram;
|
||||
}
|
||||
|
||||
private function resizeDiagram(e:Event = null):void {
|
||||
if (diagram.stage != null) {
|
||||
var coord:Point = diagram.parent.globalToLocal(new Point());
|
||||
if (_diagramAlign == StageAlign.TOP_LEFT || _diagramAlign == StageAlign.LEFT || _diagramAlign == StageAlign.BOTTOM_LEFT) {
|
||||
diagram.x = Math.round(coord.x + _diagramHorizontalMargin);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.TOP || _diagramAlign == StageAlign.BOTTOM) {
|
||||
diagram.x = Math.round(coord.x + diagram.stage.stageWidth/2 - graph.width/2);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.TOP_RIGHT || _diagramAlign == StageAlign.RIGHT || _diagramAlign == StageAlign.BOTTOM_RIGHT) {
|
||||
diagram.x = Math.round(coord.x + diagram.stage.stageWidth - _diagramHorizontalMargin - graph.width);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.TOP_LEFT || _diagramAlign == StageAlign.TOP || _diagramAlign == StageAlign.TOP_RIGHT) {
|
||||
diagram.y = Math.round(coord.y + _diagramVerticalMargin);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.LEFT || _diagramAlign == StageAlign.RIGHT) {
|
||||
diagram.y = Math.round(coord.y + diagram.stage.stageHeight/2 - (graph.y + graph.height)/2);
|
||||
}
|
||||
if (_diagramAlign == StageAlign.BOTTOM_LEFT || _diagramAlign == StageAlign.BOTTOM || _diagramAlign == StageAlign.BOTTOM_RIGHT) {
|
||||
diagram.y = Math.round(coord.y + diagram.stage.stageHeight - _diagramVerticalMargin - graph.y - graph.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function updateDiagram(e:Event):void {
|
||||
var fps:Number;
|
||||
var mod:int;
|
||||
var time:int = getTimer();
|
||||
var stageFrameRate:int = diagram.stage.frameRate;
|
||||
|
||||
// FPS текст
|
||||
if (++fpsUpdateCounter == fpsUpdatePeriod) {
|
||||
fps = 1000*fpsUpdatePeriod/(time - previousPeriodTime);
|
||||
if (fps > stageFrameRate) fps = stageFrameRate;
|
||||
mod = fps*100 % 100;
|
||||
fpsTextField.text = "FPS: " + int(fps) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00"));
|
||||
previousPeriodTime = time;
|
||||
fpsUpdateCounter = 0;
|
||||
}
|
||||
// FPS график
|
||||
fps = 1000/(time - previousFrameTime);
|
||||
if (fps > stageFrameRate) fps = stageFrameRate;
|
||||
graph.bitmapData.scroll(1, 0);
|
||||
graph.bitmapData.fillRect(rect, 0x20FFFFFF);
|
||||
graph.bitmapData.setPixel32(0, 40*(1 - fps/stageFrameRate), 0xFFCCCCCC);
|
||||
previousFrameTime = time;
|
||||
|
||||
// Память текст
|
||||
var memory:int = System.totalMemory;
|
||||
memoryTextField.text = "MEM: " + bytesToString(memory);
|
||||
// Память график
|
||||
if (memory > maxMemory) maxMemory = memory;
|
||||
graph.bitmapData.setPixel32(0, 40*(1 - memory/maxMemory), 0xFFCCCC00);
|
||||
|
||||
// Треугольники текст
|
||||
trianglesTextField.text = "TRI: " + numTriangles;
|
||||
|
||||
// Время текст
|
||||
if (++timerUpdateCounter == timerUpdatePeriod) {
|
||||
if (timeCount > 0) {
|
||||
fps = timeSum/timeCount;
|
||||
mod = fps*100 % 100;
|
||||
timerTextField.text = "TMR: " + int(fps) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00"));
|
||||
} else {
|
||||
timerTextField.text = "TMR:";
|
||||
}
|
||||
timerUpdateCounter = 0;
|
||||
timeSum = 0;
|
||||
timeCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function startTimer():void {
|
||||
timer = getTimer();
|
||||
}
|
||||
|
||||
public function stopTimer():void {
|
||||
timeSum += getTimer() - timer;
|
||||
timeCount++;
|
||||
}
|
||||
|
||||
public function get diagramAlign():String {
|
||||
return _diagramAlign;
|
||||
}
|
||||
public function set diagramAlign(value:String):void {
|
||||
_diagramAlign = value;
|
||||
resizeDiagram();
|
||||
}
|
||||
|
||||
public function get diagramHorizontalMargin():Number {
|
||||
return _diagramHorizontalMargin;
|
||||
}
|
||||
public function set diagramHorizontalMargin(value:Number):void {
|
||||
_diagramHorizontalMargin = value;
|
||||
resizeDiagram();
|
||||
}
|
||||
|
||||
public function get diagramVerticalMargin():Number {
|
||||
return _diagramVerticalMargin;
|
||||
}
|
||||
public function set diagramVerticalMargin(value:Number):void {
|
||||
_diagramVerticalMargin = value;
|
||||
resizeDiagram();
|
||||
}
|
||||
|
||||
private function bytesToString(bytes:int):String {
|
||||
if (bytes < 1024) return bytes + "b";
|
||||
else if (bytes < 10240) return (bytes/1024).toFixed(2) + "kb";
|
||||
else if (bytes < 102400) return (bytes/1024).toFixed(1) + "kb";
|
||||
else if (bytes < 1048576) return (bytes >> 10) + "kb";
|
||||
else if (bytes < 10485760) return (bytes/1048576).toFixed(2) + "mb";
|
||||
else if (bytes < 104857600) return (bytes/1048576).toFixed(1) + "mb";
|
||||
else return (bytes >> 20) + "mb";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
104
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Canvas.as
Normal file
104
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Canvas.as
Normal file
@@ -0,0 +1,104 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
import flash.display.Graphics;
|
||||
import flash.display.Sprite;
|
||||
import flash.geom.ColorTransform;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
public class Canvas extends Sprite {
|
||||
|
||||
static private const defaultColorTransform:ColorTransform = new ColorTransform();
|
||||
static private const collector:Vector.<Canvas> = new Vector.<Canvas>();
|
||||
static private var collectorLength:int = 0;
|
||||
|
||||
alternativa3d var gfx:Graphics = graphics;
|
||||
|
||||
private var modifiedGraphics:Boolean;
|
||||
private var modifiedAlpha:Boolean;
|
||||
private var modifiedBlendMode:Boolean;
|
||||
private var modifiedColorTransform:Boolean;
|
||||
private var modifiedFilters:Boolean;
|
||||
|
||||
alternativa3d var _numChildren:int = 0;
|
||||
alternativa3d var numDraws:int = 0;
|
||||
|
||||
public function Canvas() {
|
||||
mouseEnabled = false;
|
||||
mouseChildren = false;
|
||||
}
|
||||
|
||||
alternativa3d function getChildCanvas(useGraphics:Boolean, useChildren:Boolean, alpha:Number = 1, blendMode:String = "normal", colorTransform:ColorTransform = null, filters:Array = null):Canvas {
|
||||
var canvas:Canvas;
|
||||
var displayObject:DisplayObject;
|
||||
// Зачистка не канвасов
|
||||
while (_numChildren > numDraws && !((displayObject = getChildAt(_numChildren - 1 - numDraws)) is Canvas)) {
|
||||
removeChild(displayObject);
|
||||
_numChildren--;
|
||||
}
|
||||
// Получение канваса
|
||||
if (_numChildren > numDraws++) {
|
||||
canvas = displayObject as Canvas;
|
||||
// Зачистка
|
||||
canvas.gfx.clear();
|
||||
if (canvas._numChildren > 0 && !useChildren) {
|
||||
canvas.removeChildren(0);
|
||||
}
|
||||
} else {
|
||||
canvas = (collectorLength > 0) ? collector[--collectorLength] : new Canvas();
|
||||
addChildAt(canvas, 0);
|
||||
_numChildren++;
|
||||
}
|
||||
// Пометка о том, что в graphics будет что-то нарисовано
|
||||
canvas.modifiedGraphics = useGraphics;
|
||||
// Установка свойств
|
||||
if (alpha != 1) {
|
||||
canvas.alpha = alpha;
|
||||
canvas.modifiedAlpha = true;
|
||||
} else if (canvas.modifiedAlpha) {
|
||||
canvas.alpha = 1;
|
||||
canvas.modifiedAlpha = false;
|
||||
}
|
||||
if (blendMode != "normal") {
|
||||
canvas.blendMode = blendMode;
|
||||
canvas.modifiedBlendMode = true;
|
||||
} else if (canvas.modifiedBlendMode) {
|
||||
canvas.blendMode = "normal";
|
||||
canvas.modifiedBlendMode = false;
|
||||
}
|
||||
if (colorTransform != null) {
|
||||
colorTransform.alphaMultiplier = alpha;
|
||||
canvas.transform.colorTransform = colorTransform;
|
||||
canvas.modifiedColorTransform = true;
|
||||
} else if (canvas.modifiedColorTransform) {
|
||||
defaultColorTransform.alphaMultiplier = alpha;
|
||||
canvas.transform.colorTransform = defaultColorTransform;
|
||||
canvas.modifiedColorTransform = false;
|
||||
}
|
||||
if (filters != null) {
|
||||
canvas.filters = filters;
|
||||
canvas.modifiedFilters = true;
|
||||
} else if (canvas.modifiedFilters) {
|
||||
canvas.filters = null;
|
||||
canvas.modifiedFilters = false;
|
||||
}
|
||||
return canvas;
|
||||
}
|
||||
|
||||
alternativa3d function removeChildren(keep:int):void {
|
||||
for (var canvas:Canvas; _numChildren > keep; _numChildren--) {
|
||||
if ((canvas = removeChildAt(0) as Canvas) != null) {
|
||||
if (canvas.modifiedGraphics) canvas.gfx.clear();
|
||||
if (canvas._numChildren > 0) canvas.removeChildren(0);
|
||||
collector[collectorLength++] = canvas;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class Clipping {
|
||||
|
||||
/**
|
||||
* Объект отсекается целиком, если он полностью вне пирамиды видимости или пересекает nearClipping камеры.
|
||||
*/
|
||||
static public const BOUND_CULLING:int = 0;
|
||||
/**
|
||||
* Грань отсекается целиком, если она полностью вне пирамиды видимости или пересекает nearClipping камеры.
|
||||
*/
|
||||
static public const FACE_CULLING:int = 1;
|
||||
/**
|
||||
* Грань подрезается пирамидой видимости камеры.
|
||||
*/
|
||||
static public const FACE_CLIPPING:int = 2;
|
||||
|
||||
}
|
||||
}
|
||||
18
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Debug.as
Normal file
18
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Debug.as
Normal file
@@ -0,0 +1,18 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class Debug {
|
||||
|
||||
static public const NAMES:int = 1;
|
||||
static public const AXES:int = 2;
|
||||
static public const CENTERS:int = 4;
|
||||
static public const BOUNDS:int = 8;
|
||||
|
||||
static public const EDGES:int = 16;
|
||||
static public const VERTICES:int = 32;
|
||||
static public const NORMALS:int = 64;
|
||||
|
||||
static public const NODES:int = 128;
|
||||
static public const SPLITS:int = 256;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
public class Fragment {
|
||||
|
||||
static private var collector:Fragment;
|
||||
|
||||
public var next:Fragment;
|
||||
|
||||
public var negative:Fragment;
|
||||
public var positive:Fragment;
|
||||
|
||||
public var geometry:Geometry;
|
||||
|
||||
public var indices:Vector.<int> = new Vector.<int>();
|
||||
public var num:int = 0;
|
||||
|
||||
public var normalX:Number;
|
||||
public var normalY:Number;
|
||||
public var normalZ:Number;
|
||||
public var offset:Number;
|
||||
|
||||
static public function create():Fragment {
|
||||
if (collector != null) {
|
||||
var res:Fragment = collector;
|
||||
collector = collector.next;
|
||||
res.next = null;
|
||||
return res;
|
||||
} else {
|
||||
return new Fragment();
|
||||
}
|
||||
}
|
||||
|
||||
public function create():Fragment {
|
||||
if (collector != null) {
|
||||
var res:Fragment = collector;
|
||||
collector = collector.next;
|
||||
res.next = null;
|
||||
return res;
|
||||
} else {
|
||||
return new Fragment();
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy():void {
|
||||
num = 0;
|
||||
next = collector;
|
||||
collector = this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
1564
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Geometry.as
Normal file
1564
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Geometry.as
Normal file
File diff suppressed because it is too large
Load Diff
73
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/MipMap.as
Normal file
73
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/MipMap.as
Normal file
@@ -0,0 +1,73 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.display.BitmapData;
|
||||
import flash.filters.ConvolutionFilter;
|
||||
import flash.geom.Matrix;
|
||||
import flash.geom.Point;
|
||||
import flash.geom.Rectangle;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Объект, представляющий текстуру в виде последовательности её уменьшенных копий.
|
||||
* Каждая следующая в два раза меньше предыдущей. Последняя имеет размер 1х1 пиксел.
|
||||
* Чем дальше от камеры отрисовываемый объект, тем меньшая текстура выбирается.
|
||||
* Это позволяет получить лучший визуальный результат и большую производительность.
|
||||
*/
|
||||
public class MipMap {
|
||||
|
||||
/**
|
||||
* Мип-текстуры
|
||||
*/
|
||||
public var textures:Vector.<BitmapData> = new Vector.<BitmapData>();
|
||||
/**
|
||||
* Количество мип-текстур
|
||||
*/
|
||||
public var num:int;
|
||||
/**
|
||||
* Отношение размера пиксела текстуры к единице измерения трёхмерного пространства
|
||||
*/
|
||||
public var resolution:Number;
|
||||
|
||||
static private const filter:ConvolutionFilter = new ConvolutionFilter(2, 2, [1, 1, 1, 1], 4, 0, false, true);
|
||||
static private const point:Point = new Point();
|
||||
static private const matrix:Matrix = new Matrix();
|
||||
static private const rect:Rectangle = new Rectangle();
|
||||
public function MipMap(texture:BitmapData, resolution:Number = 1) {
|
||||
var bmp:BitmapData = new BitmapData(texture.width, texture.height, texture.transparent);
|
||||
var current:BitmapData = textures[num++] = texture;
|
||||
filter.preserveAlpha = !texture.transparent;
|
||||
var w:Number = rect.width = texture.width, h:Number = rect.height = texture.height;
|
||||
while (w > 1 && h > 1 && rect.width > 1 && rect.height > 1) {
|
||||
bmp.applyFilter(current, rect, point, filter);
|
||||
rect.width = w >> 1;
|
||||
rect.height = h >> 1;
|
||||
matrix.a = rect.width/w;
|
||||
matrix.d = rect.height/h;
|
||||
w *= 0.5;
|
||||
h *= 0.5;
|
||||
current = new BitmapData(rect.width, rect.height, texture.transparent, 0);
|
||||
current.draw(bmp, matrix, null, null, null, false);
|
||||
textures[num++] = current;
|
||||
}
|
||||
bmp.dispose();
|
||||
this.resolution = resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение мип-уровня в зависимости от удалённости объекта от камеры
|
||||
* @param distance Z-координата объекта в пространстве камеры
|
||||
* @param camera Камера
|
||||
* @return Индекс в списке мип-текстур textures
|
||||
*/
|
||||
public function getLevel(distance:Number, camera:Camera3D):int {
|
||||
var level:int = Math.log(distance/(camera.focalLength*resolution))*1.442695040888963387;
|
||||
if (level < 0) return 0; else if (level >= num) return num - 1;
|
||||
return level;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class MipMapping {
|
||||
|
||||
/**
|
||||
* Нет мипмаппинга.
|
||||
*/
|
||||
static public const NONE:int = 0;
|
||||
/**
|
||||
* Мипмаппинг по удалённости объекта от камеры.
|
||||
*/
|
||||
static public const PER_OBJECT:int = 1;
|
||||
|
||||
//static public const PER_POLYGON:int = 2;
|
||||
//static public const PER_PIXEL:int = 3;
|
||||
|
||||
}
|
||||
}
|
||||
27
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Node.as
Normal file
27
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Node.as
Normal file
@@ -0,0 +1,27 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
public final class Node {
|
||||
|
||||
public var positive:Node;
|
||||
public var negative:Node;
|
||||
|
||||
public var normalX:Number;
|
||||
public var normalY:Number;
|
||||
public var normalZ:Number;
|
||||
|
||||
public var offset:Number;
|
||||
public var offsetMin:Number;
|
||||
public var offsetMax:Number;
|
||||
|
||||
public var boundBox:BoundBox;
|
||||
|
||||
public var objects:Vector.<Object3D>;
|
||||
public var bounds:Vector.<BoundBox>;
|
||||
|
||||
public var numObjects:int = 0;
|
||||
public var numNonOccluders:int = 0;
|
||||
|
||||
}
|
||||
}
|
||||
270
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Object3D.as
Normal file
270
Alternativa3D7/7.2.1/src/alternativa/engine3d/core/Object3D.as
Normal file
@@ -0,0 +1,270 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.geom.ColorTransform;
|
||||
import flash.geom.Matrix3D;
|
||||
import flash.geom.Utils3D;
|
||||
import flash.utils.getQualifiedClassName;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Базовый трёхмерный объект
|
||||
*/
|
||||
public class Object3D {
|
||||
|
||||
public var name:String;
|
||||
/**
|
||||
* Матрица трансформации. Управлять трансформацией объекта можно только через это свойство
|
||||
* путём назначения новой матрицы или с помощью методов матрицы.
|
||||
*/
|
||||
public var matrix:Matrix3D = new Matrix3D();
|
||||
public var visible:Boolean = true;
|
||||
|
||||
public var alpha:Number = 1;
|
||||
public var blendMode:String = "normal";
|
||||
public var colorTransform:ColorTransform = null;
|
||||
public var filters:Array = null;
|
||||
|
||||
alternativa3d var _parent:Object3DContainer;
|
||||
|
||||
alternativa3d var _boundBox:BoundBox;
|
||||
|
||||
alternativa3d var culling:int = 0;
|
||||
|
||||
alternativa3d var cameraMatrix:Matrix3D = new Matrix3D();
|
||||
|
||||
static private const boundBoxVertices:Vector.<Number> = new Vector.<Number>(24, true);
|
||||
|
||||
alternativa3d function get canDraw():Boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {}
|
||||
|
||||
alternativa3d function debug(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
||||
var debugResult:int = camera.checkInDebug(this);
|
||||
if (debugResult == 0) return;
|
||||
var canvas:Canvas = parentCanvas.getChildCanvas(true, false);
|
||||
if (debugResult & Debug.AXES) object.drawAxes(camera, canvas);
|
||||
if (debugResult & Debug.CENTERS) object.drawCenter(camera, canvas);
|
||||
if (debugResult & Debug.NAMES) object.drawName(camera, canvas);
|
||||
if (debugResult & Debug.BOUNDS) object.drawBoundBox(camera, canvas);
|
||||
}
|
||||
|
||||
alternativa3d function getGeometry(camera:Camera3D, object:Object3D):Geometry {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function get boundBox():BoundBox {
|
||||
return _boundBox;
|
||||
}
|
||||
|
||||
public function set boundBox(value:BoundBox):void {
|
||||
_boundBox = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Расчёт баунда
|
||||
* @param matrix Трансформация пространства, в системе которого расчитывается баунд.
|
||||
* Если этот параметр не указан, баунд расчитается в локальных координатах объекта.
|
||||
* @param boundBox Баунд, в который записывается результат.
|
||||
* Если этот параметр не указан, создаётся новый экземпляр.
|
||||
* @return Расчитанный баунд.
|
||||
*/
|
||||
public function calculateBoundBox(matrix:Matrix3D = null, boundBox:BoundBox = null):BoundBox {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function get parent():Object3DContainer {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
alternativa3d function cullingInCamera(camera:Camera3D, parentCulling:int):int {
|
||||
if (camera.occludedAll) return -1;
|
||||
culling = parentCulling;
|
||||
var i:int, infront:Boolean, behind:Boolean, boundBox:BoundBox = this.boundBox, numOccluders:int = camera.numOccluders, cull:Boolean = culling > 0 && boundBox != null, occlude:Boolean = numOccluders > 0 && boundBox != null;
|
||||
// Расчёт точек баунда в координатах камеры
|
||||
if (cull || occlude) boundBoxVertices[0] = boundBoxVertices[3] = boundBoxVertices[6] = boundBoxVertices[9] = boundBox.minX, boundBoxVertices[1] = boundBoxVertices[4] = boundBoxVertices[13] = boundBoxVertices[16] = boundBox.minY, boundBoxVertices[2] = boundBoxVertices[8] = boundBoxVertices[14] = boundBoxVertices[20] = boundBox.minZ, boundBoxVertices[12] = boundBoxVertices[15] = boundBoxVertices[18] = boundBoxVertices[21] = boundBox.maxX, boundBoxVertices[7] = boundBoxVertices[10] = boundBoxVertices[19] = boundBoxVertices[22] = boundBox.maxY, boundBoxVertices[5] = boundBoxVertices[11] = boundBoxVertices[17] = boundBoxVertices[23] = boundBox.maxZ, cameraMatrix.transformVectors(boundBoxVertices, boundBoxVertices);
|
||||
// Куллинг
|
||||
if (cull) {
|
||||
if (culling & 1) {
|
||||
for (i = 2, infront = false, behind = false; i <= 23; i += 3) {
|
||||
if (boundBoxVertices[i] > camera.nearClipping) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
// TODO: проверка не нужна
|
||||
if (infront) culling &= 62;
|
||||
}
|
||||
}
|
||||
if (culling & 2) {
|
||||
for (i = 2, infront = false, behind = false; i <= 23; i += 3) {
|
||||
if (boundBoxVertices[i] < camera.farClipping) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 61;
|
||||
}
|
||||
}
|
||||
if (culling & 4) {
|
||||
for (i = 0, infront = false, behind = false; i <= 21; i += 3) {
|
||||
if (-boundBoxVertices[i] < boundBoxVertices[int(i + 2)]) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 59;
|
||||
}
|
||||
}
|
||||
if (culling & 8) {
|
||||
for (i = 0, infront = false, behind = false; i <= 21; i += 3) {
|
||||
if (boundBoxVertices[i] < boundBoxVertices[int(i + 2)]) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 55;
|
||||
}
|
||||
}
|
||||
if (culling & 16) {
|
||||
for (i = 1, infront = false, behind = false; i <= 22; i += 3) {
|
||||
if (-boundBoxVertices[i] < boundBoxVertices[int(i + 1)]) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 47;
|
||||
}
|
||||
}
|
||||
if (culling & 32) {
|
||||
for (i = 1, infront = false, behind = false; i <= 22; i += 3) {
|
||||
if (boundBoxVertices[i] < boundBoxVertices[int(i + 1)]) {
|
||||
infront = true;
|
||||
if (behind) break;
|
||||
} else {
|
||||
behind = true;
|
||||
if (infront) break;
|
||||
}
|
||||
}
|
||||
if (behind) {
|
||||
if (!infront) return -1;
|
||||
} else {
|
||||
if (infront) culling &= 31;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Окклюдинг
|
||||
if (occlude) {
|
||||
for (var o:int = 0; o < numOccluders; o++) {
|
||||
var planeOccluder:Vector.<Number> = camera.occlusionPlanes[o], planeOccluderLength:int = planeOccluder.length;
|
||||
for (var ni:int = 0; ni < planeOccluderLength; ni += 3) {
|
||||
var nx:Number = planeOccluder[ni], ny:Number = planeOccluder[int(ni + 1)], nz:Number = planeOccluder[int(ni + 2)];
|
||||
for (i = 0; i < 24; i += 3) if (nx*boundBoxVertices[i] + ny*boundBoxVertices[int(i + 1)] + nz*boundBoxVertices[int(i + 2)] >= 0) break;
|
||||
if (i < 24) break;
|
||||
}
|
||||
if (ni == planeOccluderLength) return -1;
|
||||
}
|
||||
}
|
||||
return culling;
|
||||
}
|
||||
|
||||
alternativa3d function drawAxes(camera:Camera3D, canvas:Canvas):void {
|
||||
|
||||
}
|
||||
|
||||
alternativa3d function drawCenter(camera:Camera3D, canvas:Canvas):void {
|
||||
|
||||
}
|
||||
|
||||
alternativa3d function drawName(camera:Camera3D, canvas:Canvas):void {
|
||||
|
||||
}
|
||||
|
||||
static private const boundBoxProjectedVertices:Vector.<Number> = new Vector.<Number>(16, true);
|
||||
static private const boundBoxUVTs:Vector.<Number> = new Vector.<Number>(24, true);
|
||||
alternativa3d function drawBoundBox(camera:Camera3D, canvas:Canvas, color:int = -1):void {
|
||||
|
||||
var boundBox:BoundBox = this.boundBox;
|
||||
if (boundBox == null) return;
|
||||
|
||||
boundBoxVertices[0] = boundBoxVertices[3] = boundBoxVertices[6] = boundBoxVertices[9] = boundBox.minX;
|
||||
boundBoxVertices[1] = boundBoxVertices[4] = boundBoxVertices[13] = boundBoxVertices[16] = boundBox.minY;
|
||||
boundBoxVertices[2] = boundBoxVertices[8] = boundBoxVertices[14] = boundBoxVertices[20] = boundBox.minZ;
|
||||
|
||||
boundBoxVertices[12] = boundBoxVertices[15] = boundBoxVertices[18] = boundBoxVertices[21] = boundBox.maxX;
|
||||
boundBoxVertices[7] = boundBoxVertices[10] = boundBoxVertices[19] = boundBoxVertices[22] = boundBox.maxY;
|
||||
boundBoxVertices[5] = boundBoxVertices[11] = boundBoxVertices[17] = boundBoxVertices[23] = boundBox.maxZ;
|
||||
|
||||
cameraMatrix.transformVectors(boundBoxVertices, boundBoxVertices);
|
||||
for (var i:int = 0; i < 8; i++) {
|
||||
if (boundBoxVertices[int(i*3 +2)] <= 0) return;
|
||||
}
|
||||
Utils3D.projectVectors(camera.projectionMatrix, boundBoxVertices, boundBoxProjectedVertices, boundBoxUVTs);
|
||||
canvas.gfx.endFill();
|
||||
canvas.gfx.lineStyle(0, (color < 0) ? ((culling > 0) ? 0xFFFF00 : 0x00FF00) : color);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[0], boundBoxProjectedVertices[1]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[2], boundBoxProjectedVertices[3]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[6], boundBoxProjectedVertices[7]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[4], boundBoxProjectedVertices[5]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[0], boundBoxProjectedVertices[1]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[8], boundBoxProjectedVertices[9]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[10], boundBoxProjectedVertices[11]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[14], boundBoxProjectedVertices[15]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[12], boundBoxProjectedVertices[13]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[8], boundBoxProjectedVertices[9]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[0], boundBoxProjectedVertices[1]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[8], boundBoxProjectedVertices[9]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[2], boundBoxProjectedVertices[3]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[10], boundBoxProjectedVertices[11]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[4], boundBoxProjectedVertices[5]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[12], boundBoxProjectedVertices[13]);
|
||||
canvas.gfx.moveTo(boundBoxProjectedVertices[6], boundBoxProjectedVertices[7]);
|
||||
canvas.gfx.lineTo(boundBoxProjectedVertices[14], boundBoxProjectedVertices[15]);
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
var className:String = getQualifiedClassName(this);
|
||||
return "[" + className.substr(className.indexOf("::") + 2) + " " + name + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
import __AS3__.vec.Vector;
|
||||
|
||||
import alternativa.engine3d.alternativa3d;
|
||||
|
||||
import flash.geom.ColorTransform;
|
||||
import flash.geom.Matrix3D;
|
||||
|
||||
use namespace alternativa3d;
|
||||
|
||||
/**
|
||||
* Базовый контейнер трёхмерных объектов.
|
||||
* Логика контейнеров и child-parent-отношений идентична логике
|
||||
* displayObject'ов во Flash.
|
||||
*/
|
||||
public class Object3DContainer extends Object3D {
|
||||
|
||||
protected var children:Vector.<Object3D> = new Vector.<Object3D>();
|
||||
protected var _numChildren:int = 0;
|
||||
|
||||
protected var visibleChildren:Vector.<Object3D> = new Vector.<Object3D>();
|
||||
protected var numVisibleChildren:int = 0;
|
||||
|
||||
override alternativa3d function get canDraw():Boolean {
|
||||
return _numChildren > 0;
|
||||
}
|
||||
|
||||
override alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
||||
// Сбор видимых объектов
|
||||
numVisibleChildren = 0;
|
||||
for (var i:int = 0; i < _numChildren; i++) {
|
||||
var child:Object3D = children[i];
|
||||
if (child.visible && child.canDraw) {
|
||||
child.cameraMatrix.identity();
|
||||
child.cameraMatrix.prepend(object.cameraMatrix);
|
||||
child.cameraMatrix.prepend(child.matrix);
|
||||
if (child.cullingInCamera(camera, object.culling) >= 0) {
|
||||
visibleChildren[numVisibleChildren] = child;
|
||||
numVisibleChildren++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Если есть видимые объекты
|
||||
if (numVisibleChildren > 0) {
|
||||
// Подготовка канваса
|
||||
var canvas:Canvas = parentCanvas.getChildCanvas(false, true, object.alpha, object.blendMode, object.colorTransform, object.filters);
|
||||
canvas.numDraws = 0;
|
||||
// Отрисовка видимых объектов
|
||||
drawVisibleChildren(camera, object, canvas);
|
||||
// Если была отрисовка
|
||||
if (canvas.numDraws > 0) {
|
||||
canvas.removeChildren(canvas.numDraws);
|
||||
} else {
|
||||
parentCanvas.numDraws--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function drawVisibleChildren(camera:Camera3D, object:Object3D, canvas:Canvas):void {
|
||||
for (var i:int = numVisibleChildren - 1; i >= 0; i--) {
|
||||
var child:Object3D = visibleChildren[i];
|
||||
if (camera.debugMode) child.debug(camera, child, canvas);
|
||||
child.draw(camera, child, canvas);
|
||||
visibleChildren[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
override alternativa3d function getGeometry(camera:Camera3D, object:Object3D):Geometry {
|
||||
var i:int;
|
||||
var first:Geometry;
|
||||
var last:Geometry;
|
||||
var geometry:Geometry;
|
||||
for (i = 0; i < _numChildren; i++) {
|
||||
var child:Object3D = children[i];
|
||||
if (child.visible && child.canDraw) {
|
||||
child.cameraMatrix.identity();
|
||||
child.cameraMatrix.prepend(object.cameraMatrix);
|
||||
child.cameraMatrix.prepend(child.matrix);
|
||||
if (child.cullingInCamera(camera, object.culling) >= 0) {
|
||||
geometry = child.getGeometry(camera, child);
|
||||
if (geometry != null) {
|
||||
if (first != null) {
|
||||
last.next = geometry;
|
||||
} else {
|
||||
first = geometry;
|
||||
last = geometry;
|
||||
}
|
||||
while (last.next != null) {
|
||||
last = last.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (object.alpha != 1) {
|
||||
geometry = first;
|
||||
while (geometry != null) {
|
||||
geometry.alpha *= object.alpha;
|
||||
geometry = geometry.next;
|
||||
}
|
||||
}
|
||||
if (object.blendMode != "normal") {
|
||||
geometry = first;
|
||||
while (geometry != null) {
|
||||
if (geometry.blendMode == "normal") {
|
||||
geometry.blendMode = object.blendMode;
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
}
|
||||
if (object.colorTransform != null) {
|
||||
geometry = first;
|
||||
while (geometry != null) {
|
||||
if (geometry.colorTransform != null) {
|
||||
var ct:ColorTransform = new ColorTransform(object.colorTransform.redMultiplier, object.colorTransform.greenMultiplier, object.colorTransform.blueMultiplier, object.colorTransform.alphaMultiplier, object.colorTransform.redOffset, object.colorTransform.greenOffset, object.colorTransform.blueOffset, object.colorTransform.alphaOffset);
|
||||
ct.concat(geometry.colorTransform);
|
||||
geometry.colorTransform = ct;
|
||||
} else {
|
||||
geometry.colorTransform = object.colorTransform;
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
}
|
||||
if (object.filters != null) {
|
||||
geometry = first;
|
||||
while (geometry != null) {
|
||||
if (geometry.filters != null) {
|
||||
var fs:Array = new Array();
|
||||
var fsLength:int = 0;
|
||||
var num:int = geometry.filters.length;
|
||||
for (i = 0; i < num; i++) {
|
||||
fs[fsLength] = geometry.filters[i]; fsLength++;
|
||||
}
|
||||
num = object.filters.length;
|
||||
for (i = 0; i < num; i++) {
|
||||
fs[fsLength] = object.filters[i]; fsLength++;
|
||||
}
|
||||
geometry.filters = fs;
|
||||
} else {
|
||||
geometry.filters = object.filters;
|
||||
}
|
||||
geometry = geometry.next;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
override public function calculateBoundBox(matrix:Matrix3D = null, boundBox:BoundBox = null):BoundBox {
|
||||
var m:Matrix3D = matrix != null ? matrix.clone() : new Matrix3D();
|
||||
// Если указан баунд-бокс
|
||||
if (boundBox != null) {
|
||||
boundBox.infinity();
|
||||
} else {
|
||||
boundBox = new BoundBox();
|
||||
}
|
||||
// Расчитываем баунды объектов
|
||||
var childBoundBox:BoundBox = new BoundBox();
|
||||
var childMatrix:Matrix3D = new Matrix3D();
|
||||
for (var i:int = 0; i < _numChildren; i++) {
|
||||
var child:Object3D = children[i];
|
||||
childMatrix.identity();
|
||||
childMatrix.prepend(m);
|
||||
childMatrix.prepend(child.matrix);
|
||||
child.calculateBoundBox(childMatrix, childBoundBox);
|
||||
boundBox.minX = (childBoundBox.minX < boundBox.minX) ? childBoundBox.minX : boundBox.minX;
|
||||
boundBox.minY = (childBoundBox.minY < boundBox.minY) ? childBoundBox.minY : boundBox.minY;
|
||||
boundBox.minZ = (childBoundBox.minZ < boundBox.minZ) ? childBoundBox.minZ : boundBox.minZ;
|
||||
boundBox.maxX = (childBoundBox.maxX > boundBox.maxX) ? childBoundBox.maxX : boundBox.maxX;
|
||||
boundBox.maxY = (childBoundBox.maxY > boundBox.maxY) ? childBoundBox.maxY : boundBox.maxY;
|
||||
boundBox.maxZ = (childBoundBox.maxZ > boundBox.maxZ) ? childBoundBox.maxZ : boundBox.maxZ;
|
||||
}
|
||||
return boundBox;
|
||||
}
|
||||
|
||||
public function addChild(child:Object3D):void {
|
||||
children[_numChildren++] = child;
|
||||
child._parent = this;
|
||||
}
|
||||
|
||||
public function removeChild(child:Object3D):void {
|
||||
var i:int = children.indexOf(child);
|
||||
if (i < 0) throw new ArgumentError("Child not found");
|
||||
_numChildren--;
|
||||
for (; i < _numChildren; i++) children[i] = children[int(i + 1)];
|
||||
children.length = _numChildren;
|
||||
child._parent = null;
|
||||
}
|
||||
|
||||
public function hasChild(child:Object3D):Boolean {
|
||||
return children.indexOf(child) > -1;
|
||||
}
|
||||
|
||||
public function getChildAt(index:uint):Object3D {
|
||||
return children[index];
|
||||
}
|
||||
|
||||
public function get numChildren():uint {
|
||||
return _numChildren;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package alternativa.engine3d.core {
|
||||
|
||||
public class Sorting {
|
||||
|
||||
/**
|
||||
* Грани не сортируются.
|
||||
*/
|
||||
static public const NONE:int = 0;
|
||||
/**
|
||||
* Грани сортируются по средним Z.
|
||||
*/
|
||||
static public const AVERAGE_Z:int = 1;
|
||||
/**
|
||||
* Грани находятся в BSP-дереве.
|
||||
*/
|
||||
static public const STATIC_BSP:int = 2;
|
||||
/**
|
||||
* Грани при отрисовке образуют BSP-дерево.
|
||||
*/
|
||||
static public const DYNAMIC_BSP:int = 3;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 105
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders
|
||||
END
|
||||
TextureFilesData.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 125
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/TextureFilesData.as
|
||||
END
|
||||
Loader3DS.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 118
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/Loader3DS.as
|
||||
END
|
||||
MaterialParams.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 123
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/MaterialParams.as
|
||||
END
|
||||
Parsed3DSData.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 122
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/Parsed3DSData.as
|
||||
END
|
||||
Loader3DSByteArray.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 127
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/Loader3DSByteArray.as
|
||||
END
|
||||
Parser3DS.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 118
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/Parser3DS.as
|
||||
END
|
||||
TextureLoader.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 122
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/TextureLoader.as
|
||||
END
|
||||
BatchTextureLoader.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 127
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/BatchTextureLoader.as
|
||||
END
|
||||
TextureInfo.as
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 120
|
||||
/!svn/ver/22370/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders/TextureInfo.as
|
||||
END
|
||||
@@ -0,0 +1,139 @@
|
||||
8
|
||||
|
||||
dir
|
||||
46043
|
||||
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.2.1/src/alternativa/engine3d/loaders
|
||||
http://svndev.alternativaplatform.com
|
||||
|
||||
|
||||
|
||||
2009-10-18T15:26:30.880098Z
|
||||
22239
|
||||
int
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
|
||||
|
||||
TextureFilesData.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
5dab534b47ec603953467a319d0a9757
|
||||
2009-03-03T10:45:06.942390Z
|
||||
8557
|
||||
mike
|
||||
|
||||
Loader3DS.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
65726f9d6bede8e1fedd506d28056fed
|
||||
2009-10-18T15:26:30.880098Z
|
||||
22239
|
||||
int
|
||||
|
||||
events
|
||||
dir
|
||||
|
||||
MaterialParams.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
101884503099df0a70e423bd56fcfa4b
|
||||
2009-03-03T10:45:06.942390Z
|
||||
8557
|
||||
mike
|
||||
|
||||
Parsed3DSData.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
9c3dbe4c093e301aa3af29bb56a12386
|
||||
2009-03-03T10:45:06.942390Z
|
||||
8557
|
||||
mike
|
||||
|
||||
Loader3DSByteArray.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
ed80c6eb3e24ea03208ce9363846c069
|
||||
2009-10-18T15:26:30.880098Z
|
||||
22239
|
||||
int
|
||||
|
||||
Parser3DS.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
b48bd1b567b70ed6ae2bf5a19e7937a3
|
||||
2009-10-18T15:26:30.880098Z
|
||||
22239
|
||||
int
|
||||
|
||||
TextureLoader.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
2fe362bd5849c1f2bced6097745e778e
|
||||
2009-09-24T13:14:56.450304Z
|
||||
20448
|
||||
mike
|
||||
|
||||
BatchTextureLoader.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
a200c12bc82bf970605115a4f35be670
|
||||
2009-08-27T08:28:22.626310Z
|
||||
18884
|
||||
mike
|
||||
|
||||
TextureInfo.as
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-10-28T04:31:16.000000Z
|
||||
1b2b5a651cb0fb845e977f30ad97b28e
|
||||
2009-08-27T08:17:26.370911Z
|
||||
18883
|
||||
mike
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
8
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user