more versions added

This commit is contained in:
Tubix
2024-10-05 12:11:16 +01:00
parent 413f563f33
commit c32c7e8c34
7661 changed files with 1343635 additions and 0 deletions

BIN
Alternativa3D7/.DS_Store vendored Normal file

Binary file not shown.

BIN
Alternativa3D7/7.0.1.0/.DS_Store vendored Normal file

Binary file not shown.

View 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>

View File

@@ -0,0 +1,11 @@
K 25
svn:wc:ra_dav:version-url
V 96
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.externalToolBuilders
END
haXe.launch
K 25
svn:wc:ra_dav:version-url
V 108
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.externalToolBuilders/haXe.launch
END

View File

@@ -0,0 +1,40 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.externalToolBuilders
http://svndev.alternativaplatform.com
2009-02-17T22:44:11.918721Z
7685
wolf
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
haXe.launch
file
2010-10-28T04:31:04.000000Z
af4be69e8c75066118f74a0a6685070e
2009-02-17T22:44:11.918721Z
7685
wolf

View File

@@ -0,0 +1 @@
8

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\Program Files\Motion-Twin\haxe\haxe.exe"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-cp ${project_loc}\src&#13;&#10;-swf-version 10&#13;&#10;-debug&#13;&#10;-swf ${project_loc}\bin\Alternativa3DMath.swc&#13;&#10;alternativa.engine3d.core.MeshMath"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
</launchConfiguration>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\Program Files\Motion-Twin\haxe\haxe.exe"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-cp ${project_loc}\src&#13;&#10;-swf-version 10&#13;&#10;-debug&#13;&#10;-swf ${project_loc}\bin\Alternativa3DMath.swc&#13;&#10;alternativa.engine3d.core.MeshMath"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
</launchConfiguration>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flexLibProperties version="1">
<includeClasses>
<classEntry path="alternativa.engine3d.core.MipMap"/>
<classEntry path="alternativa.engine3d.objects.KDObject"/>
<classEntry path="alternativa.engine3d.loaders.MaterialParams"/>
<classEntry path="alternativa.engine3d.core.Object3DContainer"/>
<classEntry path="alternativa.engine3d.primitives.FillBox"/>
<classEntry path="alternativa.engine3d.controllers.SimpleObjectController"/>
<classEntry path="alternativa.engine3d.objects.WireQuad"/>
<classEntry path="alternativa.engine3d.objects.Occluder"/>
<classEntry path="alternativa.engine3d.loaders.TextureMapsBatchLoader"/>
<classEntry path="alternativa.engine3d.containers.AverageZContainer"/>
<classEntry path="alternativa.engine3d.core.Canvas"/>
<classEntry path="alternativa.engine3d.loaders.Parser3DS"/>
<classEntry path="alternativa.engine3d.core.BoundBox"/>
<classEntry path="alternativa.engine3d.objects.Sprite3D"/>
<classEntry path="alternativa.engine3d.objects.LOD"/>
<classEntry path="alternativa.engine3d.core.KDNode"/>
<classEntry path="alternativa.engine3d.objects.FillMesh"/>
<classEntry path="alternativa.engine3d.containers.KDTree"/>
<classEntry path="alternativa.engine3d.loaders.Loader3DSByteArray"/>
<classEntry path="alternativa.engine3d.objects.Mesh"/>
<classEntry path="alternativa.engine3d.objects.Bone"/>
<classEntry path="alternativa.engine3d.loaders.Loader3DS"/>
<classEntry path="alternativa.engine3d.objects.SkeletalMesh"/>
<classEntry path="alternativa.engine3d.containers.DirectionContainer"/>
<classEntry path="alternativa.engine3d.containers.SkyBox"/>
<classEntry path="alternativa.engine3d.primitives.GeoSphere"/>
<classEntry path="alternativa.engine3d.primitives.FillPlane"/>
<classEntry path="alternativa.engine3d.primitives.Box"/>
<classEntry path="alternativa.engine3d.loaders.Parsed3DSData"/>
<classEntry path="alternativa.engine3d.loaders.TextureMapsInfo"/>
<classEntry path="alternativa.engine3d.objects.Reference"/>
<classEntry path="alternativa.engine3d.loaders.TextureMapsLoader"/>
<classEntry path="alternativa.engine3d.core.Object3D"/>
<classEntry path="alternativa.engine3d.objects.AnimSprite"/>
<classEntry path="alternativa.engine3d.objects.Axes"/>
<classEntry path="alternativa.engine3d.loaders.TextureFilesData"/>
<classEntry path="alternativa.engine3d.core.BSPNode"/>
<classEntry path="alternativa.engine3d.alternativa3d"/>
<classEntry path="alternativa.engine3d.containers.SplitContainer"/>
<classEntry path="alternativa.engine3d.core.Camera3D"/>
<classEntry path="alternativa.engine3d.primitives.Plane"/>
</includeClasses>
<includeResources/>
<namespaceManifests/>
</flexLibProperties>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Alternativa3D</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/haXe.launch</value>
</dictionary>
</arguments>
</buildCommand>
<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>

View File

@@ -0,0 +1,17 @@
K 25
svn:wc:ra_dav:version-url
V 84
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.settings
END
org.eclipse.core.resources.prefs
K 25
svn:wc:ra_dav:version-url
V 117
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.settings/org.eclipse.core.resources.prefs
END
org.eclipse.ltk.core.refactoring.prefs
K 25
svn:wc:ra_dav:version-url
V 123
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.settings/org.eclipse.ltk.core.refactoring.prefs
END

View File

@@ -0,0 +1,52 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.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:04.000000Z
63644c8a8f9fe441148cb750eb3dc2f3
2008-08-25T13:44:47.077292Z
176
int
org.eclipse.ltk.core.refactoring.prefs
file
2010-10-28T04:31:04.000000Z
85719ffc1d818e46b40e2f90aad31e8c
2008-08-25T13:44:47.077292Z
176
int

View File

@@ -0,0 +1 @@
8

View File

@@ -0,0 +1,3 @@
#Thu Feb 14 09:12:30 YEKT 2008
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@@ -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

View File

@@ -0,0 +1,3 @@
#Thu Feb 14 09:12:30 YEKT 2008
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@@ -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

View File

@@ -0,0 +1,29 @@
K 25
svn:wc:ra_dav:version-url
V 74
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0
END
.flexLibProperties
K 25
svn:wc:ra_dav:version-url
V 93
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.flexLibProperties
END
.project
K 25
svn:wc:ra_dav:version-url
V 83
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.project
END
pom.xml
K 25
svn:wc:ra_dav:version-url
V 82
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/pom.xml
END
.actionScriptProperties
K 25
svn:wc:ra_dav:version-url
V 98
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/.actionScriptProperties
END

View File

@@ -0,0 +1,15 @@
K 10
svn:ignore
V 46
help
Alternativa3D API Documentation.launch
K 13
svn:mergeinfo
V 412
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0:5796-7235
/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

View File

@@ -0,0 +1,88 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0
http://svndev.alternativaplatform.com
2009-06-29T08:23:48.653633Z
15289
mike
has-props
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
META-INF
dir
.flexLibProperties
file
2010-10-28T04:31:04.000000Z
2d2a4569dd504bd884ad62ad18144a74
2009-06-23T11:11:31.485394Z
14968
int
.project
file
2010-10-28T04:31:04.000000Z
43d8655bb09871bab44a10d4ba5a19e5
2009-03-03T10:45:06.942390Z
8557
mike
src
dir
.externalToolBuilders
dir
pom.xml
file
2010-10-28T04:31:04.000000Z
681f507d62f27c39a4b8155badf6a4a6
2009-06-29T08:23:48.653633Z
15289
mike
.actionScriptProperties
file
2010-10-28T04:31:04.000000Z
7af24faaf5d92b617880b65756a4918d
2009-06-29T08:22:26.540886Z
15285
mike
.settings
dir

View File

@@ -0,0 +1 @@
8

View 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>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flexLibProperties version="1">
<includeClasses>
<classEntry path="alternativa.engine3d.core.MipMap"/>
<classEntry path="alternativa.engine3d.objects.KDObject"/>
<classEntry path="alternativa.engine3d.loaders.MaterialParams"/>
<classEntry path="alternativa.engine3d.core.Object3DContainer"/>
<classEntry path="alternativa.engine3d.primitives.FillBox"/>
<classEntry path="alternativa.engine3d.controllers.SimpleObjectController"/>
<classEntry path="alternativa.engine3d.objects.WireQuad"/>
<classEntry path="alternativa.engine3d.objects.Occluder"/>
<classEntry path="alternativa.engine3d.loaders.TextureMapsBatchLoader"/>
<classEntry path="alternativa.engine3d.containers.AverageZContainer"/>
<classEntry path="alternativa.engine3d.core.Canvas"/>
<classEntry path="alternativa.engine3d.loaders.Parser3DS"/>
<classEntry path="alternativa.engine3d.core.BoundBox"/>
<classEntry path="alternativa.engine3d.objects.Sprite3D"/>
<classEntry path="alternativa.engine3d.objects.LOD"/>
<classEntry path="alternativa.engine3d.core.KDNode"/>
<classEntry path="alternativa.engine3d.objects.FillMesh"/>
<classEntry path="alternativa.engine3d.containers.KDTree"/>
<classEntry path="alternativa.engine3d.loaders.Loader3DSByteArray"/>
<classEntry path="alternativa.engine3d.objects.Mesh"/>
<classEntry path="alternativa.engine3d.objects.Bone"/>
<classEntry path="alternativa.engine3d.loaders.Loader3DS"/>
<classEntry path="alternativa.engine3d.objects.SkeletalMesh"/>
<classEntry path="alternativa.engine3d.containers.DirectionContainer"/>
<classEntry path="alternativa.engine3d.containers.SkyBox"/>
<classEntry path="alternativa.engine3d.primitives.GeoSphere"/>
<classEntry path="alternativa.engine3d.primitives.FillPlane"/>
<classEntry path="alternativa.engine3d.primitives.Box"/>
<classEntry path="alternativa.engine3d.loaders.Parsed3DSData"/>
<classEntry path="alternativa.engine3d.loaders.TextureMapsInfo"/>
<classEntry path="alternativa.engine3d.objects.Reference"/>
<classEntry path="alternativa.engine3d.loaders.TextureMapsLoader"/>
<classEntry path="alternativa.engine3d.core.Object3D"/>
<classEntry path="alternativa.engine3d.objects.AnimSprite"/>
<classEntry path="alternativa.engine3d.objects.Axes"/>
<classEntry path="alternativa.engine3d.loaders.TextureFilesData"/>
<classEntry path="alternativa.engine3d.core.BSPNode"/>
<classEntry path="alternativa.engine3d.alternativa3d"/>
<classEntry path="alternativa.engine3d.containers.SplitContainer"/>
<classEntry path="alternativa.engine3d.core.Camera3D"/>
<classEntry path="alternativa.engine3d.primitives.Plane"/>
</includeClasses>
<includeResources/>
<namespaceManifests/>
</flexLibProperties>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Alternativa3D</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/haXe.launch</value>
</dictionary>
</arguments>
</buildCommand>
<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>

View 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.1.0</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/tags/7.0.1.0</connection>
</scm>
</project>

View File

@@ -0,0 +1,11 @@
K 25
svn:wc:ra_dav:version-url
V 83
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/META-INF
END
MANIFEST.MF
K 25
svn:wc:ra_dav:version-url
V 95
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/META-INF/MANIFEST.MF
END

View File

@@ -0,0 +1,40 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/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:04.000000Z
0069b2b9a3b474d1d94113e9d6731290
2009-03-04T09:09:17.957056Z
8649
mike

View File

@@ -0,0 +1 @@
8

View File

@@ -0,0 +1 @@
Bundle-Name: platform.clients.fp10.libraries.Alternativa3D

View File

@@ -0,0 +1 @@
Bundle-Name: platform.clients.fp10.libraries.Alternativa3D

View 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.1.0</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/tags/7.0.1.0</connection>
</scm>
</project>

BIN
Alternativa3D7/7.0.1.0/src/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,11 @@
K 25
svn:wc:ra_dav:version-url
V 78
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src
END
manifest.xml
K 25
svn:wc:ra_dav:version-url
V 91
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/manifest.xml
END

View File

@@ -0,0 +1,43 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src
http://svndev.alternativaplatform.com
2009-06-28T14:57:52.173273Z
15193
int
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
manifest.xml
file
2010-10-28T04:31:04.000000Z
2e2b1aa9d128d192e5f544209f610433
2009-06-25T13:27:32.420515Z
15144
int
alternativa
dir

View File

@@ -0,0 +1 @@
8

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<componentPackage>
<component id="Alternativa3D" class="alternativa.Alternativa3D"/>
</componentPackage>

Binary file not shown.

View File

@@ -0,0 +1,11 @@
K 25
svn:wc:ra_dav:version-url
V 90
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa
END
Alternativa3D.as
K 25
svn:wc:ra_dav:version-url
V 107
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/Alternativa3D.as
END

View File

@@ -0,0 +1,10 @@
K 13
svn:mergeinfo
V 552
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0/src/alternativa:5796-7235
/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

View File

@@ -0,0 +1,43 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa
http://svndev.alternativaplatform.com
2009-06-28T14:57:52.173273Z
15193
int
has-props
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
Alternativa3D.as
file
2010-10-28T04:31:04.000000Z
1500acb71dc17d3fd581f2398575f25e
2009-06-25T13:27:32.420515Z
15144
int
engine3d
dir

View File

@@ -0,0 +1 @@
8

View File

@@ -0,0 +1,14 @@
package alternativa {
/**
* Класс содержит информацию о версии библиотеки.
* Также используется для интеграции библиотеки в среду разработки Adobe Flash.
*/
public class Alternativa3D {
/**
* Версия библиотеки в формате: поколение.feature-версия.fix-версия
*/
public static const version:String = "7.0.0";
}
}

View File

@@ -0,0 +1,14 @@
package alternativa {
/**
* Класс содержит информацию о версии библиотеки.
* Также используется для интеграции библиотеки в среду разработки Adobe Flash.
*/
public class Alternativa3D {
/**
* Версия библиотеки в формате: поколение.feature-версия.fix-версия
*/
public static const version:String = "7.0.0";
}
}

Binary file not shown.

View File

@@ -0,0 +1,11 @@
K 25
svn:wc:ra_dav:version-url
V 99
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d
END
alternativa3d.as
K 25
svn:wc:ra_dav:version-url
V 116
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/alternativa3d.as
END

View File

@@ -0,0 +1,58 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d
http://svndev.alternativaplatform.com
2009-06-28T14:57:52.173273Z
15193
int
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
alternativa3d.as
file
2010-10-28T04:31:04.000000Z
64183f832985e252cc4bc98977484bc9
2009-02-11T11:56:39.925226Z
7238
wolf
containers
dir
controllers
dir
core
dir
loaders
dir
objects
dir
primitives
dir

View File

@@ -0,0 +1 @@
8

View File

@@ -0,0 +1,3 @@
package alternativa.engine3d {
public namespace alternativa3d = "http://alternativaplatform.com/en/alternativa3d";
}

View File

@@ -0,0 +1,3 @@
package alternativa.engine3d {
public namespace alternativa3d = "http://alternativaplatform.com/en/alternativa3d";
}

View File

@@ -0,0 +1,35 @@
K 25
svn:wc:ra_dav:version-url
V 110
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/containers
END
KDTree.as
K 25
svn:wc:ra_dav:version-url
V 120
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/containers/KDTree.as
END
SplitContainer.as
K 25
svn:wc:ra_dav:version-url
V 128
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/containers/SplitContainer.as
END
SkyBox.as
K 25
svn:wc:ra_dav:version-url
V 120
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/containers/SkyBox.as
END
DirectionContainer.as
K 25
svn:wc:ra_dav:version-url
V 132
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/containers/DirectionContainer.as
END
AverageZContainer.as
K 25
svn:wc:ra_dav:version-url
V 131
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/containers/AverageZContainer.as
END

View File

@@ -0,0 +1,88 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/containers
http://svndev.alternativaplatform.com
2009-06-25T11:51:01.015697Z
15140
int
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
KDTree.as
file
2010-10-28T04:31:04.000000Z
db8b0a5eae379b6bf019ac094814cdd7
2009-06-25T11:51:01.015697Z
15140
int
SplitContainer.as
file
2010-10-28T04:31:04.000000Z
285288fe28f8e348ae79b31cf302666d
2009-06-11T09:21:13.390850Z
14302
int
SkyBox.as
file
2010-10-28T04:31:04.000000Z
b4b5f0c0b433000fe80e1c9f2710cba5
2009-06-11T09:21:13.390850Z
14302
int
DirectionContainer.as
file
2010-10-28T04:31:04.000000Z
4c3461704e4a438b0967c96d96bba57d
2009-06-11T09:21:13.390850Z
14302
int
AverageZContainer.as
file
2010-10-28T04:31:04.000000Z
bdafd4f00bcc9cf7e33460dbb1f74284
2009-06-25T11:51:01.015697Z
15140
int

View File

@@ -0,0 +1,66 @@
package alternativa.engine3d.containers {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import flash.geom.Vector3D;
import alternativa.engine3d.core.Camera3D;
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>();
private var sortingStackIndex:int;
private var sortingLeft:Number;
private var sortingMedian:Number;
private var sortingRight:Number;
private var sortingChild:Object3D;
override protected function calculateOrder(camera:Camera3D, object:Object3D):void {
// Сортировка
for (var i:int = 0; i < numVisibleChildren; i++) {
(visibleChildren[i] as Object3D).cameraMatrix.transformVectors(center, cameraCenter);
averageZ[i] = cameraCenter[0]*cameraCenter[0] + cameraCenter[1]*cameraCenter[1] + cameraCenter[2]*cameraCenter[2];
}
var j:int, l:int = 0, r:int = numVisibleChildren - 1;
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;
}
}
}
}
}

View File

@@ -0,0 +1,28 @@
package alternativa.engine3d.containers {
import alternativa.engine3d.alternativa3d;
import flash.geom.Vector3D;
import alternativa.engine3d.core.Camera3D;
import alternativa.engine3d.core.Object3D;
import alternativa.engine3d.core.Object3DContainer;
use namespace alternativa3d;
public class DirectionContainer extends Object3DContainer {
public var direction:Vector3D = new Vector3D(0, 0, -1);
override protected function calculateOrder(camera:Camera3D, object:Object3D):void {
if (Vector3D.Z_AXIS.dotProduct(object.cameraMatrix.deltaTransformVector(direction)) < 0) {
var num:uint = numVisibleChildren >> 1;
for (var i:uint = 0; i < num; i++) {
var child:Object3D = visibleChildren[i];
visibleChildren[i] = visibleChildren[numVisibleChildren - 1 - i];
visibleChildren[numVisibleChildren - 1 - i] = child;
}
}
}
}
}

View File

@@ -0,0 +1,156 @@
package alternativa.engine3d.containers {
import flash.display.BitmapData;
import __AS3__.vec.Vector;
import alternativa.engine3d.core.Object3DContainer;
import alternativa.engine3d.objects.Mesh;
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():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.perspectiveCorrection = true;
frontPlane.perspectiveCorrection = true;
topPlane.perspectiveCorrection = true;
bottomPlane.perspectiveCorrection = true;
leftPlane.perspectiveCorrection = true;
rightPlane.perspectiveCorrection = true;
const size:Number = 1000;
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 uvs:Vector.<Number> = Vector.<Number>([1, 1, 1, 0, 0, 0, 0, 1]);
backPlane.uvs = uvs;
frontPlane.uvs = uvs;
topPlane.uvs = uvs;
bottomPlane.uvs = uvs;
leftPlane.uvs = uvs;
rightPlane.uvs = uvs;
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;
}
}
}

View File

@@ -0,0 +1,38 @@
package alternativa.engine3d.containers {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import alternativa.engine3d.core.Camera3D;
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 calculateOrder(camera:Camera3D, object:Object3D):void {
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) {
var num:uint = numVisibleChildren >> 1;
for (var i:uint = 0; i < num; i++) {
var child:Object3D = visibleChildren[i];
visibleChildren[i] = visibleChildren[numVisibleChildren - 1 - i];
visibleChildren[numVisibleChildren - 1 - i] = child;
}
}
}
}
}

View File

@@ -0,0 +1,66 @@
package alternativa.engine3d.containers {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import flash.geom.Vector3D;
import alternativa.engine3d.core.Camera3D;
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>();
private var sortingStackIndex:int;
private var sortingLeft:Number;
private var sortingMedian:Number;
private var sortingRight:Number;
private var sortingChild:Object3D;
override protected function calculateOrder(camera:Camera3D, object:Object3D):void {
// Сортировка
for (var i:int = 0; i < numVisibleChildren; i++) {
(visibleChildren[i] as Object3D).cameraMatrix.transformVectors(center, cameraCenter);
averageZ[i] = cameraCenter[0]*cameraCenter[0] + cameraCenter[1]*cameraCenter[1] + cameraCenter[2]*cameraCenter[2];
}
var j:int, l:int = 0, r:int = numVisibleChildren - 1;
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;
}
}
}
}
}

View File

@@ -0,0 +1,28 @@
package alternativa.engine3d.containers {
import alternativa.engine3d.alternativa3d;
import flash.geom.Vector3D;
import alternativa.engine3d.core.Camera3D;
import alternativa.engine3d.core.Object3D;
import alternativa.engine3d.core.Object3DContainer;
use namespace alternativa3d;
public class DirectionContainer extends Object3DContainer {
public var direction:Vector3D = new Vector3D(0, 0, -1);
override protected function calculateOrder(camera:Camera3D, object:Object3D):void {
if (Vector3D.Z_AXIS.dotProduct(object.cameraMatrix.deltaTransformVector(direction)) < 0) {
var num:uint = numVisibleChildren >> 1;
for (var i:uint = 0; i < num; i++) {
var child:Object3D = visibleChildren[i];
visibleChildren[i] = visibleChildren[numVisibleChildren - 1 - i];
visibleChildren[numVisibleChildren - 1 - i] = child;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
package alternativa.engine3d.containers {
import flash.display.BitmapData;
import __AS3__.vec.Vector;
import alternativa.engine3d.core.Object3DContainer;
import alternativa.engine3d.objects.Mesh;
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():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.perspectiveCorrection = true;
frontPlane.perspectiveCorrection = true;
topPlane.perspectiveCorrection = true;
bottomPlane.perspectiveCorrection = true;
leftPlane.perspectiveCorrection = true;
rightPlane.perspectiveCorrection = true;
const size:Number = 1000;
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 uvs:Vector.<Number> = Vector.<Number>([1, 1, 1, 0, 0, 0, 0, 1]);
backPlane.uvs = uvs;
frontPlane.uvs = uvs;
topPlane.uvs = uvs;
bottomPlane.uvs = uvs;
leftPlane.uvs = uvs;
rightPlane.uvs = uvs;
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;
}
}
}

View File

@@ -0,0 +1,38 @@
package alternativa.engine3d.containers {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import alternativa.engine3d.core.Camera3D;
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 calculateOrder(camera:Camera3D, object:Object3D):void {
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) {
var num:uint = numVisibleChildren >> 1;
for (var i:uint = 0; i < num; i++) {
var child:Object3D = visibleChildren[i];
visibleChildren[i] = visibleChildren[numVisibleChildren - 1 - i];
visibleChildren[numVisibleChildren - 1 - i] = child;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
K 25
svn:wc:ra_dav:version-url
V 111
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/controllers
END
SimpleObjectController.as
K 25
svn:wc:ra_dav:version-url
V 137
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/controllers/SimpleObjectController.as
END

View File

@@ -0,0 +1,40 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/controllers
http://svndev.alternativaplatform.com
2009-04-26T14:29:18.192027Z
11986
mike
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
SimpleObjectController.as
file
2010-10-28T04:31:04.000000Z
f4a127bf817a1469ad6f70f2672151c9
2009-04-26T14:29:18.192027Z
11986
mike

View File

@@ -0,0 +1,450 @@
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;
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;
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);
}
}
}

View File

@@ -0,0 +1,450 @@
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;
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;
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);
}
}
}

View File

@@ -0,0 +1,59 @@
K 25
svn:wc:ra_dav:version-url
V 104
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core
END
Object3D.as
K 25
svn:wc:ra_dav:version-url
V 116
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/Object3D.as
END
Camera3D.as
K 25
svn:wc:ra_dav:version-url
V 116
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/Camera3D.as
END
BoundBox.as
K 25
svn:wc:ra_dav:version-url
V 116
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/BoundBox.as
END
Object3DContainer.as
K 25
svn:wc:ra_dav:version-url
V 125
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/Object3DContainer.as
END
MeshMath.hx
K 25
svn:wc:ra_dav:version-url
V 116
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/MeshMath.hx
END
MipMap.as
K 25
svn:wc:ra_dav:version-url
V 114
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/MipMap.as
END
KDNode.as
K 25
svn:wc:ra_dav:version-url
V 114
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/KDNode.as
END
BSPNode.as
K 25
svn:wc:ra_dav:version-url
V 115
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/BSPNode.as
END
Canvas.as
K 25
svn:wc:ra_dav:version-url
V 114
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core/Canvas.as
END

View File

@@ -0,0 +1,139 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/core
http://svndev.alternativaplatform.com
2009-06-28T14:57:52.173273Z
15193
int
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
Object3D.as
file
2010-10-28T04:31:04.000000Z
dd548c0f9eaa4771ce63bdf851c7bf15
2009-06-26T11:59:58.557105Z
15183
int
has-props
Camera3D.as
file
2010-10-28T04:31:04.000000Z
b84355435ee36b9862a34e32900fe913
2009-06-28T14:57:52.173273Z
15193
int
BoundBox.as
file
2010-10-28T04:31:04.000000Z
729f4c838c872d947f7b3a85290d4081
2009-06-11T09:21:13.390850Z
14302
int
has-props
Object3DContainer.as
file
2010-10-28T04:31:04.000000Z
8a2cfd5cd28391f712c9e8ea6730c2fe
2009-06-25T11:51:01.015697Z
15140
int
MeshMath.hx
file
2010-10-28T04:31:04.000000Z
970cec8de096e9635bc389d02f351d69
2009-02-17T05:29:17.508178Z
7592
wolf
MipMap.as
file
2010-10-28T04:31:04.000000Z
3af2aeb1a132098a771adaa8350db4c3
2009-06-25T11:51:01.015697Z
15140
int
KDNode.as
file
2010-10-28T04:31:04.000000Z
bebdc6eb5ec3f68bb58b26d53b7cdc25
2009-06-11T09:21:13.390850Z
14302
int
BSPNode.as
file
2010-10-28T04:31:04.000000Z
7e765bd3aadb97db30a4259fbe186862
2009-06-25T11:51:01.015697Z
15140
int
Canvas.as
file
2010-10-28T04:31:04.000000Z
1dc393e4f075faf10e6b2a337a0bb72f
2009-06-25T11:51:01.015697Z
15140
int
has-props

View File

@@ -0,0 +1 @@
8

View File

@@ -0,0 +1,10 @@
K 13
svn:mergeinfo
V 720
/platform/clients/fp10/libraries/Alternativa3D/branches/7.0/src/alternativa/engine3d/bounds/BoundBox.as:5796-7235
/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

View File

@@ -0,0 +1,5 @@
K 13
svn:mergeinfo
V 0
END

View File

@@ -0,0 +1,9 @@
K 13
svn:mergeinfo
V 596
/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

View File

@@ -0,0 +1,66 @@
package alternativa.engine3d.core {
import alternativa.engine3d.alternativa3d;
import __AS3__.vec.Vector;
use namespace alternativa3d;
public class BSPNode {
static private var collector:Vector.<BSPNode> = new Vector.<BSPNode>();
static private var collectorLength:int = 0;
// Нормаль и смещение
public var normal:int;
// Дочерние ноды
public var negative:BSPNode;
public var positive:BSPNode;
// Треугольники
public var triangles:Vector.<int> = new Vector.<int>();
public var trianglesLength:uint = 0;
// Полигоны
public var polygons:Vector.<int> = new Vector.<int>();
public var polygonsLength:uint = 0;
// Флаг расположения камеры
public var cameraInfront:Boolean;
static alternativa3d function create():BSPNode {
return (collectorLength > 0) ? collector[--collectorLength] : new BSPNode();
}
public function create():BSPNode {
return (collectorLength > 0) ? collector[--collectorLength] : new BSPNode();
}
public function destroy():void {
if (negative != null) {
negative.destroy();
negative = null;
}
if (positive != null) {
positive.destroy();
positive = null;
}
trianglesLength = 0;
polygonsLength = 0;
collector[collectorLength++] = this;
}
// Добавление фрагмента в ноду
public function addFragment(fragment:Vector.<int>, begin:int, end:int):void {
polygons[polygonsLength++] = end - begin;
var i:int = begin, a:int = polygons[polygonsLength++] = fragment[i++], b:int = polygons[polygonsLength++] = fragment[i++], c:int;
while (i < end) {
triangles[trianglesLength++] = a;
triangles[trianglesLength++] = b;
triangles[trianglesLength++] = c = polygons[polygonsLength++] = fragment[i++];
b = c;
}
}
}
}

View File

@@ -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) + "]";
}
}
}

View File

@@ -0,0 +1,195 @@
package alternativa.engine3d.core {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import alternativa.engine3d.objects.Mesh;
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 farClipping:Number = 5000;
public var farFalloff:Number = 4000;
public var nearClipping:Number = 50;
// Матрица проецирования
/**
* @private
*/
alternativa3d var projectionMatrixData:Vector.<Number> = new Vector.<Number>(16, true);
/**
* @private
*/
alternativa3d var projectionMatrix:Matrix3D;
// Параметры перспективы
/**
* @private
*/
alternativa3d var viewSize:Number;
/**
* @private
*/
alternativa3d var viewSizeX:Number;
/**
* @private
*/
alternativa3d var viewSizeY:Number;
/**
* @private
*/
alternativa3d var perspectiveScaleX:Number;
/**
* @private
*/
alternativa3d var perspectiveScaleY:Number;
/**
* @private
*/
alternativa3d var invertPerspectiveScaleX:Number;
/**
* @private
*/
alternativa3d var invertPerspectiveScaleY:Number;
/**
* @private
*/
alternativa3d var focalLength:Number;
// Перекрытия
/**
* @private
*/
alternativa3d var occlusionPlanes:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
/**
* @private
*/
alternativa3d var occlusionEdges:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
/**
* @private
*/
alternativa3d var numOccluders:int;
/**
* @private
*/
alternativa3d var occludedAll:Boolean;
/**
* @private
*/
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;
Mesh.numDrawingTriangles = 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;
object.draw(this, object, canvas);
// Если не нарисовалось, зачищаем рутовый канвас
if (canvas.numDraws == 0) canvas.removeChildren(0);
} 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;
invertPerspectiveScaleX = viewSizeX/focalLength;
invertPerspectiveScaleY = viewSizeY/focalLength;
// Подготовка матрицы проецирования
projectionMatrixData[0] = viewSizeX;
projectionMatrixData[5] = viewSizeY;
projectionMatrixData[10] = 1;
projectionMatrixData[11] = 1;
projectionMatrix = new Matrix3D(projectionMatrixData);
}
/*
// Occlusion culling
if (numOccluders > 0) {
for (var n:int = 0; n < numOccluders; n++) {
var occluder:Vector.<Number> = occluders[n];
var occlude:Boolean = true;
occlude: for (var j:int = 0, length:int = occluder.length; j < length;) {
var x:Number = occluder[j++], y:Number = occluder[j++], z:Number = occluder[j++]
for (i = 0; i <= 21; i += 3) {
if (boundBoxVertices[i]*x + boundBoxVertices[int(i + 1)]*y + boundBoxVertices[int(i + 2)]*z > 0) {
occlude = false;
break occlude;
}
}
}
if (occlude) return -1;
}
}
*/
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;
}
}
}

View File

@@ -0,0 +1,78 @@
package alternativa.engine3d.core {
import alternativa.engine3d.alternativa3d;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import __AS3__.vec.Vector;
import flash.display.DisplayObject;
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;
/**
* @private
*/
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;
/**
* @private
*/
alternativa3d var _numChildren:int = 0;
/**
* @private
*/
alternativa3d var numDraws:int = 0;
public function Canvas() {
mouseEnabled = false;
mouseChildren = false;
}
/**
* @private
*/
alternativa3d function getChildCanvas(useGraphics:Boolean, useChildren:Boolean, alpha:Number, blendMode:String, colorTransform:ColorTransform, filters:Array):Canvas {
var canvas:Canvas, 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() else canvas = (collectorLength > 0) ? collector[--collectorLength] : new Canvas(), addChildAt(canvas, 0), _numChildren++;
// Пометка о том, что в graphics будет что-то нарисовано
canvas.modifiedGraphics = useGraphics;
// Если не нужны дочерние канвасы
if (!useChildren) canvas.removeChildren(0);
// Установка свойств
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;
}
/**
* @private
*/
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();
canvas.removeChildren(0), collector[collectorLength++] = canvas;
}
}
}
}
}

View File

@@ -0,0 +1,23 @@
package alternativa.engine3d.core {
import __AS3__.vec.Vector;
public final class KDNode {
public var axis:int; // 0 - x, 1 - y, 2 - z
public var coord:Number;
public var minCoord:Number;
public var maxCoord:Number;
public var positive:KDNode;
public var negative:KDNode;
public var boundBox:BoundBox;
public var objects:Vector.<Object3D>;
public var bounds:Vector.<BoundBox>;
public var numObjects:int = 0;
public var numNonOccluders:int = 0;
}
}

View File

@@ -0,0 +1,49 @@
package alternativa.engine3d.core;
class MeshMath {
/**
public function test():Void {
var m = flash.Memory;
var x:Float;
for (n in 0...1000000) {
x = n;
//1/m.sqrt(x);
//invSqrt(n);
var half = 0.5 * x;
m.setFloat(0,x);
var i = m.getI32(0);
i = 0x5f3759df - (i>>1);
m.setI32(0,i);
x = m.getFloat(0);
x = x * (1.5 - half*x*x);
}
return;
}
public function inverseSqrt(n:Float):Float {
return 1/Math.sqrt(n);
}
public function prepare() {
var b = new flash.utils.ByteArray();
b.length = 1024;
flash.Memory.select(b);
}
inline function invSqrt( x : Float ) : Float {
var half = 0.5 * x;
flash.Memory.setFloat(0,x);
var i = flash.Memory.getI32(0);
i = 0x5f3759df - (i>>1);
flash.Memory.setI32(0,i);
x = flash.Memory.getFloat(0);
x = x * (1.5 - half*x*x);
return x;
}
**/
}

View 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;
}
}
}

View File

@@ -0,0 +1,257 @@
package alternativa.engine3d.core {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import flash.geom.ColorTransform;
import flash.geom.Matrix3D;
import flash.geom.Utils3D;
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;
/**
* @private
*/
alternativa3d var _parent:Object3DContainer;
/**
* @private
*/
alternativa3d var _boundBox:BoundBox;
/**
* @private
*/
alternativa3d var culling:int = 0;
/**
* @private
*/
alternativa3d var cameraMatrix:Matrix3D = new Matrix3D();
static private const boundBoxVertices:Vector.<Number> = new Vector.<Number>(24, true);
/**
* @private
* Может быть отрисован
*/
alternativa3d function get canDraw():Boolean {
return true;
}
/**
* @private
* Отрисовка
*/
alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {}
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;
}
static private const boundBoxProjectedVertices:Vector.<Number> = new Vector.<Number>(16, true);
static private const boundBoxUVTs:Vector.<Number> = new Vector.<Number>(24, true);
/**
* @private
*/
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]);
}
}
}

View File

@@ -0,0 +1,164 @@
package alternativa.engine3d.core {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import flash.geom.Matrix3D;
use namespace alternativa3d;
/**
* Базовый контейнер трёхмерных объектов.
* Логика контейнеров и child-parent-отношений идентична логике
* displayObject'ов во Flash.
*/
public class Object3DContainer extends Object3D {
static public var debug:Boolean = false;
/**
* @private
*/
alternativa3d var _numChildren:int = 0;
/**
* @private
*/
alternativa3d var children:Vector.<Object3D> = new Vector.<Object3D>();
protected var numVisibleChildren:int = 0;
protected var visibleChildren:Vector.<Object3D> = new Vector.<Object3D>();
/**
* @private
*/
override alternativa3d function get canDraw():Boolean {
return _numChildren > 0;
}
/**
* @private
*/
override alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
// Определяем видимые объекты
numVisibleChildren = 0;
calculateVisibleChildren(camera, object);
// Если нет видимых дочерних объектов выходим без отрисовки
if (numVisibleChildren == 0) return;
// Расчёт порядка вывода видимых объектов
calculateOrder(camera, object);
// Отрисовка видимых объектов
drawVisibleChildren(camera, object, parentCanvas);
}
protected function calculateVisibleChildren(camera:Camera3D, object:Object3D):void {
var i:int = 0, child:Object3D;
while (i < _numChildren) {
child = 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;
}
}
}
// Подрезаем список видимых детей
visibleChildren.length = numVisibleChildren;
}
protected function calculateOrder(camera:Camera3D, object:Object3D):void {}
// Отрисовка сзади детей
protected function drawBack(camera:Camera3D, object:Object3D, canvas:Canvas):void {}
// Отрисовка перед детьми
protected function drawFront(camera:Camera3D, object:Object3D, canvas:Canvas):void {}
// Отрисовка видимых детей
protected function drawVisibleChildren(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
// Подготовка канваса
var canvas:Canvas = parentCanvas.getChildCanvas(debug, true, object.alpha, object.blendMode, object.colorTransform, object.filters);
canvas.numDraws = 0;
// Отрисовываем перед детьми
drawFront(camera, object, canvas);
// Отрисовываем видимые дочерние объекты от ближних к дальним
var child:Object3D;
for (var i:int = numVisibleChildren - 1; i >= 0; i--) {
(child = visibleChildren[i]).draw(camera, child, canvas);
}
// Отрисовываем после детей
drawBack(camera, object, canvas);
// Если не было отрисовки
if (canvas.numDraws == 0) {
parentCanvas.numDraws--;
return;
}
// Зачищаем остатки
canvas.removeChildren(canvas.numDraws);
if (debug) object.drawBoundBox(camera, canvas);
}
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;
}
}
}

View File

@@ -0,0 +1,66 @@
package alternativa.engine3d.core {
import alternativa.engine3d.alternativa3d;
import __AS3__.vec.Vector;
use namespace alternativa3d;
public class BSPNode {
static private var collector:Vector.<BSPNode> = new Vector.<BSPNode>();
static private var collectorLength:int = 0;
// Нормаль и смещение
public var normal:int;
// Дочерние ноды
public var negative:BSPNode;
public var positive:BSPNode;
// Треугольники
public var triangles:Vector.<int> = new Vector.<int>();
public var trianglesLength:uint = 0;
// Полигоны
public var polygons:Vector.<int> = new Vector.<int>();
public var polygonsLength:uint = 0;
// Флаг расположения камеры
public var cameraInfront:Boolean;
static alternativa3d function create():BSPNode {
return (collectorLength > 0) ? collector[--collectorLength] : new BSPNode();
}
public function create():BSPNode {
return (collectorLength > 0) ? collector[--collectorLength] : new BSPNode();
}
public function destroy():void {
if (negative != null) {
negative.destroy();
negative = null;
}
if (positive != null) {
positive.destroy();
positive = null;
}
trianglesLength = 0;
polygonsLength = 0;
collector[collectorLength++] = this;
}
// Добавление фрагмента в ноду
public function addFragment(fragment:Vector.<int>, begin:int, end:int):void {
polygons[polygonsLength++] = end - begin;
var i:int = begin, a:int = polygons[polygonsLength++] = fragment[i++], b:int = polygons[polygonsLength++] = fragment[i++], c:int;
while (i < end) {
triangles[trianglesLength++] = a;
triangles[trianglesLength++] = b;
triangles[trianglesLength++] = c = polygons[polygonsLength++] = fragment[i++];
b = c;
}
}
}
}

View File

@@ -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) + "]";
}
}
}

View File

@@ -0,0 +1,195 @@
package alternativa.engine3d.core {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import alternativa.engine3d.objects.Mesh;
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 farClipping:Number = 5000;
public var farFalloff:Number = 4000;
public var nearClipping:Number = 50;
// Матрица проецирования
/**
* @private
*/
alternativa3d var projectionMatrixData:Vector.<Number> = new Vector.<Number>(16, true);
/**
* @private
*/
alternativa3d var projectionMatrix:Matrix3D;
// Параметры перспективы
/**
* @private
*/
alternativa3d var viewSize:Number;
/**
* @private
*/
alternativa3d var viewSizeX:Number;
/**
* @private
*/
alternativa3d var viewSizeY:Number;
/**
* @private
*/
alternativa3d var perspectiveScaleX:Number;
/**
* @private
*/
alternativa3d var perspectiveScaleY:Number;
/**
* @private
*/
alternativa3d var invertPerspectiveScaleX:Number;
/**
* @private
*/
alternativa3d var invertPerspectiveScaleY:Number;
/**
* @private
*/
alternativa3d var focalLength:Number;
// Перекрытия
/**
* @private
*/
alternativa3d var occlusionPlanes:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
/**
* @private
*/
alternativa3d var occlusionEdges:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
/**
* @private
*/
alternativa3d var numOccluders:int;
/**
* @private
*/
alternativa3d var occludedAll:Boolean;
/**
* @private
*/
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;
Mesh.numDrawingTriangles = 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;
object.draw(this, object, canvas);
// Если не нарисовалось, зачищаем рутовый канвас
if (canvas.numDraws == 0) canvas.removeChildren(0);
} 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;
invertPerspectiveScaleX = viewSizeX/focalLength;
invertPerspectiveScaleY = viewSizeY/focalLength;
// Подготовка матрицы проецирования
projectionMatrixData[0] = viewSizeX;
projectionMatrixData[5] = viewSizeY;
projectionMatrixData[10] = 1;
projectionMatrixData[11] = 1;
projectionMatrix = new Matrix3D(projectionMatrixData);
}
/*
// Occlusion culling
if (numOccluders > 0) {
for (var n:int = 0; n < numOccluders; n++) {
var occluder:Vector.<Number> = occluders[n];
var occlude:Boolean = true;
occlude: for (var j:int = 0, length:int = occluder.length; j < length;) {
var x:Number = occluder[j++], y:Number = occluder[j++], z:Number = occluder[j++]
for (i = 0; i <= 21; i += 3) {
if (boundBoxVertices[i]*x + boundBoxVertices[int(i + 1)]*y + boundBoxVertices[int(i + 2)]*z > 0) {
occlude = false;
break occlude;
}
}
}
if (occlude) return -1;
}
}
*/
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;
}
}
}

View File

@@ -0,0 +1,78 @@
package alternativa.engine3d.core {
import alternativa.engine3d.alternativa3d;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import __AS3__.vec.Vector;
import flash.display.DisplayObject;
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;
/**
* @private
*/
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;
/**
* @private
*/
alternativa3d var _numChildren:int = 0;
/**
* @private
*/
alternativa3d var numDraws:int = 0;
public function Canvas() {
mouseEnabled = false;
mouseChildren = false;
}
/**
* @private
*/
alternativa3d function getChildCanvas(useGraphics:Boolean, useChildren:Boolean, alpha:Number, blendMode:String, colorTransform:ColorTransform, filters:Array):Canvas {
var canvas:Canvas, 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() else canvas = (collectorLength > 0) ? collector[--collectorLength] : new Canvas(), addChildAt(canvas, 0), _numChildren++;
// Пометка о том, что в graphics будет что-то нарисовано
canvas.modifiedGraphics = useGraphics;
// Если не нужны дочерние канвасы
if (!useChildren) canvas.removeChildren(0);
// Установка свойств
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;
}
/**
* @private
*/
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();
canvas.removeChildren(0), collector[collectorLength++] = canvas;
}
}
}
}
}

View File

@@ -0,0 +1,23 @@
package alternativa.engine3d.core {
import __AS3__.vec.Vector;
public final class KDNode {
public var axis:int; // 0 - x, 1 - y, 2 - z
public var coord:Number;
public var minCoord:Number;
public var maxCoord:Number;
public var positive:KDNode;
public var negative:KDNode;
public var boundBox:BoundBox;
public var objects:Vector.<Object3D>;
public var bounds:Vector.<BoundBox>;
public var numObjects:int = 0;
public var numNonOccluders:int = 0;
}
}

View File

@@ -0,0 +1,49 @@
package alternativa.engine3d.core;
class MeshMath {
/**
public function test():Void {
var m = flash.Memory;
var x:Float;
for (n in 0...1000000) {
x = n;
//1/m.sqrt(x);
//invSqrt(n);
var half = 0.5 * x;
m.setFloat(0,x);
var i = m.getI32(0);
i = 0x5f3759df - (i>>1);
m.setI32(0,i);
x = m.getFloat(0);
x = x * (1.5 - half*x*x);
}
return;
}
public function inverseSqrt(n:Float):Float {
return 1/Math.sqrt(n);
}
public function prepare() {
var b = new flash.utils.ByteArray();
b.length = 1024;
flash.Memory.select(b);
}
inline function invSqrt( x : Float ) : Float {
var half = 0.5 * x;
flash.Memory.setFloat(0,x);
var i = flash.Memory.getI32(0);
i = 0x5f3759df - (i>>1);
flash.Memory.setI32(0,i);
x = flash.Memory.getFloat(0);
x = x * (1.5 - half*x*x);
return x;
}
**/
}

View 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;
}
}
}

View File

@@ -0,0 +1,257 @@
package alternativa.engine3d.core {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import flash.geom.ColorTransform;
import flash.geom.Matrix3D;
import flash.geom.Utils3D;
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;
/**
* @private
*/
alternativa3d var _parent:Object3DContainer;
/**
* @private
*/
alternativa3d var _boundBox:BoundBox;
/**
* @private
*/
alternativa3d var culling:int = 0;
/**
* @private
*/
alternativa3d var cameraMatrix:Matrix3D = new Matrix3D();
static private const boundBoxVertices:Vector.<Number> = new Vector.<Number>(24, true);
/**
* @private
* Может быть отрисован
*/
alternativa3d function get canDraw():Boolean {
return true;
}
/**
* @private
* Отрисовка
*/
alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {}
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;
}
static private const boundBoxProjectedVertices:Vector.<Number> = new Vector.<Number>(16, true);
static private const boundBoxUVTs:Vector.<Number> = new Vector.<Number>(24, true);
/**
* @private
*/
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]);
}
}
}

View File

@@ -0,0 +1,164 @@
package alternativa.engine3d.core {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import flash.geom.Matrix3D;
use namespace alternativa3d;
/**
* Базовый контейнер трёхмерных объектов.
* Логика контейнеров и child-parent-отношений идентична логике
* displayObject'ов во Flash.
*/
public class Object3DContainer extends Object3D {
static public var debug:Boolean = false;
/**
* @private
*/
alternativa3d var _numChildren:int = 0;
/**
* @private
*/
alternativa3d var children:Vector.<Object3D> = new Vector.<Object3D>();
protected var numVisibleChildren:int = 0;
protected var visibleChildren:Vector.<Object3D> = new Vector.<Object3D>();
/**
* @private
*/
override alternativa3d function get canDraw():Boolean {
return _numChildren > 0;
}
/**
* @private
*/
override alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
// Определяем видимые объекты
numVisibleChildren = 0;
calculateVisibleChildren(camera, object);
// Если нет видимых дочерних объектов выходим без отрисовки
if (numVisibleChildren == 0) return;
// Расчёт порядка вывода видимых объектов
calculateOrder(camera, object);
// Отрисовка видимых объектов
drawVisibleChildren(camera, object, parentCanvas);
}
protected function calculateVisibleChildren(camera:Camera3D, object:Object3D):void {
var i:int = 0, child:Object3D;
while (i < _numChildren) {
child = 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;
}
}
}
// Подрезаем список видимых детей
visibleChildren.length = numVisibleChildren;
}
protected function calculateOrder(camera:Camera3D, object:Object3D):void {}
// Отрисовка сзади детей
protected function drawBack(camera:Camera3D, object:Object3D, canvas:Canvas):void {}
// Отрисовка перед детьми
protected function drawFront(camera:Camera3D, object:Object3D, canvas:Canvas):void {}
// Отрисовка видимых детей
protected function drawVisibleChildren(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
// Подготовка канваса
var canvas:Canvas = parentCanvas.getChildCanvas(debug, true, object.alpha, object.blendMode, object.colorTransform, object.filters);
canvas.numDraws = 0;
// Отрисовываем перед детьми
drawFront(camera, object, canvas);
// Отрисовываем видимые дочерние объекты от ближних к дальним
var child:Object3D;
for (var i:int = numVisibleChildren - 1; i >= 0; i--) {
(child = visibleChildren[i]).draw(camera, child, canvas);
}
// Отрисовываем после детей
drawBack(camera, object, canvas);
// Если не было отрисовки
if (canvas.numDraws == 0) {
parentCanvas.numDraws--;
return;
}
// Зачищаем остатки
canvas.removeChildren(canvas.numDraws);
if (debug) object.drawBoundBox(camera, canvas);
}
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;
}
}
}

View File

@@ -0,0 +1,59 @@
K 25
svn:wc:ra_dav:version-url
V 107
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders
END
TextureFilesData.as
K 25
svn:wc:ra_dav:version-url
V 127
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/TextureFilesData.as
END
TextureMapsInfo.as
K 25
svn:wc:ra_dav:version-url
V 126
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/TextureMapsInfo.as
END
Loader3DS.as
K 25
svn:wc:ra_dav:version-url
V 120
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/Loader3DS.as
END
MaterialParams.as
K 25
svn:wc:ra_dav:version-url
V 125
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/MaterialParams.as
END
Parsed3DSData.as
K 25
svn:wc:ra_dav:version-url
V 124
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/Parsed3DSData.as
END
Loader3DSByteArray.as
K 25
svn:wc:ra_dav:version-url
V 129
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/Loader3DSByteArray.as
END
Parser3DS.as
K 25
svn:wc:ra_dav:version-url
V 120
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/Parser3DS.as
END
TextureMapsLoader.as
K 25
svn:wc:ra_dav:version-url
V 128
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/TextureMapsLoader.as
END
TextureMapsBatchLoader.as
K 25
svn:wc:ra_dav:version-url
V 133
/!svn/ver/15289/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders/TextureMapsBatchLoader.as
END

View File

@@ -0,0 +1,136 @@
8
dir
46043
http://svndev.alternativaplatform.com/platform/clients/fp10/libraries/Alternativa3D/tags/7.0.1.0/src/alternativa/engine3d/loaders
http://svndev.alternativaplatform.com
2009-06-23T12:58:38.998839Z
14991
mike
svn:special svn:externals svn:needs-lock
d9e2387a-1f3e-40e2-b57f-9df5970a2fa5
TextureFilesData.as
file
2010-10-28T04:31:04.000000Z
5dab534b47ec603953467a319d0a9757
2009-03-03T10:45:06.942390Z
8557
mike
TextureMapsInfo.as
file
2010-10-28T04:31:04.000000Z
88db02ba1e191078e041e5b06625a9fe
2009-03-05T12:10:13.528151Z
8769
mike
Loader3DS.as
file
2010-10-28T04:31:04.000000Z
06a527977ab57e84259cf76907867cce
2009-06-23T12:58:38.998839Z
14991
mike
MaterialParams.as
file
2010-10-28T04:31:04.000000Z
101884503099df0a70e423bd56fcfa4b
2009-03-03T10:45:06.942390Z
8557
mike
Parsed3DSData.as
file
2010-10-28T04:31:04.000000Z
9c3dbe4c093e301aa3af29bb56a12386
2009-03-03T10:45:06.942390Z
8557
mike
Loader3DSByteArray.as
file
2010-10-28T04:31:04.000000Z
d16c1ccc19f56c308fc4e92a39ca3376
2009-06-11T09:21:13.390850Z
14302
int
Parser3DS.as
file
2010-10-28T04:31:04.000000Z
6a24bd22eff8a189af160c48a2a37ce1
2009-06-23T12:58:38.998839Z
14991
mike
TextureMapsLoader.as
file
2010-10-28T04:31:04.000000Z
d07e5fd6b8c2272e7fbc209eb9bf1fb5
2009-03-05T12:10:13.528151Z
8769
mike
TextureMapsBatchLoader.as
file
2010-10-28T04:31:04.000000Z
e1185eb11ccfdcb06bc2aeb2ad03705f
2009-03-05T12:10:13.528151Z
8769
mike

View File

@@ -0,0 +1,931 @@
package alternativa.engine3d.loaders {
import __AS3__.vec.Vector;
import alternativa.engine3d.objects.Mesh;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Orientation3D;
import flash.geom.Point;
import flash.geom.Vector3D;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.utils.ByteArray;
import flash.utils.Endian;
[Event (name="complete", type="flash.events.Event")]
/**
*
*/
public class Loader3DS extends EventDispatcher {
private static const STATE_IDLE:int = -1;
private static const STATE_LOADING_MODEL:int = 0;
private static const STATE_LOADING_TEXTURES:int = 1;
private static var stubBitmapData:BitmapData;
private var _content:Vector.<Mesh>;
private var version:uint;
private var objectDatas:Object;
private var animationDatas:Array;
private var materialDatas:Array;
private var bitmaps:Array;
private var modelLoader:URLLoader;
private var textureLoader:TextureMapsLoader;
private var data:ByteArray;
private var counter:int;
private var textureMaterialNames:Array;
private var context:LoaderContext;
private var path:String;
private var loaderState:int = STATE_IDLE;
/**
* Повтор текстуры при заливке для создаваемых текстурных материалов.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var repeat:Boolean = true;
/**
* Сглаживание текстур при увеличении масштаба.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var smooth:Boolean = false;
/**
* Режим наложения цвета для создаваемых текстурных материалов.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var blendMode:String = BlendMode.NORMAL;
/**
* Коэффициент пересчёта единиц измерения модели.
*/
public var units:Number = 1;
/**
* Устанавливаемый уровень мобильности загруженных объектов.
*/
public var mobility:int = 0;
/**
* Прекращение текущей загрузки.
*/
public function close():void {
if (loaderState == STATE_LOADING_MODEL) {
modelLoader.close();
}
if (loaderState == STATE_LOADING_TEXTURES) {
textureLoader.close();
}
loaderState = STATE_IDLE;
}
/**
* Метод очищает внутренние ссылки на загруженные данные чтобы сборщик мусора мог освободить занимаемую ими память. Метод не работает
* во время загрузки.
*/
public function unload():void {
if (loaderState == STATE_IDLE) {
clean();
}
}
private function clean():void {
_content = null;
objectDatas = null;
animationDatas = null;
materialDatas = null;
bitmaps = null;
textureMaterialNames = null;
}
public function load(url:String, context:LoaderContext = null):void {
path = url.substring(0, url.lastIndexOf("/") + 1);
this.context = context;
// Очистка
version = 0;
clean();
if (modelLoader == null) {
modelLoader = new URLLoader();
modelLoader.dataFormat = URLLoaderDataFormat.BINARY;
modelLoader.addEventListener(Event.COMPLETE, on3DSLoad);
modelLoader.addEventListener(IOErrorEvent.IO_ERROR, on3DSError);
modelLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on3DSError);
} else {
close();
}
loaderState = STATE_LOADING_MODEL;
modelLoader.load(new URLRequest(url));
}
private function on3DSLoad(e:Event):void {
loaderState = STATE_IDLE;
data = modelLoader.data;
data.endian = Endian.LITTLE_ENDIAN;
parse3DSChunk(0, data.bytesAvailable);
}
private function on3DSError(e:Event):void {
loaderState = STATE_IDLE;
dispatchEvent(e);
}
private function loadBitmaps():void {
if (textureLoader == null) {
textureLoader = new TextureMapsLoader();
textureLoader.addEventListener(Event.COMPLETE, loadNextBitmap);
textureLoader.addEventListener(IOErrorEvent.IO_ERROR, loadNextBitmap);
}
// Имена материалов с диффузными текстурами собираются в массив textureMaterialNames
bitmaps = new Array();
textureMaterialNames = new Array();
for each (var materialData:MaterialData in materialDatas) {
if (materialData.diffuseMap != null) {
textureMaterialNames.push(materialData.name);
}
}
loaderState = STATE_LOADING_TEXTURES;
loadNextBitmap();
}
private function loadNextBitmap(e:Event = null):void {
if (e != null) {
if (!(e is IOErrorEvent)) {
bitmaps[textureMaterialNames[counter]] = textureLoader.bitmapData;
} else {
if (stubBitmapData == null) {
var size:uint = 20;
stubBitmapData = new BitmapData(size, size, false, 0);
for (var i:uint = 0; i < size; i++) {
for (var j:uint = 0; j < size; j+=2) {
stubBitmapData.setPixel((i % 2) ? j : (j+1), i, 0xFF00FF);
}
}
}
bitmaps[textureMaterialNames[counter]] = stubBitmapData;
}
} else {
counter = -1;
}
counter++;
if (counter < textureMaterialNames.length) {
var materialData:MaterialData = materialDatas[textureMaterialNames[counter]];
textureLoader.load(path + materialData.diffuseMap.filename, materialData.opacityMap == null ? null : path + materialData.opacityMap.filename, context);
} else {
loaderState = STATE_IDLE;
buildContent();
}
}
private function buildContent():void {
var i:uint;
var length:uint;
// Формируем связи объектов
_content = new Vector.<Mesh>();
// Создаём материалы
var materialData:MaterialData;
for (var materialName:String in materialDatas) {
materialData = materialDatas[materialName];
var mapData:MapData = materialData.diffuseMap;
var materialMatrix:Matrix = new Matrix();
if (mapData != null) {
var rot:Number = mapData.rotation*Math.PI/180;
var rotSin:Number = Math.sin(rot);
var rotCos:Number = Math.cos(rot);
materialMatrix.translate(-mapData.offsetU, mapData.offsetV);
materialMatrix.translate(-0.5, -0.5);
materialMatrix.rotate(-rot);
materialMatrix.scale(mapData.scaleU, mapData.scaleV);
materialMatrix.translate(0.5, 0.5);
}
materialData.matrix = materialMatrix;
}
// Если есть данные об анимации и иерархии объектов
var objectName:String;
var objectData:ObjectData;
var mesh:Mesh;
if (animationDatas != null) {
if (objectDatas != null) {
length = animationDatas.length;
for (i = 0; i < length; i++) {
var animationData:AnimationData = animationDatas[i];
objectName = animationData.objectName;
objectData = objectDatas[objectName];
// Если на один объект приходится несколько данных об анимации
if (objectData != null) {
var nameCounter:uint = 2;
for (var j:uint = i + 1; j < length; j++) {
var animationData2:AnimationData = animationDatas[j];
if (objectName == animationData2.objectName) {
var newName:String = objectName + nameCounter;
var newObjectData:ObjectData = new ObjectData();
animationData2.objectName = newName;
newObjectData.name = newName;
if (objectData.vertices != null) {
newObjectData.vertices = new Vector.<Vector3D>().concat(objectData.vertices);
}
if (objectData.uvs != null) {
newObjectData.uvs = new new Vector.<Point>().concat(objectData.uvs);
}
if (objectData.matrix != null) {
newObjectData.matrix = objectData.matrix.clone();
}
if (objectData.faces != null) {
newObjectData.faces = new Array().concat(objectData.faces);
}
if (objectData.surfaces != null) {
newObjectData.surfaces = objectData.surfaces.clone();
}
objectDatas[newName] = newObjectData;
nameCounter++;
}
}
}
if (objectData != null && objectData.vertices != null) {
// Меш
mesh = new Mesh();
mesh.createEmptyGeometry(objectData.vertices.length, objectData.faces.length);
animationData.object = mesh;
buildObject(animationData);
buildMesh(mesh, objectData, animationData);
_content.push(mesh);
}
}
}
} else {
for (objectName in objectDatas) {
objectData = objectDatas[objectName];
if (objectData.vertices != null) {
// Меш
mesh = new Mesh();
mesh.createEmptyGeometry(objectData.vertices.length, objectData.faces.length);
buildMesh(mesh, objectData, null);
_content.push(mesh);
}
}
}
// Рассылаем событие о завершении
dispatchEvent(new Event(Event.COMPLETE));
}
private function buildObject(animationData:AnimationData):void {
var object:Mesh = animationData.object;
object.name = animationData.objectName;
var transform:Vector.<Vector3D> = new Vector.<Vector3D>(3, true);
transform[0] = (animationData.position == null) ? new Vector3D() : new Vector3D(animationData.position.x * units, animationData.position.y * units, animationData.position.z * units);
transform[1] = (animationData.rotation == null) ? new Vector3D() : animationData.rotation.clone();
transform[2] = (animationData.scale == null) ? new Vector3D(1, 1, 1) : animationData.scale.clone();
object.matrix.recompose(transform, Orientation3D.AXIS_ANGLE);
}
private function buildMesh(mesh:Mesh, objectData:ObjectData, animationData:AnimationData):void {
// Добавляем вершины
var i:uint;
var j:uint;
var k:uint;
var key:*;
var length:uint = objectData.vertices.length;
for (i = 0; i < length; i++) {
var vertexData:Vector3D = objectData.vertices[i];
var uv:Point = objectData.uvs[i];
j = i*3;
mesh.vertices[j] = vertexData.x;
mesh.vertices[j + 1] = vertexData.y;
mesh.vertices[j + 2] = vertexData.z;
mesh.uvts[j] = uv.x;
mesh.uvts[j + 1] = 1 - uv.y;
k = i << 1;
mesh.uvs[k] = uv.x;
mesh.uvs[k + 1] = 1 - uv.y;
}
// Коррекция вершин
if (animationData != null) {
// Инвертируем матрицу
objectData.matrix.invert();
// Вычитаем точку привязки из смещения матрицы
if (animationData.pivot != null) {
objectData.matrix.appendTranslation(-animationData.pivot.x, -animationData.pivot.y, -animationData.pivot.z);
}
// Трансформируем вершины
objectData.matrix.transformVectors(mesh.vertices, mesh.vertices);
}
for (i = 0; i < mesh.numVertices*3; i++) {
mesh.vertices[i] *= units;
}
// Добавляем грани
length = objectData.faces.length;
for (i = 0; i < length; i++) {
var faceData:FaceData = objectData.faces[i];
j = i*3;
mesh.indices[j] = faceData.a;
mesh.indices[j + 1] = faceData.b;
mesh.indices[j + 2] = faceData.c;
}
// Добавляем поверхности
if (objectData.surfaces != null) {
for (var surfaceId:String in objectData.surfaces) {
var materialData:MaterialData = materialDatas[surfaceId];
if (materialData.diffuseMap != null) {
mesh.texture = bitmaps[materialData.name];
}
}
}
}
private function parse3DSChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Главный
case 0x4D4D:
parseMainChunk(dataIndex, dataLength);
break;
}
parse3DSChunk(index + chunkLength, length - chunkLength);
} else {
// Загрузка битмап
loadBitmaps();
}
}
private function parseMainChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Версия
case 0x0002:
parseVersion(dataIndex);
break;
// 3D-сцена
case 0x3D3D:
parse3DChunk(dataIndex, dataLength);
break;
// Анимация
case 0xB000:
parseAnimationChunk(dataIndex, dataLength);
break;
}
parseMainChunk(index + chunkLength, length - chunkLength);
}
}
private function parseVersion(index:uint):void {
data.position = index;
version = data.readUnsignedInt();
}
private function parse3DChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Материал
case 0xAFFF:
// Парсим материал
var material:MaterialData = new MaterialData();
parseMaterialChunk(material, dataIndex, dataLength);
break;
// Объект
case 0x4000:
// Создаём данные объекта
var object:ObjectData = new ObjectData();
var objectLength:uint = parseObject(object, dataIndex);
// Парсим объект
parseObjectChunk(object, dataIndex + objectLength, dataLength - objectLength);
break;
}
parse3DChunk(index + chunkLength, length - chunkLength);
}
}
private function parseMaterialChunk(material:MaterialData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Имя материала
case 0xA000:
parseMaterialName(material, dataIndex);
break;
// Ambient color
case 0xA010:
break;
// Diffuse color
case 0xA020:
data.position = dataIndex + 6;
material.color = (data.readUnsignedByte() << 16) + (data.readUnsignedByte() << 8) + data.readUnsignedByte();
break;
// Specular color
case 0xA030:
break;
// Shininess percent
case 0xA040:
data.position = dataIndex + 6;
material.glossiness = data.readUnsignedShort();
break;
// Shininess strength percent
case 0xA041:
data.position = dataIndex + 6;
material.specular = data.readUnsignedShort();
break;
// Transperensy
case 0xA050:
data.position = dataIndex + 6;
material.transparency = data.readUnsignedShort();
break;
// Texture map 1
case 0xA200:
material.diffuseMap = new MapData();
parseMapChunk(material.name, material.diffuseMap, dataIndex, dataLength);
break;
// Texture map 2
case 0xA33A:
break;
// Opacity map
case 0xA210:
material.opacityMap = new MapData();
parseMapChunk(material.name, material.opacityMap, dataIndex, dataLength);
break;
// Bump map
case 0xA230:
//material.normalMap = new MapData();
//parseMapChunk(material.normalMap, dataIndex, dataLength);
break;
// Shininess map
case 0xA33C:
break;
// Specular map
case 0xA204:
break;
// Self-illumination map
case 0xA33D:
break;
// Reflection map
case 0xA220:
break;
}
parseMaterialChunk(material, index + chunkLength, length - chunkLength);
}
}
private function parseMaterialName(material:MaterialData, index:uint):void {
// Создаём список материалов, если надо
if (materialDatas == null) {
materialDatas = new Array();
}
// Получаем название материала
material.name = getString(index);
// Помещаем данные материала в список
materialDatas[material.name] = material;
}
private function parseMapChunk(materialName:String, map:MapData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Имя файла
case 0xA300:
map.filename = getString(dataIndex).toLowerCase();
break;
// Масштаб по U
case 0xA354:
data.position = dataIndex;
map.scaleU = data.readFloat();
break;
// Масштаб по V
case 0xA356:
data.position = dataIndex;
map.scaleV = data.readFloat();
break;
// Смещение по U
case 0xA358:
data.position = dataIndex;
map.offsetU = data.readFloat();
break;
// Смещение по V
case 0xA35A:
data.position = dataIndex;
map.offsetV = data.readFloat();
break;
// Угол поворота
case 0xA35C:
data.position = dataIndex;
map.rotation = data.readFloat();
break;
}
parseMapChunk(materialName, map, index + chunkLength, length - chunkLength);
}
}
private function parseObject(object:ObjectData, index:uint):uint {
// Создаём список объектов, если надо
if (objectDatas == null) {
objectDatas = new Object();
}
// Получаем название объекта
object.name = getString(index);
// Помещаем данные объекта в список
objectDatas[object.name] = object;
return object.name.length + 1;
}
private function parseObjectChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Меш
case 0x4100:
parseMeshChunk(object, dataIndex, dataLength);
break;
// Источник света
case 0x4600:
break;
// Камера
case 0x4700:
break;
}
parseObjectChunk(object, index + chunkLength, length - chunkLength);
}
}
private function parseMeshChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Вершины
case 0x4110:
parseVertices(object, dataIndex);
break;
// UV
case 0x4140:
parseUVs(object, dataIndex);
break;
// Трансформация
case 0x4160:
parseMatrix(object, dataIndex);
break;
// Грани
case 0x4120:
var facesLength:uint = parseFaces(object, dataIndex);
parseFacesChunk(object, dataIndex + facesLength, dataLength - facesLength);
break;
}
parseMeshChunk(object, index + chunkLength, length - chunkLength);
}
}
private function parseVertices(object:ObjectData, index:uint):void {
data.position = index;
var num:uint = data.readUnsignedShort();
object.vertices = new Vector.<Vector3D>();
for (var i:uint = 0; i < num; i++) {
object.vertices.push(new Vector3D(data.readFloat(), data.readFloat(), data.readFloat()));
}
}
private function parseUVs(object:ObjectData, index:uint):void {
data.position = index;
var num:uint = data.readUnsignedShort();
object.uvs = new Vector.<Point>();
for (var i:uint = 0; i < num; i++) {
object.uvs.push(new Point(data.readFloat(), data.readFloat()));
}
}
private function parseMatrix(object:ObjectData, index:uint):void {
data.position = index;
object.matrix = new Matrix3D(Vector.<Number>([
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 1
]));
}
private function parseFaces(object:ObjectData, index:uint):uint {
data.position = index;
var num:uint = data.readUnsignedShort();
object.faces = new Array();
for (var i:uint = 0; i < num; i++) {
var face:FaceData = new FaceData();
face.a = data.readUnsignedShort();
face.b = data.readUnsignedShort();
face.c = data.readUnsignedShort();
object.faces.push(face);
data.position += 2; // Пропускаем флаг
}
return 2 + num*8;
}
private function parseFacesChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Поверхности
case 0x4130:
parseSurface(object, dataIndex);
break;
// Группы сглаживания
case 0x4150:
break;
}
parseFacesChunk(object, index + chunkLength, length - chunkLength);
}
}
private function parseSurface(object:ObjectData, index:uint):void {
// Создаём данные поверхности
var surface:SurfaceData = new SurfaceData();
// Создаём список поверхностей, если надо
if (object.surfaces == null) {
object.surfaces = new Object();
}
// Получаем название материала
surface.materialName = getString(index);
// Помещаем данные поверхности в список
object.surfaces[surface.materialName] = surface;
// Получаем грани поверхности
data.position = index + surface.materialName.length + 1;
var num:uint = data.readUnsignedShort();
surface.faces = new Array();
for (var i:uint = 0; i < num; i++) {
surface.faces.push(data.readUnsignedShort());
}
}
private function parseAnimationChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Анимация объекта
case 0xB001:
case 0xB002:
case 0xB003:
case 0xB004:
case 0xB005:
case 0xB006:
case 0xB007:
var animation:AnimationData = new AnimationData();
if (animationDatas == null) {
animationDatas = new Array();
}
animationDatas.push(animation);
parseObjectAnimationChunk(animation, dataIndex, dataLength);
break;
// Таймлайн
case 0xB008:
break;
}
parseAnimationChunk(index + chunkLength, length - chunkLength);
}
}
private function parseObjectAnimationChunk(animation:AnimationData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Идентификация объекта и его связь
case 0xB010:
parseObjectAnimationInfo(animation, dataIndex);
break;
// Точка привязки объекта (pivot)
case 0xB013:
parseObjectAnimationPivot(animation, dataIndex);
break;
// Смещение объекта относительно родителя
case 0xB020:
parseObjectAnimationPosition(animation, dataIndex);
break;
// Поворот объекта относительно родителя (angle-axis)
case 0xB021:
parseObjectAnimationRotation(animation, dataIndex);
break;
// Масштабирование объекта относительно родителя
case 0xB022:
parseObjectAnimationScale(animation, dataIndex);
break;
}
parseObjectAnimationChunk(animation, index + chunkLength, length - chunkLength);
}
}
private function parseObjectAnimationInfo(animation:AnimationData, index:uint):void {
var name:String = getString(index);
data.position = index + name.length + 1 + 4;
animation.objectName = name;
animation.parentIndex = data.readUnsignedShort();
}
private function parseObjectAnimationPivot(animation:AnimationData, index:uint):void {
data.position = index;
animation.pivot = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
private function parseObjectAnimationPosition(animation:AnimationData, index:uint):void {
data.position = index + 20;
animation.position = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
private function parseObjectAnimationRotation(animation:AnimationData, index:uint):void {
data.position = index + 20;
var angle:Number = data.readFloat();
animation.rotation = new Vector3D(-data.readFloat(), -data.readFloat(), -data.readFloat(), angle);
}
private function parseObjectAnimationScale(animation:AnimationData, index:uint):void {
data.position = index + 20;
animation.scale = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
/**
* Объект-контейнер, содержащий все загруженные объекты.
*/
public function get content():Vector.<Mesh> {
return _content;
}
// Считываем строку заканчивающуюся на нулевой байт
private function getString(index:uint):String {
data.position = index;
var charCode:uint = data.readByte();
var res:String = "";
while (charCode != 0) {
res += String.fromCharCode(charCode);
charCode = data.readByte();
}
return res;
}
private function getRotationFrom3DSAngleAxis(angle:Number, x:Number, z:Number, y:Number):Vector3D {
var res:Vector3D = new Vector3D();
var s:Number = Math.sin(angle);
var c:Number = Math.cos(angle);
var t:Number = 1 - c;
var k:Number = x*y*t + z*s;
var half:Number;
if (k > 0.998) {
half = angle/2;
res.z = -2*Math.atan2(x*Math.sin(half), Math.cos(half));
res.y = -Math.PI/2;
res.x = 0;
return res;
}
if (k < -0.998) {
half = angle/2;
res.z = 2*Math.atan2(x*Math.sin(half), Math.cos(half));
res.y = Math.PI/2;
res.x = 0;
return res;
}
res.z = -Math.atan2(y*s - x*z*t, 1 - (y*y + z*z)*t);
res.y = -Math.asin(x*y*t + z*s);
res.x = -Math.atan2(x*s - y*z*t, 1 - (x*x + z*z)*t);
return res;
}
}
}
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import __AS3__.vec.Vector;
import flash.geom.Point;
import alternativa.engine3d.objects.Mesh;
class MaterialData {
public var name:String;
public var color:uint;
public var specular:uint;
public var glossiness:uint;
public var transparency:uint;
public var diffuseMap:MapData;
public var opacityMap:MapData;
//public var normalMap:MapData;
public var matrix:Matrix;
}
class MapData {
public var filename:String;
public var scaleU:Number = 1;
public var scaleV:Number = 1;
public var offsetU:Number = 0;
public var offsetV:Number = 0;
public var rotation:Number = 0;
}
class ObjectData {
public var name:String;
public var vertices:Vector.<Vector3D>;
public var uvs:Vector.<Point>;
public var matrix:Matrix3D;
public var faces:Array;
public var surfaces:Object;
}
class FaceData {
public var a:uint;
public var b:uint;
public var c:uint;
}
class SurfaceData {
public var materialName:String;
public var faces:Array;
}
class AnimationData {
public var objectName:String;
public var object:Mesh;
public var parentIndex:uint;
public var pivot:Vector3D;
public var position:Vector3D;
public var rotation:Vector3D;
public var scale:Vector3D;
}

View File

@@ -0,0 +1,819 @@
package alternativa.engine3d.loaders {
import __AS3__.vec.Vector;
import alternativa.engine3d.alternativa3d;
import alternativa.engine3d.objects.Mesh;
import flash.display.BlendMode;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Orientation3D;
import flash.geom.Point;
import flash.geom.Vector3D;
import flash.net.URLLoader;
import flash.system.LoaderContext;
import flash.utils.ByteArray;
import flash.utils.Endian;
use namespace alternativa3d;
public class Loader3DSByteArray extends EventDispatcher {
private var _content:Vector.<Mesh>;
private var version:uint;
private var objectDatas:Object;
private var animationDatas:Array;
private var materialDatas:Array;
private var bitmaps:Array;
private var modelLoader:URLLoader;
private var textureLoader:TextureMapsLoader;
alternativa3d var data:ByteArray;
private var counter:int;
private var textureMaterialNames:Array;
private var context:LoaderContext;
private var path:String;
/**
* Повтор текстуры при заливке для создаваемых текстурных материалов.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var repeat:Boolean = true;
/**
* Сглаживание текстур при увеличении масштаба.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var smooth:Boolean = false;
/**
* Режим наложения цвета для создаваемых текстурных материалов.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var blendMode:String = BlendMode.NORMAL;
/**
* Коэффициент пересчёта единиц измерения модели.
*/
public var units:Number = 1;
/**
* Устанавливаемый уровень мобильности загруженных объектов.
*/
public var mobility:int = 0;
private function clean():void {
_content = null;
objectDatas = null;
animationDatas = null;
materialDatas = null;
bitmaps = null;
textureMaterialNames = null;
}
public function parseByteArray(data:ByteArray):void {
this.data = data;
this.data.endian = Endian.LITTLE_ENDIAN;
parse3DSChunk(0, this.data.bytesAvailable);
}
private function buildContent():void {
var i:uint;
var length:uint;
// Формируем связи объектов
_content = new Vector.<Mesh>();
// Создаём материалы
var materialData:MaterialData;
for (var materialName:String in materialDatas) {
materialData = materialDatas[materialName];
var mapData:MapData = materialData.diffuseMap;
var materialMatrix:Matrix = new Matrix();
if (mapData != null) {
var rot:Number = mapData.rotation*Math.PI/180;
var rotSin:Number = Math.sin(rot);
var rotCos:Number = Math.cos(rot);
materialMatrix.translate(-mapData.offsetU, mapData.offsetV);
materialMatrix.translate(-0.5, -0.5);
materialMatrix.rotate(-rot);
materialMatrix.scale(mapData.scaleU, mapData.scaleV);
materialMatrix.translate(0.5, 0.5);
}
materialData.matrix = materialMatrix;
}
// Если есть данные об анимации и иерархии объектов
var objectName:String;
var objectData:ObjectData;
var mesh:Mesh;
if (animationDatas != null) {
if (objectDatas != null) {
length = animationDatas.length;
for (i = 0; i < length; i++) {
var animationData:AnimationData = animationDatas[i];
objectName = animationData.objectName;
objectData = objectDatas[objectName];
// Если на один объект приходится несколько данных об анимации
if (objectData != null) {
var nameCounter:uint = 2;
for (var j:uint = i + 1; j < length; j++) {
var animationData2:AnimationData = animationDatas[j];
if (objectName == animationData2.objectName) {
var newName:String = objectName + nameCounter;
var newObjectData:ObjectData = new ObjectData();
animationData2.objectName = newName;
newObjectData.name = newName;
if (objectData.vertices != null) {
newObjectData.vertices = new Vector.<Vector3D>().concat(objectData.vertices);
}
if (objectData.uvs != null) {
newObjectData.uvs = new new Vector.<Point>().concat(objectData.uvs);
}
if (objectData.matrix != null) {
newObjectData.matrix = objectData.matrix.clone();
}
if (objectData.faces != null) {
newObjectData.faces = new Array().concat(objectData.faces);
}
if (objectData.surfaces != null) {
newObjectData.surfaces = objectData.surfaces.clone();
}
objectDatas[newName] = newObjectData;
nameCounter++;
}
}
}
if (objectData != null && objectData.vertices != null) {
// Меш
mesh = new Mesh();
mesh.createEmptyGeometry(objectData.vertices.length, objectData.faces.length);
animationData.object = mesh;
buildObject(animationData);
buildMesh(mesh, objectData, animationData);
_content.push(mesh);
}
}
}
} else {
for (objectName in objectDatas) {
objectData = objectDatas[objectName];
if (objectData.vertices != null) {
// Меш
mesh = new Mesh();
mesh.createEmptyGeometry(objectData.vertices.length, objectData.faces.length);
buildMesh(mesh, objectData, null);
_content.push(mesh);
}
}
}
// Рассылаем событие о завершении
dispatchEvent(new Event(Event.COMPLETE));
}
private function buildObject(animationData:AnimationData):void {
var object:Mesh = animationData.object;
var transform:Vector.<Vector3D> = new Vector.<Vector3D>(3, true);
transform[0] = (animationData.position == null) ? new Vector3D() : new Vector3D(animationData.position.x * units, animationData.position.y * units, animationData.position.z * units);
transform[1] = (animationData.rotation == null) ? new Vector3D() : animationData.rotation.clone();
transform[2] = (animationData.scale == null) ? new Vector3D(1, 1, 1) : animationData.scale.clone();
object.matrix.recompose(transform, Orientation3D.AXIS_ANGLE);
}
private function buildMesh(mesh:Mesh, objectData:ObjectData, animationData:AnimationData):void {
// Добавляем вершины
var i:uint;
var j:uint;
var k:uint;
var key:*;
var length:uint = objectData.vertices.length;
for (i = 0; i < length; i++) {
var vertexData:Vector3D = objectData.vertices[i];
var uv:Point = objectData.uvs[i];
j = i*3;
mesh.vertices[j] = vertexData.x;
mesh.vertices[j + 1] = vertexData.y;
mesh.vertices[j + 2] = vertexData.z;
mesh.uvts[j] = uv.x;
mesh.uvts[j + 1] = 1 - uv.y;
k = i << 1;
mesh.uvs[k] = uv.x;
mesh.uvs[k + 1] = 1 - uv.y;
}
// Коррекция вершин
if (animationData != null) {
// Инвертируем матрицу
objectData.matrix.invert();
// Вычитаем точку привязки из смещения матрицы
if (animationData.pivot != null) {
objectData.matrix.appendTranslation(-animationData.pivot.x, -animationData.pivot.y, -animationData.pivot.z);
}
// Трансформируем вершины
objectData.matrix.transformVectors(mesh.vertices, mesh.vertices);
}
for (i = 0; i < mesh.numVertices*3; i++) {
mesh.vertices[i] *= units;
}
// Добавляем грани
length = objectData.faces.length;
for (i = 0; i < length; i++) {
var faceData:FaceData = objectData.faces[i];
j = i*3;
mesh.indices[j] = faceData.a;
mesh.indices[j + 1] = faceData.b;
mesh.indices[j + 2] = faceData.c;
}
// Добавляем поверхности
/*if (objectData.surfaces != null) {
for (var surfaceId:String in objectData.surfaces) {
var materialData:MaterialData = materialDatas[surfaceId];
if (materialData.diffuseMap != null) {
mesh.texture = bitmaps[materialData.name];
}
}
}*/
}
alternativa3d function parse3DSChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Главный
case 0x4D4D:
parseMainChunk(dataIndex, dataLength);
break;
}
parse3DSChunk(index + chunkLength, length - chunkLength);
} else {
// Загрузка битмап
//loadBitmaps();
buildContent(); // Без подгрузки битмап
}
}
private function parseMainChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Версия
case 0x0002:
parseVersion(dataIndex);
break;
// 3D-сцена
case 0x3D3D:
parse3DChunk(dataIndex, dataLength);
break;
// Анимация
case 0xB000:
parseAnimationChunk(dataIndex, dataLength);
break;
}
parseMainChunk(index + chunkLength, length - chunkLength);
}
}
private function parseVersion(index:uint):void {
data.position = index;
version = data.readUnsignedInt();
}
private function parse3DChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Материал
case 0xAFFF:
// Парсим материал
var material:MaterialData = new MaterialData();
parseMaterialChunk(material, dataIndex, dataLength);
break;
// Объект
case 0x4000:
// Создаём данные объекта
var object:ObjectData = new ObjectData();
var objectLength:uint = parseObject(object, dataIndex);
// Парсим объект
parseObjectChunk(object, dataIndex + objectLength, dataLength - objectLength);
break;
}
parse3DChunk(index + chunkLength, length - chunkLength);
}
}
private function parseMaterialChunk(material:MaterialData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Имя материала
case 0xA000:
parseMaterialName(material, dataIndex);
break;
// Ambient color
case 0xA010:
break;
// Diffuse color
case 0xA020:
data.position = dataIndex + 6;
material.color = (data.readUnsignedByte() << 16) + (data.readUnsignedByte() << 8) + data.readUnsignedByte();
break;
// Specular color
case 0xA030:
break;
// Shininess percent
case 0xA040:
data.position = dataIndex + 6;
material.glossiness = data.readUnsignedShort();
break;
// Shininess strength percent
case 0xA041:
data.position = dataIndex + 6;
material.specular = data.readUnsignedShort();
break;
// Transperensy
case 0xA050:
data.position = dataIndex + 6;
material.transparency = data.readUnsignedShort();
break;
// Texture map 1
case 0xA200:
material.diffuseMap = new MapData();
parseMapChunk(material.name, material.diffuseMap, dataIndex, dataLength);
break;
// Texture map 2
case 0xA33A:
break;
// Opacity map
case 0xA210:
material.opacityMap = new MapData();
parseMapChunk(material.name, material.opacityMap, dataIndex, dataLength);
break;
// Bump map
case 0xA230:
//material.normalMap = new MapData();
//parseMapChunk(material.normalMap, dataIndex, dataLength);
break;
// Shininess map
case 0xA33C:
break;
// Specular map
case 0xA204:
break;
// Self-illumination map
case 0xA33D:
break;
// Reflection map
case 0xA220:
break;
}
parseMaterialChunk(material, index + chunkLength, length - chunkLength);
}
}
private function parseMaterialName(material:MaterialData, index:uint):void {
// Создаём список материалов, если надо
if (materialDatas == null) {
materialDatas = new Array();
}
// Получаем название материала
material.name = getString(index);
// Помещаем данные материала в список
materialDatas[material.name] = material;
}
private function parseMapChunk(materialName:String, map:MapData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Имя файла
case 0xA300:
map.filename = getString(dataIndex).toLowerCase();
break;
// Масштаб по U
case 0xA354:
data.position = dataIndex;
map.scaleU = data.readFloat();
break;
// Масштаб по V
case 0xA356:
data.position = dataIndex;
map.scaleV = data.readFloat();
break;
// Смещение по U
case 0xA358:
data.position = dataIndex;
map.offsetU = data.readFloat();
break;
// Смещение по V
case 0xA35A:
data.position = dataIndex;
map.offsetV = data.readFloat();
break;
// Угол поворота
case 0xA35C:
data.position = dataIndex;
map.rotation = data.readFloat();
break;
}
parseMapChunk(materialName, map, index + chunkLength, length - chunkLength);
}
}
private function parseObject(object:ObjectData, index:uint):uint {
// Создаём список объектов, если надо
if (objectDatas == null) {
objectDatas = new Object();
}
// Получаем название объекта
object.name = getString(index);
// Помещаем данные объекта в список
objectDatas[object.name] = object;
return object.name.length + 1;
}
private function parseObjectChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Меш
case 0x4100:
parseMeshChunk(object, dataIndex, dataLength);
break;
// Источник света
case 0x4600:
break;
// Камера
case 0x4700:
break;
}
parseObjectChunk(object, index + chunkLength, length - chunkLength);
}
}
private function parseMeshChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Вершины
case 0x4110:
parseVertices(object, dataIndex);
break;
// UV
case 0x4140:
parseUVs(object, dataIndex);
break;
// Трансформация
case 0x4160:
parseMatrix(object, dataIndex);
break;
// Грани
case 0x4120:
var facesLength:uint = parseFaces(object, dataIndex);
parseFacesChunk(object, dataIndex + facesLength, dataLength - facesLength);
break;
}
parseMeshChunk(object, index + chunkLength, length - chunkLength);
}
}
private function parseVertices(object:ObjectData, index:uint):void {
data.position = index;
var num:uint = data.readUnsignedShort();
object.vertices = new Vector.<Vector3D>();
for (var i:uint = 0; i < num; i++) {
object.vertices.push(new Vector3D(data.readFloat(), data.readFloat(), data.readFloat()));
}
}
private function parseUVs(object:ObjectData, index:uint):void {
data.position = index;
var num:uint = data.readUnsignedShort();
object.uvs = new Vector.<Point>();
for (var i:uint = 0; i < num; i++) {
object.uvs.push(new Point(data.readFloat(), data.readFloat()));
}
}
private function parseMatrix(object:ObjectData, index:uint):void {
data.position = index;
object.matrix = new Matrix3D(Vector.<Number>([
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 1
]));
}
private function parseFaces(object:ObjectData, index:uint):uint {
data.position = index;
var num:uint = data.readUnsignedShort();
object.faces = new Array();
for (var i:uint = 0; i < num; i++) {
var face:FaceData = new FaceData();
face.a = data.readUnsignedShort();
face.b = data.readUnsignedShort();
face.c = data.readUnsignedShort();
object.faces.push(face);
data.position += 2; // Пропускаем флаг
}
return 2 + num*8;
}
private function parseFacesChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Поверхности
case 0x4130:
parseSurface(object, dataIndex);
break;
// Группы сглаживания
case 0x4150:
break;
}
parseFacesChunk(object, index + chunkLength, length - chunkLength);
}
}
private function parseSurface(object:ObjectData, index:uint):void {
// Создаём данные поверхности
var surface:SurfaceData = new SurfaceData();
// Создаём список поверхностей, если надо
if (object.surfaces == null) {
object.surfaces = new Object();
}
// Получаем название материала
surface.materialName = getString(index);
// Помещаем данные поверхности в список
object.surfaces[surface.materialName] = surface;
// Получаем грани поверхности
data.position = index + surface.materialName.length + 1;
var num:uint = data.readUnsignedShort();
surface.faces = new Array();
for (var i:uint = 0; i < num; i++) {
surface.faces.push(data.readUnsignedShort());
}
}
private function parseAnimationChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Анимация объекта
case 0xB001:
case 0xB002:
case 0xB003:
case 0xB004:
case 0xB005:
case 0xB006:
case 0xB007:
var animation:AnimationData = new AnimationData();
if (animationDatas == null) {
animationDatas = new Array();
}
animationDatas.push(animation);
parseObjectAnimationChunk(animation, dataIndex, dataLength);
break;
// Таймлайн
case 0xB008:
break;
}
parseAnimationChunk(index + chunkLength, length - chunkLength);
}
}
private function parseObjectAnimationChunk(animation:AnimationData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Идентификация объекта и его связь
case 0xB010:
parseObjectAnimationInfo(animation, dataIndex);
break;
// Точка привязки объекта (pivot)
case 0xB013:
parseObjectAnimationPivot(animation, dataIndex);
break;
// Смещение объекта относительно родителя
case 0xB020:
parseObjectAnimationPosition(animation, dataIndex);
break;
// Поворот объекта относительно родителя (angle-axis)
case 0xB021:
parseObjectAnimationRotation(animation, dataIndex);
break;
// Масштабирование объекта относительно родителя
case 0xB022:
parseObjectAnimationScale(animation, dataIndex);
break;
}
parseObjectAnimationChunk(animation, index + chunkLength, length - chunkLength);
}
}
private function parseObjectAnimationInfo(animation:AnimationData, index:uint):void {
var name:String = getString(index);
data.position = index + name.length + 1 + 4;
animation.objectName = name;
animation.parentIndex = data.readUnsignedShort();
}
private function parseObjectAnimationPivot(animation:AnimationData, index:uint):void {
data.position = index;
animation.pivot = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
private function parseObjectAnimationPosition(animation:AnimationData, index:uint):void {
data.position = index + 20;
animation.position = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
private function parseObjectAnimationRotation(animation:AnimationData, index:uint):void {
data.position = index + 20;
var angle:Number = data.readFloat();
animation.rotation = new Vector3D(data.readFloat(), -data.readFloat(), data.readFloat(), angle);
}
private function parseObjectAnimationScale(animation:AnimationData, index:uint):void {
data.position = index + 20;
animation.scale = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
/**
* Объект-контейнер, содержащий все загруженные объекты.
*/
public function get content():Vector.<Mesh> {
return _content;
}
// Считываем строку заканчивающуюся на нулевой байт
private function getString(index:uint):String {
data.position = index;
var charCode:uint = data.readByte();
var res:String = "";
while (charCode != 0) {
res += String.fromCharCode(charCode);
charCode = data.readByte();
}
return res;
}
private function getRotationFrom3DSAngleAxis(angle:Number, x:Number, z:Number, y:Number):Vector3D {
var res:Vector3D = new Vector3D();
var s:Number = Math.sin(angle);
var c:Number = Math.cos(angle);
var t:Number = 1 - c;
var k:Number = x*y*t + z*s;
var half:Number;
if (k > 0.998) {
half = angle/2;
res.z = -2*Math.atan2(x*Math.sin(half), Math.cos(half));
res.y = -Math.PI/2;
res.x = 0;
return res;
}
if (k < -0.998) {
half = angle/2;
res.z = 2*Math.atan2(x*Math.sin(half), Math.cos(half));
res.y = Math.PI/2;
res.x = 0;
return res;
}
res.z = -Math.atan2(y*s - x*z*t, 1 - (y*y + z*z)*t);
res.y = -Math.asin(x*y*t + z*s);
res.x = -Math.atan2(x*s - y*z*t, 1 - (x*x + z*z)*t);
return res;
}
}
}
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import __AS3__.vec.Vector;
import flash.geom.Point;
import alternativa.engine3d.objects.Mesh;
class MaterialData {
public var name:String;
public var color:uint;
public var specular:uint;
public var glossiness:uint;
public var transparency:uint;
public var diffuseMap:MapData;
public var opacityMap:MapData;
//public var normalMap:MapData;
public var matrix:Matrix;
}
class MapData {
public var filename:String;
public var scaleU:Number = 1;
public var scaleV:Number = 1;
public var offsetU:Number = 0;
public var offsetV:Number = 0;
public var rotation:Number = 0;
}
class ObjectData {
public var name:String;
public var vertices:Vector.<Vector3D>;
public var uvs:Vector.<Point>;
public var matrix:Matrix3D;
public var faces:Array;
public var surfaces:Object;
}
class FaceData {
public var a:uint;
public var b:uint;
public var c:uint;
}
class SurfaceData {
public var materialName:String;
public var faces:Array;
}
class AnimationData {
public var objectName:String;
public var object:Mesh;
public var parentIndex:uint;
public var pivot:Vector3D;
public var position:Vector3D;
public var rotation:Vector3D;
public var scale:Vector3D;
}

View File

@@ -0,0 +1,15 @@
package alternativa.engine3d.loaders {
public class MaterialParams {
public var color:uint;
public var opacity:Number;
public var diffuseMap:String;
public var opacityMap:String;
public function toString():String {
return "[MaterialParams color=" + color + ", opacity=" + opacity + ", diffuseMap=" + diffuseMap + ", opacityMap=" + opacityMap + "]";
}
}
}

View File

@@ -0,0 +1,22 @@
package alternativa.engine3d.loaders {
import __AS3__.vec.Vector;
import alternativa.engine3d.core.Object3D;
public class Parsed3DSData {
/**
* Список объектов в порядке их появления в 3DS-данных.
**/
public var objects:Vector.<Object3D>;
/**
* Список материалов каждого объекта. Если для объекта нет назначенных материалов, соответствующий элемент списка равен null.
**/
public var objectMaterials:Vector.<Vector.<String>>;
/**
* Список материалов 3DS-файла (materialName => MaterialParams).
*/
public var materials:Object;
}
}

View File

@@ -0,0 +1,977 @@
package alternativa.engine3d.loaders {
import __AS3__.vec.Vector;
import alternativa.engine3d.core.Object3D;
import alternativa.engine3d.objects.Mesh;
import flash.display.BlendMode;
import flash.events.EventDispatcher;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Orientation3D;
import flash.geom.Point;
import flash.geom.Vector3D;
import flash.net.URLLoader;
import flash.utils.ByteArray;
import flash.utils.Endian;
/**
*
*/
public class Parser3DS extends EventDispatcher {
private var version:uint;
private var objectDatas:Object;
private var animationDatas:Vector.<AnimationData>;
private var materialDatas:Object;
private var modelLoader:URLLoader;
private var data:ByteArray;
/**
* Повтор текстуры при заливке для создаваемых текстурных материалов.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var repeat:Boolean = true;
/**
* Сглаживание текстур при увеличении масштаба.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var smooth:Boolean = false;
/**
* Режим наложения цвета для создаваемых текстурных материалов.
*
* @see alternativa.engine3d.materials.TextureMaterial
*/
public var blendMode:String = BlendMode.NORMAL;
/**
* Коэффициент пересчёта единиц измерения модели.
*/
public var units:Number = 1;
/**
*
* @param data
*/
public function Parser3DS() {
}
/**
*
* @param data
*/
public function parse(data:ByteArray):Parsed3DSData {
this.data = data;
data.endian = Endian.LITTLE_ENDIAN;
parse3DSChunk(0, data.bytesAvailable);
return buildContent();
}
/**
*
*/
private function clean():void {
objectDatas = null;
animationDatas = null;
materialDatas = null;
}
/**
*
*/
private function buildContent():Parsed3DSData {
var result:Parsed3DSData = new Parsed3DSData();
var i:uint;
var length:uint;
// Формируем связи объектов
result.objects = new Vector.<Object3D>();
result.objectMaterials = new Vector.<Vector.<String>>();
result.materials = {};
// Создаём материалы
var materialData:MaterialData;
for (var materialName:String in materialDatas) {
materialData = materialDatas[materialName];
var mapData:MapData = materialData.diffuseMap;
var materialMatrix:Matrix = new Matrix();
if (mapData != null) {
var rot:Number = mapData.rotation*Math.PI/180;
var rotSin:Number = Math.sin(rot);
var rotCos:Number = Math.cos(rot);
materialMatrix.translate(-mapData.offsetU, mapData.offsetV);
materialMatrix.translate(-0.5, -0.5);
materialMatrix.rotate(-rot);
materialMatrix.scale(mapData.scaleU, mapData.scaleV);
materialMatrix.translate(0.5, 0.5);
}
materialData.matrix = materialMatrix;
var mat:MaterialParams = new MaterialParams();
mat.color = materialData.color;
mat.opacity = 1 - 0.01*materialData.transparency;
if (materialData.diffuseMap != null) {
mat.diffuseMap = materialData.diffuseMap.filename;
}
if (materialData.opacityMap != null) {
mat.opacityMap = materialData.opacityMap.filename;
}
result.materials[materialName] = mat;
}
// Если есть данные об анимации и иерархии объектов
var objectName:String;
var objectData:ObjectData;
var mesh:Mesh;
if (animationDatas != null) {
if (objectDatas != null) {
length = animationDatas.length;
for (i = 0; i < length; i++) {
var animationData:AnimationData = animationDatas[i];
objectName = animationData.objectName;
objectData = objectDatas[objectName];
// Если на один объект приходится несколько данных об анимации
if (objectData != null) {
var nameCounter:uint = 2;
for (var j:uint = i + 1; j < length; j++) {
var animationData2:AnimationData = animationDatas[j];
if (objectName == animationData2.objectName) {
var newName:String = objectName + nameCounter;
var newObjectData:ObjectData = new ObjectData();
animationData2.objectName = newName;
newObjectData.name = newName;
if (objectData.vertices != null) {
newObjectData.vertices = new Vector.<Vector3D>().concat(objectData.vertices);
}
if (objectData.uvs != null) {
newObjectData.uvs = new Vector.<Point>().concat(objectData.uvs);
}
if (objectData.matrix != null) {
newObjectData.matrix = objectData.matrix.clone();
}
if (objectData.faces != null) {
newObjectData.faces = new Array().concat(objectData.faces);
}
if (objectData.surfaces != null) {
newObjectData.surfaces = objectData.surfaces.clone();
}
objectDatas[newName] = newObjectData;
nameCounter++;
}
}
}
if (objectData != null && objectData.vertices != null) {
// Меш
mesh = new Mesh();
mesh.createEmptyGeometry(objectData.vertices.length, objectData.faces.length);
animationData.object = mesh;
buildObject(animationData);
buildMesh(mesh, objectData, animationData, result);
}
}
}
} else {
for (objectName in objectDatas) {
objectData = objectDatas[objectName];
if (objectData.vertices != null) {
// Меш
mesh = new Mesh();
mesh.createEmptyGeometry(objectData.vertices.length, objectData.faces.length);
buildMesh(mesh, objectData, null, result);
}
}
}
clean();
return result;
}
/**
*
* @param animationData
*/
private function buildObject(animationData:AnimationData):void {
var object:Mesh = animationData.object;
var transform:Vector.<Vector3D> = new Vector.<Vector3D>(3, true);
transform[0] = (animationData.position == null) ? new Vector3D() : new Vector3D(animationData.position.x*units, animationData.position.y*units, animationData.position.z*units);
transform[1] = (animationData.rotation == null) ? new Vector3D() : animationData.rotation.clone();
transform[2] = (animationData.scale == null) ? new Vector3D(1, 1, 1) : animationData.scale.clone();
// trace("transform[2]", transform[2]);
object.matrix.recompose(transform, Orientation3D.AXIS_ANGLE);
}
/**
*
* @param mesh
* @param objectData
* @param animationData
*/
private function buildMesh(mesh:Mesh, objectData:ObjectData, animationData:AnimationData, parsedData:Parsed3DSData):void {
mesh.name = objectData.name;
// Добавляем вершины
var i:uint;
var j:uint;
var k:uint;
var key:*;
var length:uint = objectData.vertices.length;
for (i = 0; i < length; i++) {
var vertexData:Vector3D = objectData.vertices[i];
var uv:Point = objectData.uvs[i];
j = i*3;
mesh.vertices[j] = vertexData.x;
mesh.vertices[j + 1] = vertexData.y;
mesh.vertices[j + 2] = vertexData.z;
mesh.uvts[j] = uv.x;
mesh.uvts[j + 1] = 1 - uv.y;
k = i << 1;
mesh.uvs[k] = uv.x;
mesh.uvs[k + 1] = 1 - uv.y;
}
// Коррекция вершин
if (animationData != null) {
// Инвертируем матрицу
objectData.matrix.invert();
// Вычитаем точку привязки из смещения матрицы
if (animationData.pivot != null) {
objectData.matrix.appendTranslation(-animationData.pivot.x, -animationData.pivot.y, -animationData.pivot.z);
}
// Трансформируем вершины
objectData.matrix.transformVectors(mesh.vertices, mesh.vertices);
}
for (i = 0; i < mesh.numVertices*3; i++) {
mesh.vertices[i] *= units;
}
// Добавляем грани
length = objectData.faces.length;
for (i = 0; i < length; i++) {
var faceData:FaceData = objectData.faces[i];
j = i*3;
mesh.indices[j] = faceData.a;
mesh.indices[j + 1] = faceData.b;
mesh.indices[j + 2] = faceData.c;
}
parsedData.objects.push(mesh);
// Добавляем поверхности
if (objectData.surfaces != null) {
var meshMaterials:Vector.<String> = new Vector.<String>();
for (var surfaceId:String in objectData.surfaces) {
meshMaterials.push(surfaceId);
// var materialData:MaterialData = materialDatas[surfaceId];
// if (materialData.diffuseMap != null) {
// mesh.texture = bitmaps[materialData.name];
// }
}
parsedData.objectMaterials.push(meshMaterials);
} else {
parsedData.objectMaterials.push(null);
}
// trace("mesh.matrix.decompose()", mesh.matrix.decompose());
}
/**
*
* @param index
* @param length
*/
private function parse3DSChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Главный
case 0x4D4D:
parseMainChunk(dataIndex, dataLength);
break;
}
parse3DSChunk(index + chunkLength, length - chunkLength);
}
}
/**
*
* @param index
* @param length
*/
private function parseMainChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Версия
case 0x0002:
parseVersion(dataIndex);
break;
// 3D-сцена
case 0x3D3D:
parse3DChunk(dataIndex, dataLength);
break;
// Анимация
case 0xB000:
parseAnimationChunk(dataIndex, dataLength);
break;
}
parseMainChunk(index + chunkLength, length - chunkLength);
}
}
/**
*
* @param index
*/
private function parseVersion(index:uint):void {
data.position = index;
version = data.readUnsignedInt();
}
/**
*
* @param index
* @param length
*/
private function parse3DChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Материал
case 0xAFFF:
// Парсим материал
var material:MaterialData = new MaterialData();
parseMaterialChunk(material, dataIndex, dataLength);
break;
// Объект
case 0x4000:
// Создаём данные объекта
var object:ObjectData = new ObjectData();
var objectLength:uint = parseObject(object, dataIndex);
// Парсим объект
parseObjectChunk(object, dataIndex + objectLength, dataLength - objectLength);
break;
}
parse3DChunk(index + chunkLength, length - chunkLength);
}
}
/**
*
* @param material
* @param index
* @param length
*/
private function parseMaterialChunk(material:MaterialData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Имя материала
case 0xA000:
parseMaterialName(material, dataIndex);
break;
// Ambient color
case 0xA010:
break;
// Diffuse color
case 0xA020:
data.position = dataIndex + 6;
material.color = (data.readUnsignedByte() << 16) + (data.readUnsignedByte() << 8) + data.readUnsignedByte();
break;
// Specular color
case 0xA030:
break;
// Shininess percent
case 0xA040:
data.position = dataIndex + 6;
material.glossiness = data.readUnsignedShort();
break;
// Shininess strength percent
case 0xA041:
data.position = dataIndex + 6;
material.specular = data.readUnsignedShort();
break;
// Transperensy
case 0xA050:
data.position = dataIndex + 6;
material.transparency = data.readUnsignedShort();
break;
// Texture map 1
case 0xA200:
material.diffuseMap = new MapData();
parseMapChunk(material.name, material.diffuseMap, dataIndex, dataLength);
break;
// Texture map 2
case 0xA33A:
break;
// Opacity map
case 0xA210:
material.opacityMap = new MapData();
parseMapChunk(material.name, material.opacityMap, dataIndex, dataLength);
break;
// Bump map
case 0xA230:
//material.normalMap = new MapData();
//parseMapChunk(material.normalMap, dataIndex, dataLength);
break;
// Shininess map
case 0xA33C:
break;
// Specular map
case 0xA204:
break;
// Self-illumination map
case 0xA33D:
break;
// Reflection map
case 0xA220:
break;
}
parseMaterialChunk(material, index + chunkLength, length - chunkLength);
}
}
/**
*
* @param material
* @param index
*/
private function parseMaterialName(material:MaterialData, index:uint):void {
// Создаём список материалов, если надо
if (materialDatas == null) {
materialDatas = {};
}
// Получаем название материала
material.name = getString(index);
// Помещаем данные материала в список
materialDatas[material.name] = material;
}
/**
*
* @param materialName
* @param map
* @param index
* @param length
*/
private function parseMapChunk(materialName:String, map:MapData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Имя файла
case 0xA300:
map.filename = getString(dataIndex).toLowerCase();
break;
// Масштаб по U
case 0xA354:
data.position = dataIndex;
map.scaleU = data.readFloat();
break;
// Масштаб по V
case 0xA356:
data.position = dataIndex;
map.scaleV = data.readFloat();
break;
// Смещение по U
case 0xA358:
data.position = dataIndex;
map.offsetU = data.readFloat();
break;
// Смещение по V
case 0xA35A:
data.position = dataIndex;
map.offsetV = data.readFloat();
break;
// Угол поворота
case 0xA35C:
data.position = dataIndex;
map.rotation = data.readFloat();
break;
}
parseMapChunk(materialName, map, index + chunkLength, length - chunkLength);
}
}
/**
*
* @param object
* @param index
* @return
*/
private function parseObject(object:ObjectData, index:uint):uint {
// Создаём список объектов, если надо
if (objectDatas == null) {
objectDatas = new Object();
}
// Получаем название объекта
object.name = getString(index);
// Помещаем данные объекта в список
objectDatas[object.name] = object;
return object.name.length + 1;
}
/**
*
* @param object
* @param index
* @param length
*/
private function parseObjectChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Меш
case 0x4100:
parseMeshChunk(object, dataIndex, dataLength);
break;
// Источник света
case 0x4600:
break;
// Камера
case 0x4700:
break;
}
parseObjectChunk(object, index + chunkLength, length - chunkLength);
}
}
/**
*
* @param object
* @param index
* @param length
*/
private function parseMeshChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Вершины
case 0x4110:
parseVertices(object, dataIndex);
break;
// UV
case 0x4140:
parseUVs(object, dataIndex);
break;
// Трансформация
case 0x4160:
parseMatrix(object, dataIndex);
break;
// Грани
case 0x4120:
var facesLength:uint = parseFaces(object, dataIndex);
parseFacesChunk(object, dataIndex + facesLength, dataLength - facesLength);
break;
}
parseMeshChunk(object, index + chunkLength, length - chunkLength);
}
}
/**
*
* @param object
* @param index
*/
private function parseVertices(object:ObjectData, index:uint):void {
data.position = index;
var num:uint = data.readUnsignedShort();
object.vertices = new Vector.<Vector3D>();
for (var i:uint = 0; i < num; i++) {
object.vertices.push(new Vector3D(data.readFloat(), data.readFloat(), data.readFloat()));
}
}
/**
*
* @param object
* @param index
*/
private function parseUVs(object:ObjectData, index:uint):void {
data.position = index;
var num:uint = data.readUnsignedShort();
object.uvs = new Vector.<Point>();
for (var i:uint = 0; i < num; i++) {
object.uvs.push(new Point(data.readFloat(), data.readFloat()));
}
}
/**
*
* @param object
* @param index
*/
private function parseMatrix(object:ObjectData, index:uint):void {
data.position = index;
object.matrix = new Matrix3D(Vector.<Number>([
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 0,
data.readFloat(), data.readFloat(), data.readFloat(), 1
]));
}
/**
*
* @param object
* @param index
* @return
*/
private function parseFaces(object:ObjectData, index:uint):uint {
data.position = index;
var num:uint = data.readUnsignedShort();
object.faces = new Array();
for (var i:uint = 0; i < num; i++) {
var face:FaceData = new FaceData();
face.a = data.readUnsignedShort();
face.b = data.readUnsignedShort();
face.c = data.readUnsignedShort();
object.faces.push(face);
data.position += 2; // Пропускаем флаг
}
return 2 + num*8;
}
/**
*
* @param object
* @param index
* @param length
*/
private function parseFacesChunk(object:ObjectData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Поверхности
case 0x4130:
parseSurface(object, dataIndex);
break;
// Группы сглаживания
case 0x4150:
break;
}
parseFacesChunk(object, index + chunkLength, length - chunkLength);
}
}
/**
*
* @param object
* @param index
*/
private function parseSurface(object:ObjectData, index:uint):void {
// Создаём данные поверхности
var surface:SurfaceData = new SurfaceData();
// Создаём список поверхностей, если надо
if (object.surfaces == null) {
object.surfaces = new Object();
}
// Получаем название материала
surface.materialName = getString(index);
// Помещаем данные поверхности в список
object.surfaces[surface.materialName] = surface;
// Получаем грани поверхности
data.position = index + surface.materialName.length + 1;
var num:uint = data.readUnsignedShort();
surface.faces = new Array();
for (var i:uint = 0; i < num; i++) {
surface.faces.push(data.readUnsignedShort());
}
}
/**
*
* @param index
* @param length
*/
private function parseAnimationChunk(index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Анимация объекта
case 0xB001:
case 0xB002:
case 0xB003:
case 0xB004:
case 0xB005:
case 0xB006:
case 0xB007:
var animation:AnimationData = new AnimationData();
if (animationDatas == null) {
animationDatas = new Vector.<AnimationData>();
}
animationDatas.push(animation);
parseObjectAnimationChunk(animation, dataIndex, dataLength);
break;
// Таймлайн
case 0xB008:
break;
}
parseAnimationChunk(index + chunkLength, length - chunkLength);
}
}
/**
*
* @param animation
* @param index
* @param length
*/
private function parseObjectAnimationChunk(animation:AnimationData, index:uint, length:uint):void {
if (length > 6) {
data.position = index;
var chunkId:uint = data.readUnsignedShort();
var chunkLength:uint = data.readUnsignedInt();
var dataIndex:uint = index + 6;
var dataLength:uint = chunkLength - 6;
switch (chunkId) {
// Идентификация объекта и его связь
case 0xB010:
parseObjectAnimationInfo(animation, dataIndex);
break;
// Точка привязки объекта (pivot)
case 0xB013:
parseObjectAnimationPivot(animation, dataIndex);
break;
// Смещение объекта относительно родителя
case 0xB020:
parseObjectAnimationPosition(animation, dataIndex);
break;
// Поворот объекта относительно родителя (angle-axis)
case 0xB021:
parseObjectAnimationRotation(animation, dataIndex);
break;
// Масштабирование объекта относительно родителя
case 0xB022:
parseObjectAnimationScale(animation, dataIndex);
break;
}
parseObjectAnimationChunk(animation, index + chunkLength, length - chunkLength);
}
}
/**
*
* @param animation
* @param index
*/
private function parseObjectAnimationInfo(animation:AnimationData, index:uint):void {
var name:String = getString(index);
data.position = index + name.length + 1 + 4;
animation.objectName = name;
animation.parentIndex = data.readUnsignedShort();
}
/**
*
* @param animation
* @param index
*/
private function parseObjectAnimationPivot(animation:AnimationData, index:uint):void {
data.position = index;
animation.pivot = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
/**
*
* @param animation
* @param index
*/
private function parseObjectAnimationPosition(animation:AnimationData, index:uint):void {
data.position = index + 20;
animation.position = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
/**
*
* @param animation
* @param index
*/
private function parseObjectAnimationRotation(animation:AnimationData, index:uint):void {
data.position = index + 20;
var angle:Number = data.readFloat();
animation.rotation = new Vector3D(-data.readFloat(), -data.readFloat(), -data.readFloat(), angle);
}
/**
*
* @param animation
* @param index
*/
private function parseObjectAnimationScale(animation:AnimationData, index:uint):void {
data.position = index + 20;
animation.scale = new Vector3D(data.readFloat(), data.readFloat(), data.readFloat());
}
/**
* Считывает строку, заканчивающуюся на нулевой байт.
*
* @param index
* @return
*/
private function getString(index:uint):String {
data.position = index;
var charCode:uint = data.readByte();
var res:String = "";
while (charCode != 0) {
res += String.fromCharCode(charCode);
charCode = data.readByte();
}
return res;
}
/**
*
* @param angle
* @param x
* @param z
* @param y
* @return
*/
private function getRotationFrom3DSAngleAxis(angle:Number, x:Number, z:Number, y:Number):Vector3D {
var res:Vector3D = new Vector3D();
var s:Number = Math.sin(angle);
var c:Number = Math.cos(angle);
var t:Number = 1 - c;
var k:Number = x*y*t + z*s;
var half:Number;
if (k >= 1) {
half = 0.5*angle;
res.z = -2*Math.atan2(x*Math.sin(half), Math.cos(half));
res.y = -0.5*Math.PI;
res.x = 0;
return res;
}
if (k <= -1) {
half = 0.5*angle;
res.z = 2*Math.atan2(x*Math.sin(half), Math.cos(half));
res.y = 0.5*Math.PI;
res.x = 0;
return res;
}
res.z = -Math.atan2(y*s - x*z*t, 1 - (y*y + z*z)*t);
res.y = -Math.asin(k);
res.x = -Math.atan2(x*s - y*z*t, 1 - (x*x + z*z)*t);
return res;
}
}
}
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import __AS3__.vec.Vector;
import flash.geom.Point;
import alternativa.engine3d.objects.Mesh;
class MaterialData {
public var name:String;
public var color:uint;
public var specular:uint;
public var glossiness:uint;
public var transparency:uint;
public var diffuseMap:MapData;
public var opacityMap:MapData;
//public var normalMap:MapData;
public var matrix:Matrix;
}
class MapData {
public var filename:String;
public var scaleU:Number = 1;
public var scaleV:Number = 1;
public var offsetU:Number = 0;
public var offsetV:Number = 0;
public var rotation:Number = 0;
}
class ObjectData {
public var name:String;
public var vertices:Vector.<Vector3D>;
public var uvs:Vector.<Point>;
public var matrix:Matrix3D;
public var faces:Array;
public var surfaces:Object;
}
class FaceData {
public var a:uint;
public var b:uint;
public var c:uint;
}
class SurfaceData {
public var materialName:String;
public var faces:Array;
}
class AnimationData {
public var objectName:String;
public var object:Mesh;
public var parentIndex:uint;
public var pivot:Vector3D;
public var position:Vector3D;
public var rotation:Vector3D;
public var scale:Vector3D;
}

View File

@@ -0,0 +1,13 @@
package alternativa.engine3d.loaders {
public class TextureFilesData {
public var diffuseMap:String;
public var opacityMap:String;
public function TextureFilesData(diffuseMap:String, opacityMap:String) {
this.diffuseMap = diffuseMap;
this.opacityMap = opacityMap;
}
}
}

Some files were not shown because too many files have changed in this diff Show More