Apple2Mac first cut and refactor common rendering code

* Based on NSOpenGLView and Apple's GLEssentials sample code
    * CVDisplayLink- or NSTimer-driven rendering
    * Works in window or fullscreen mode on Mac OSX Lion or later

TODO FIXME:
    * Breaks Linux/Posix build
    * Cocoa menu interfaces
    * Key/mouse/joystick/gamepad handling
This commit is contained in:
Aaron Culliney 2014-09-27 11:03:51 -07:00
parent f794098a02
commit 6858e51a75
34 changed files with 3817 additions and 1099 deletions

View File

@ -11,8 +11,6 @@
773B3D1A1956885A0085CE5F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 773B3D181956885A0085CE5F /* InfoPlist.strings */; };
773B3D1C1956885A0085CE5F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D1B1956885A0085CE5F /* main.m */; };
773B3D201956885A0085CE5F /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 773B3D1E1956885A0085CE5F /* Credits.rtf */; };
773B3D231956885A0085CE5F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D221956885A0085CE5F /* AppDelegate.m */; };
773B3D261956885A0085CE5F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 773B3D241956885A0085CE5F /* MainMenu.xib */; };
773B3D281956885A0085CE5F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 773B3D271956885A0085CE5F /* Images.xcassets */; };
773B3DA019568A570085CE5F /* cpu-supp.c in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D5D19568A570085CE5F /* cpu-supp.c */; };
773B3DA219568A570085CE5F /* darwin-shim.c in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D6019568A570085CE5F /* darwin-shim.c */; };
@ -32,7 +30,6 @@
773B3DC019568A570085CE5F /* darwin-glue.S in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D9119568A570085CE5F /* darwin-glue.S */; };
773B3DC319568A570085CE5F /* zlib-helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D9519568A570085CE5F /* zlib-helpers.c */; };
773B3DCB1956903D0085CE5F /* libz.1.1.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 773B3DCA1956903D0085CE5F /* libz.1.1.3.dylib */; };
773B3DD3195697290085CE5F /* EmulatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 773B3DD2195697290085CE5F /* EmulatorView.m */; };
779DD827195764E200DF89E5 /* rom-shim.c in Sources */ = {isa = PBXBuildFile; fileRef = 779DD826195764E200DF89E5 /* rom-shim.c */; };
779DD82F195BD9F900DF89E5 /* cpu.S in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D9019568A570085CE5F /* cpu.S */; };
779DD830195BD9F900DF89E5 /* prefs.c in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D7719568A570085CE5F /* prefs.c */; };
@ -62,6 +59,18 @@
779DD852195BDA3000DF89E5 /* testcpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D7E19568A570085CE5F /* testcpu.c */; };
779DD853195BDA3400DF89E5 /* testcommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 773B3D7C19568A570085CE5F /* testcommon.c */; };
779DD856195BDB1700DF89E5 /* CPUTestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 779DD854195BDB1700DF89E5 /* CPUTestAppDelegate.m */; };
779F561C19D7929100A6F107 /* glvideo.c in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0C719D736EB004344E0 /* glvideo.c */; };
779F562119DA584800A6F107 /* Basic.vert in Resources */ = {isa = PBXBuildFile; fileRef = 779F561D19D79AC000A6F107 /* Basic.vert */; };
779F562219DA585200A6F107 /* Basic.frag in Resources */ = {isa = PBXBuildFile; fileRef = 779F561E19D79AC000A6F107 /* Basic.frag */; };
779F562319DA59D600A6F107 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 773B3D241956885A0085CE5F /* MainMenu.xib */; };
77E1C0B319D72700004344E0 /* vectorUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0A919D72700004344E0 /* vectorUtil.c */; };
77E1C0B419D72700004344E0 /* sourceUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0AB19D72700004344E0 /* sourceUtil.c */; };
77E1C0B519D72700004344E0 /* modelUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0AD19D72700004344E0 /* modelUtil.c */; };
77E1C0B619D72700004344E0 /* matrixUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0AF19D72700004344E0 /* matrixUtil.c */; };
77E1C0B719D72700004344E0 /* imageUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0B019D72700004344E0 /* imageUtil.m */; };
77E1C0C419D7298F004344E0 /* EmulatorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0BE19D7298F004344E0 /* EmulatorWindowController.m */; };
77E1C0C519D7298F004344E0 /* EmulatorGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0C019D7298F004344E0 /* EmulatorGLView.m */; };
77E1C0C619D7298F004344E0 /* EmulatorFullscreenWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E1C0C219D7298F004344E0 /* EmulatorFullscreenWindow.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@ -75,8 +84,6 @@
773B3D1B1956885A0085CE5F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
773B3D1D1956885A0085CE5F /* Apple2Mac-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Apple2Mac-Prefix.pch"; sourceTree = "<group>"; };
773B3D1F1956885A0085CE5F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
773B3D211956885A0085CE5F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
773B3D221956885A0085CE5F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
773B3D251956885A0085CE5F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
773B3D271956885A0085CE5F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
773B3D2E1956885A0085CE5F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
@ -122,13 +129,34 @@
773B3D9519568A570085CE5F /* zlib-helpers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "zlib-helpers.c"; sourceTree = "<group>"; };
773B3D9619568A570085CE5F /* zlib-helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "zlib-helpers.h"; sourceTree = "<group>"; };
773B3DCA1956903D0085CE5F /* libz.1.1.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.1.3.dylib; path = usr/lib/libz.1.1.3.dylib; sourceTree = SDKROOT; };
773B3DD1195697290085CE5F /* EmulatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmulatorView.h; sourceTree = "<group>"; };
773B3DD2195697290085CE5F /* EmulatorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EmulatorView.m; sourceTree = "<group>"; };
779DD826195764E200DF89E5 /* rom-shim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "rom-shim.c"; sourceTree = "<group>"; };
779DD850195BD9F900DF89E5 /* Apple2MacTestCPU.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Apple2MacTestCPU.app; sourceTree = BUILT_PRODUCTS_DIR; };
779DD851195BD9F900DF89E5 /* Apple2MacTestCPU-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Apple2MacTestCPU-Info.plist"; path = "/Users/aaronculliney/Documents/00web/apple2/Apple2Mac/Apple2MacTests/Apple2MacTestCPU-Info.plist"; sourceTree = "<absolute>"; };
779DD854195BDB1700DF89E5 /* CPUTestAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CPUTestAppDelegate.m; sourceTree = "<group>"; };
779DD855195BDB1700DF89E5 /* CPUTestAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPUTestAppDelegate.h; sourceTree = "<group>"; };
779F561B19D78B8200A6F107 /* renderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = renderer.h; sourceTree = "<group>"; };
779F561D19D79AC000A6F107 /* Basic.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = Basic.vert; sourceTree = "<group>"; };
779F561E19D79AC000A6F107 /* Basic.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = Basic.frag; sourceTree = "<group>"; };
77E1C0A119D726C9004344E0 /* character.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = character.vsh; path = Shaders/character.vsh; sourceTree = "<group>"; };
77E1C0A219D726C9004344E0 /* character.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = character.fsh; path = Shaders/character.fsh; sourceTree = "<group>"; };
77E1C0A819D72700004344E0 /* vectorUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vectorUtil.h; path = video_util/vectorUtil.h; sourceTree = "<group>"; };
77E1C0A919D72700004344E0 /* vectorUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vectorUtil.c; path = video_util/vectorUtil.c; sourceTree = "<group>"; };
77E1C0AA19D72700004344E0 /* sourceUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sourceUtil.h; path = video_util/sourceUtil.h; sourceTree = "<group>"; };
77E1C0AB19D72700004344E0 /* sourceUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sourceUtil.c; path = video_util/sourceUtil.c; sourceTree = "<group>"; };
77E1C0AC19D72700004344E0 /* modelUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = modelUtil.h; path = video_util/modelUtil.h; sourceTree = "<group>"; };
77E1C0AD19D72700004344E0 /* modelUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = modelUtil.c; path = video_util/modelUtil.c; sourceTree = "<group>"; };
77E1C0AE19D72700004344E0 /* matrixUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = matrixUtil.h; path = video_util/matrixUtil.h; sourceTree = "<group>"; };
77E1C0AF19D72700004344E0 /* matrixUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = matrixUtil.c; path = video_util/matrixUtil.c; sourceTree = "<group>"; };
77E1C0B019D72700004344E0 /* imageUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = imageUtil.m; path = video_util/imageUtil.m; sourceTree = "<group>"; };
77E1C0B119D72700004344E0 /* imageUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imageUtil.h; path = video_util/imageUtil.h; sourceTree = "<group>"; };
77E1C0B219D72700004344E0 /* glUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glUtil.h; path = video_util/glUtil.h; sourceTree = "<group>"; };
77E1C0BE19D7298F004344E0 /* EmulatorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EmulatorWindowController.m; path = Classes/OSX/EmulatorWindowController.m; sourceTree = "<group>"; };
77E1C0BF19D7298F004344E0 /* EmulatorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EmulatorWindowController.h; path = Classes/OSX/EmulatorWindowController.h; sourceTree = "<group>"; };
77E1C0C019D7298F004344E0 /* EmulatorGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EmulatorGLView.m; path = Classes/OSX/EmulatorGLView.m; sourceTree = "<group>"; };
77E1C0C119D7298F004344E0 /* EmulatorGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EmulatorGLView.h; path = Classes/OSX/EmulatorGLView.h; sourceTree = "<group>"; };
77E1C0C219D7298F004344E0 /* EmulatorFullscreenWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EmulatorFullscreenWindow.m; path = Classes/OSX/EmulatorFullscreenWindow.m; sourceTree = "<group>"; };
77E1C0C319D7298F004344E0 /* EmulatorFullscreenWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EmulatorFullscreenWindow.h; path = Classes/OSX/EmulatorFullscreenWindow.h; sourceTree = "<group>"; };
77E1C0C719D736EB004344E0 /* glvideo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = glvideo.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -198,6 +226,7 @@
children = (
773B3D4519568A570085CE5F /* src */,
773B3D431956897D0085CE5F /* Classes */,
77E1C09E19D726B8004344E0 /* Shaders */,
773B3D44195689910085CE5F /* Resources */,
773B3D161956885A0085CE5F /* Supporting Files */,
);
@ -239,10 +268,12 @@
773B3D431956897D0085CE5F /* Classes */ = {
isa = PBXGroup;
children = (
773B3D211956885A0085CE5F /* AppDelegate.h */,
773B3D221956885A0085CE5F /* AppDelegate.m */,
773B3DD1195697290085CE5F /* EmulatorView.h */,
773B3DD2195697290085CE5F /* EmulatorView.m */,
77E1C0BE19D7298F004344E0 /* EmulatorWindowController.m */,
77E1C0BF19D7298F004344E0 /* EmulatorWindowController.h */,
77E1C0C019D7298F004344E0 /* EmulatorGLView.m */,
77E1C0C119D7298F004344E0 /* EmulatorGLView.h */,
77E1C0C219D7298F004344E0 /* EmulatorFullscreenWindow.m */,
77E1C0C319D7298F004344E0 /* EmulatorFullscreenWindow.h */,
);
name = Classes;
sourceTree = "<group>";
@ -284,6 +315,7 @@
773B3D8819568A570085CE5F /* timing.h */,
773B3D8919568A570085CE5F /* uthash.h */,
773B3D8A19568A570085CE5F /* video */,
77E1C0A719D726E8004344E0 /* video_util */,
773B3D8D19568A570085CE5F /* vm.c */,
773B3D8E19568A570085CE5F /* x86 */,
773B3D9519568A570085CE5F /* zlib-helpers.c */,
@ -321,7 +353,11 @@
773B3D8A19568A570085CE5F /* video */ = {
isa = PBXGroup;
children = (
779F561D19D79AC000A6F107 /* Basic.vert */,
779F561E19D79AC000A6F107 /* Basic.frag */,
77E1C0C719D736EB004344E0 /* glvideo.c */,
773B3D8B19568A570085CE5F /* video.h */,
779F561B19D78B8200A6F107 /* renderer.h */,
);
path = video;
sourceTree = "<group>";
@ -337,6 +373,33 @@
path = x86;
sourceTree = "<group>";
};
77E1C09E19D726B8004344E0 /* Shaders */ = {
isa = PBXGroup;
children = (
77E1C0A119D726C9004344E0 /* character.vsh */,
77E1C0A219D726C9004344E0 /* character.fsh */,
);
name = Shaders;
sourceTree = "<group>";
};
77E1C0A719D726E8004344E0 /* video_util */ = {
isa = PBXGroup;
children = (
77E1C0A819D72700004344E0 /* vectorUtil.h */,
77E1C0A919D72700004344E0 /* vectorUtil.c */,
77E1C0AA19D72700004344E0 /* sourceUtil.h */,
77E1C0AB19D72700004344E0 /* sourceUtil.c */,
77E1C0AC19D72700004344E0 /* modelUtil.h */,
77E1C0AD19D72700004344E0 /* modelUtil.c */,
77E1C0AE19D72700004344E0 /* matrixUtil.h */,
77E1C0AF19D72700004344E0 /* matrixUtil.c */,
77E1C0B019D72700004344E0 /* imageUtil.m */,
77E1C0B119D72700004344E0 /* imageUtil.h */,
77E1C0B219D72700004344E0 /* glUtil.h */,
);
name = video_util;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -413,8 +476,10 @@
files = (
773B3D1A1956885A0085CE5F /* InfoPlist.strings in Resources */,
773B3D281956885A0085CE5F /* Images.xcassets in Resources */,
779F562219DA585200A6F107 /* Basic.frag in Resources */,
773B3D201956885A0085CE5F /* Credits.rtf in Resources */,
773B3D261956885A0085CE5F /* MainMenu.xib in Resources */,
779F562119DA584800A6F107 /* Basic.vert in Resources */,
779F562319DA59D600A6F107 /* MainMenu.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -500,20 +565,27 @@
773B3DA419568A570085CE5F /* display.c in Sources */,
773B3DA319568A570085CE5F /* disk.c in Sources */,
773B3DAD19568A570085CE5F /* debugger.c in Sources */,
77E1C0B319D72700004344E0 /* vectorUtil.c in Sources */,
773B3DAB19568A570085CE5F /* keys.c in Sources */,
773B3DBC19568A570085CE5F /* timing.c in Sources */,
773B3DAF19568A570085CE5F /* misc.c in Sources */,
77E1C0C419D7298F004344E0 /* EmulatorWindowController.m in Sources */,
77E1C0B619D72700004344E0 /* matrixUtil.c in Sources */,
77E1C0C519D7298F004344E0 /* EmulatorGLView.m in Sources */,
773B3DAE19568A570085CE5F /* opcodes.c in Sources */,
779DD827195764E200DF89E5 /* rom-shim.c in Sources */,
773B3DC319568A570085CE5F /* zlib-helpers.c in Sources */,
77E1C0B719D72700004344E0 /* imageUtil.m in Sources */,
773B3DA219568A570085CE5F /* darwin-shim.c in Sources */,
773B3D231956885A0085CE5F /* AppDelegate.m in Sources */,
77E1C0B519D72700004344E0 /* modelUtil.c in Sources */,
773B3DAC19568A570085CE5F /* debug.l in Sources */,
77E1C0C619D7298F004344E0 /* EmulatorFullscreenWindow.m in Sources */,
773B3DA519568A570085CE5F /* font.c in Sources */,
773B3DA019568A570085CE5F /* cpu-supp.c in Sources */,
779F561C19D7929100A6F107 /* glvideo.c in Sources */,
77E1C0B419D72700004344E0 /* sourceUtil.c in Sources */,
773B3DBE19568A570085CE5F /* vm.c in Sources */,
773B3DC019568A570085CE5F /* darwin-glue.S in Sources */,
773B3DD3195697290085CE5F /* EmulatorView.m in Sources */,
773B3D1C1956885A0085CE5F /* main.m in Sources */,
773B3DAA19568A570085CE5F /* joystick.c in Sources */,
);

View File

@ -1,15 +0,0 @@
//
// AppDelegate.h
// Apple2Mac
//
// Created by Aaron Culliney on 6/21/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (assign) IBOutlet NSWindow *window;
@end

View File

@ -1,27 +0,0 @@
//
// AppDelegate.m
// Apple2Mac
//
// Created by Aaron Culliney on 6/21/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
#import "AppDelegate.h"
#import "common.h"
extern void c_initialize_firsttime(void);
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
#if 0
c_initialize_firsttime();
// spin off cpu thread
pthread_create(&cpu_thread_id, NULL, (void *) &cpu_thread, (void *)NULL);
#endif
}
@end

View File

@ -1,664 +1,80 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13D65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment version="1060" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate">
<connections>
<outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="Apple2Mac" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Apple2Mac" systemMenu="apple" id="uQy-DD-JDr">
<menuItem title="Apple2Mac" id="56">
<menu key="submenu" title="Apple2Mac" systemMenu="apple" id="57">
<items>
<menuItem title="About Apple2Mac" id="5kV-Vb-QxS">
<menuItem title="About Apple2Mac" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
<menuItem isSeparatorItem="YES" id="236">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide Apple2Mac" keyEquivalent="h" id="Olw-nP-bQN">
<menuItem title="Toggle Full Screen..." keyEquivalent="F" id="rP9-cs-9dM">
<connections>
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
<action selector="toggleFullScreen:" target="M8b-ga-iOS" id="Xan-eQ-CRM"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
<menuItem isSeparatorItem="YES" id="143">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Services" id="131">
<menu key="submenu" title="Services" systemMenu="services" id="130"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide Apple2Mac" keyEquivalent="h" id="134">
<connections>
<action selector="hide:" target="-1" id="367"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="145">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
<action selector="hideOtherApplications:" target="-1" id="368"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<menuItem title="Show All" id="150">
<connections>
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
<action selector="unhideAllApplications:" target="-1" id="370"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit Apple2Mac" keyEquivalent="q" id="4sb-4s-VLi">
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit Apple2Mac" keyEquivalent="q" id="136">
<connections>
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
<action selector="terminate:" target="-3" id="449"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="dMs-cI-mzQ">
<menuItem title="Help" id="490">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="File" id="bib-Uj-vzu">
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
<menuItem title="Apple2Mac Help" keyEquivalent="?" id="492" userLabel="Menu Item - Apple2Mac Help">
<connections>
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
</connections>
</menuItem>
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
<connections>
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="tXI-mr-wws">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
<items>
<menuItem title="Clear Menu" id="vNY-rz-j42">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
<connections>
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
<connections>
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
</connections>
</menuItem>
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
<connections>
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="KaW-ft-85H">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
</connections>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
<connections>
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
<items>
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
<connections>
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
<connections>
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
<connections>
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
<connections>
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
<connections>
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
</connections>
</menuItem>
<menuItem title="Delete" id="pa3-QI-u2k">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
<connections>
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
<menuItem title="Find" id="4EN-yA-p0u">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Find" id="1b7-l0-nxx">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
<connections>
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
<connections>
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
<connections>
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
<connections>
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
<connections>
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
<connections>
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="9ic-FL-obx">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
<items>
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
</connections>
</menuItem>
<menuItem title="Smart Links" id="cwL-P1-jid">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
</connections>
</menuItem>
<menuItem title="Data Detectors" id="tRr-pd-1PS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="2oI-Rn-ZJC">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
<items>
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="xrE-MZ-jX0">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
<items>
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
<items>
<menuItem title="Font" id="Gi5-1S-RQB">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
<connections>
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
<connections>
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
<menuItem title="Kern" id="jBQ-r6-VK2">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
<items>
<menuItem title="Use Default" id="GUa-eO-cwY">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
</connections>
</menuItem>
<menuItem title="Use None" id="cDB-IK-hbR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="46P-cB-AYj">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="ogc-rX-tC1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="o6e-r0-MWq">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
<items>
<menuItem title="Use Default" id="agt-UL-0e3">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
</connections>
</menuItem>
<menuItem title="Use None" id="J7y-lM-qPV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
</connections>
</menuItem>
<menuItem title="Use All" id="xQD-1f-W4t">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="OaQ-X3-Vso">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
<items>
<menuItem title="Use Default" id="3Om-Ey-2VK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="Rqc-34-cIF">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="I0S-gh-46l">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
</connections>
</menuItem>
<menuItem title="Raise" id="2h7-ER-AoG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
</connections>
</menuItem>
<menuItem title="Lower" id="1tx-W0-xDw">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
<connections>
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="Fal-I4-PZk">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="d9c-me-L2H">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
<connections>
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
<connections>
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
</connections>
</menuItem>
<menuItem title="Justify" id="J5U-5w-g23">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
<connections>
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
<menuItem title="Writing Direction" id="H1b-Si-o9J">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
<items>
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="YGs-j5-SAR">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
</connections>
</menuItem>
<menuItem id="Lbh-J2-qVU">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
</connections>
</menuItem>
<menuItem id="jFq-tB-4Kx">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="Nop-cj-93Q">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
</connections>
</menuItem>
<menuItem id="BgM-ve-c93">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
</connections>
</menuItem>
<menuItem id="RB4-Sm-HuC">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
<menuItem title="Show Ruler" id="vLm-3I-IUL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
</connections>
</menuItem>
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
<connections>
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="R4o-n2-Eq4">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
<items>
<menuItem title="Apple2Mac Help" keyEquivalent="?" id="FKE-Sm-Kum">
<connections>
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
@ -666,15 +82,22 @@
</menuItem>
</items>
</menu>
<window title="Apple2Mac" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<window title="Apple2Mac" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371" userLabel="Window - Apple2Mac">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="778"/>
<view key="contentView" id="EiT-Mj-1SZ" customClass="EmulatorView">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<rect key="contentRect" x="200" y="200" width="320" height="480"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1178"/>
<view key="contentView" id="372" customClass="EmulatorGLView">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</window>
<customObject id="494" userLabel="GL Essentials View" customClass="EmulatorGLView"/>
<customObject id="M8b-ga-iOS" userLabel="GL Essentials Window Controller" customClass="EmulatorWindowController" colorLabel="IBBuiltInLabel-Blue">
<connections>
<outlet property="view" destination="372" id="pRG-Kn-92X"/>
<outlet property="window" destination="371" id="z3B-S9-PsV"/>
</connections>
</customObject>
</objects>
</document>

View File

@ -0,0 +1,15 @@
//
// EmulatorFullscreenWindow.h
// Apple2Mac
//
// Created by Aaron Culliney on 9/27/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
// Based on sample code from https://developer.apple.com/library/mac/samplecode/GLEssentials/Introduction/Intro.html
#import <Cocoa/Cocoa.h>
@interface EmulatorFullscreenWindow : NSWindow
@end

View File

@ -0,0 +1,48 @@
//
// EmulatorFullscreenWindow.m
// Apple2Mac
//
// Created by Aaron Culliney on 9/27/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
// Based on sample code from https://developer.apple.com/library/mac/samplecode/GLEssentials/Introduction/Intro.html
#import "EmulatorFullscreenWindow.h"
@implementation EmulatorFullscreenWindow
- (id)init
{
// Create a screen-sized window on the display you want to take over
NSRect screenRect = [[NSScreen mainScreen] frame];
// Initialize the window making it size of the screen and borderless
self = [super initWithContentRect:screenRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
// Set the window level to be above the menu bar to cover everything else
[self setLevel:NSMainMenuWindowLevel+1];
// Set opaque
[self setOpaque:YES];
// Hide this when user switches to another window (or app)
[self setHidesOnDeactivate:YES];
return self;
}
- (BOOL)canBecomeKeyWindow
{
// Return yes so that this borderless window can receive input
return YES;
}
- (void)keyDown:(NSEvent *)event
{
// Implement keyDown since controller will not get [ESC] key event which
// the controller uses to kill fullscreen
[[self windowController] keyDown:event];
}
@end

View File

@ -0,0 +1,18 @@
//
// EmulatorGLView.h
// Apple2Mac
//
// Created by Aaron Culliney on 9/27/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
// Based on sample code from https://developer.apple.com/library/mac/samplecode/GLEssentials/Introduction/Intro.html
#import <Cocoa/Cocoa.h>
#import <QuartzCore/CVDisplayLink.h>
#import "modelUtil.h"
#import "imageUtil.h"
@interface EmulatorGLView : NSOpenGLView
@end

View File

@ -0,0 +1,304 @@
//
// EmulatorGLView.m
// Apple2Mac
//
// Created by Aaron Culliney on 9/27/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
// Based on sample code from https://developer.apple.com/library/mac/samplecode/GLEssentials/Introduction/Intro.html
#import "EmulatorGLView.h"
// Apple //e common routines
#import "common.h"
#import "video/renderer.h"
#if TARGET_OS_MAC
#define USE_DISPLAYLINK 0
#define BROKEN_DISPLAYLINK 1
#else
// iOS uses CADisplayLink
#define USE_DISPLAYLINK 1
#endif
#define SUPPORT_RETINA_RESOLUTION 1
@interface EmulatorGLView ()
#if USE_DISPLAYLINK
@property (nonatomic, assign) CVDisplayLinkRef displayLink;
#else
@property (nonatomic, retain) NSTimer *timer;
#endif
- (void)initGL;
@end
@implementation EmulatorGLView
#if USE_DISPLAYLINK
@synthesize displayLink = _displayLink;
#else
@synthesize timer = _timer;
#endif
#pragma mark CVDisplayLink / NSTimer stuff
#if USE_DISPLAYLINK
- (CVReturn)getFrameForTime:(const CVTimeStamp *)outputTime
{
// There is no autorelease pool when this method is called
// because it will be called from a background thread.
// It's important to create one or app can leak objects.
@autoreleasepool {
// We draw on a secondary thread through the display link
// When resizing the view, -reshape is called automatically on the main
// thread. Add a mutex around to avoid the threads accessing the context
// simultaneously when resizing
#if BROKEN_DISPLAYLINK
#warning ASC NOTE 2014/09/27 multi-threaded OpenGL on Mac considered harmful to developer sanity
// 2014/09/27 Kinda defeats the purpose of using CVDisplayLink ... but keeps it from crashing to dispatch to main queue
dispatch_async(dispatch_get_main_queue(), ^{
#endif
[[self openGLContext] makeCurrentContext];
[self drawView];
#if BROKEN_DISPLAYLINK
});
#endif
}
return kCVReturnSuccess;
}
// This is the renderer output callback function
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext)
{
CVReturn result = [(EmulatorGLView *)displayLinkContext getFrameForTime:outputTime];
return result;
}
#else // use NSTimer
- (void)targetMethod:(NSTimer *)theTimer
{
NSAssert([NSThread isMainThread], @"Timer fired on non-main thread!");
[[self openGLContext] makeCurrentContext];
[self drawView];
}
#endif
#pragma mark -
- (void)awakeFromNib
{
NSOpenGLPixelFormatAttribute attrs[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, 24,
// Must specify the 3.2 Core Profile to use OpenGL 3.2
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
NSOpenGLPFAOpenGLProfile,
NSOpenGLProfileVersion3_2Core,
#endif
0
};
NSOpenGLPixelFormat *pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease];
if (!pf)
{
NSLog(@"No OpenGL pixel format");
}
NSOpenGLContext* context = [[[NSOpenGLContext alloc] initWithFormat:pf shareContext:nil] autorelease];
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 && defined(DEBUG)
// When we're using a CoreProfile context, crash if we call a legacy OpenGL function
// This will make it much more obvious where and when such a function call is made so
// that we can remove such calls.
// Without this we'd simply get GL_INVALID_OPERATION error for calling legacy functions
// but it would be more difficult to see where that function was called.
CGLEnable([context CGLContextObj], kCGLCECrashOnRemovedFunctions);
#endif
[self setPixelFormat:pf];
[self setOpenGLContext:context];
#if SUPPORT_RETINA_RESOLUTION
// Opt-In to Retina resolution
[self setWantsBestResolutionOpenGLSurface:YES];
#endif // SUPPORT_RETINA_RESOLUTION
}
- (void)prepareOpenGL
{
[super prepareOpenGL];
// Make all the OpenGL calls to setup rendering
// and build the necessary rendering objects
[self initGL];
#if USE_DISPLAYLINK
// Create a display link capable of being used with all active displays
CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
// Set the renderer output callback function
CVDisplayLinkSetOutputCallback(_displayLink, &displayLinkCallback, self);
// Set the display link for the current renderer
CGLContextObj cglContext = [[self openGLContext] CGLContextObj];
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(_displayLink, cglContext, cglPixelFormat);
// Activate the display link
CVDisplayLinkStart(_displayLink);
#else
[self.timer invalidate];
self.timer = nil;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(targetMethod:) userInfo:nil repeats:YES];
#endif
// Register to be notified when the window closes so we can stop the displaylink
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:[self window]];
}
- (void)windowWillClose:(NSNotification*)notification
{
// Stop the display link when the window is closing because default
// OpenGL render buffers will be destroyed. If display link continues to
// fire without renderbuffers, OpenGL draw calls will set errors.
#if USE_DISPLAYLINK
CVDisplayLinkStop(_displayLink);
#else
[self.timer invalidate];
self.timer = nil;
#endif
}
- (void)initGL
{
// The reshape function may have changed the thread to which our OpenGL
// context is attached before prepareOpenGL and initGL are called. So call
// makeCurrentContext to ensure that our OpenGL context current to this
// thread (i.e. makeCurrentContext directs all OpenGL calls on this thread
// to [self openGLContext])
[[self openGLContext] makeCurrentContext];
c_initialize_firsttime();
pthread_create(&cpu_thread_id, NULL, (void *)&cpu_thread, (void *)NULL);
// Synchronize buffer swaps with vertical refresh rate
GLint swapInt = 1;
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
// Init our renderer. Use 0 for the defaultFBO which is appropriate for
// OSX (but not iOS since iOS apps must create their own FBO)
#if TARGET_OS_MAC
video_driver_init(0);
#elif TARGET_OS_IPHONE
# error "FBO FIXME TODO"
video_driver_init(otherFBO);
#else
# error "unknown/unsupported Apple platform
#endif
}
- (void)reshape
{
[super reshape];
// We draw on a secondary thread through the display link. However, when
// resizing the view, -drawRect is called on the main thread.
// Add a mutex around to avoid the threads accessing the context
// simultaneously when resizing.
CGLLockContext([[self openGLContext] CGLContextObj]);
// Get the view size in Points
NSRect viewRectPoints = [self bounds];
#if SUPPORT_RETINA_RESOLUTION
// Rendering at retina resolutions will reduce aliasing, but at the potential
// cost of framerate and battery life due to the GPU needing to render more
// pixels.
// Any calculations the renderer does which use pixel dimentions, must be
// in "retina" space. [NSView convertRectToBacking] converts point sizes
// to pixel sizes. Thus the renderer gets the size in pixels, not points,
// so that it can set it's viewport and perform and other pixel based
// calculations appropriately.
// viewRectPixels will be larger (2x) than viewRectPoints for retina displays.
// viewRectPixels will be the same as viewRectPoints for non-retina displays
NSRect viewRectPixels = [self convertRectToBacking:viewRectPoints];
#else //if !SUPPORT_RETINA_RESOLUTION
// App will typically render faster and use less power rendering at
// non-retina resolutions since the GPU needs to render less pixels. There
// is the cost of more aliasing, but it will be no-worse than on a Mac
// without a retina display.
// Points:Pixels is always 1:1 when not supporting retina resolutions
NSRect viewRectPixels = viewRectPoints;
#endif // !SUPPORT_RETINA_RESOLUTION
// Set the new dimensions in our renderer
video_driver_reshape((int)viewRectPixels.size.width, (int)viewRectPixels.size.height);
CGLUnlockContext([[self openGLContext] CGLContextObj]);
}
- (void)renewGState
{
// Called whenever graphics state updated (such as window resize)
// OpenGL rendering is not synchronous with other rendering on the OSX.
// Therefore, call disableScreenUpdatesUntilFlush so the window server
// doesn't render non-OpenGL content in the window asynchronously from
// OpenGL content, which could cause flickering. (non-OpenGL content
// includes the title bar and drawing done by the app with other APIs)
[[self window] disableScreenUpdatesUntilFlush];
[super renewGState];
}
- (void)drawRect:(NSRect)theRect
{
NSAssert([NSThread isMainThread], @"drawRect called on non-main thread!");
// Called during resize operations
// Avoid flickering during resize by drawing
[[self openGLContext] makeCurrentContext];
[self drawView];
}
- (void)drawView
{
CGLLockContext([[self openGLContext] CGLContextObj]);
video_driver_render();
CGLFlushDrawable([[self openGLContext] CGLContextObj]);
CGLUnlockContext([[self openGLContext] CGLContextObj]);
}
- (void)dealloc
{
// Stop the display link BEFORE releasing anything in the view
// otherwise the display link thread may call into the view and crash
// when it encounters something that has been release
#if USE_DISPLAYLINK
CVDisplayLinkStop(_displayLink);
CVDisplayLinkRelease(_displayLink);
#else
[self.timer invalidate];
self.timer = nil;
#endif
// shut down common OpenGL stuff AFTER display link has been released
video_driver_shutdown();
[super dealloc];
}
@end

View File

@ -0,0 +1,16 @@
//
// EmulatorWindowController.h
// Apple2Mac
//
// Created by Aaron Culliney on 9/27/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
// Based on sample code from https://developer.apple.com/library/mac/samplecode/GLEssentials/Introduction/Intro.html
#import <Cocoa/Cocoa.h>
#import "EmulatorGLView.h"
@interface EmulatorWindowController : NSWindowController
@end

View File

@ -0,0 +1,136 @@
//
// EmulatorWindowController.m
// Apple2Mac
//
// Created by Aaron Culliney on 9/27/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
// Based on sample code from https://developer.apple.com/library/mac/samplecode/GLEssentials/Introduction/Intro.html
#import "EmulatorWindowController.h"
#import "EmulatorFullscreenWindow.h"
@interface EmulatorWindowController ()
@property (nonatomic, assign) IBOutlet EmulatorGLView *view;
@property (nonatomic, retain) EmulatorFullscreenWindow *fullscreenWindow;
@property (nonatomic, retain) NSWindow *standardWindow;
@end
@implementation EmulatorWindowController
@synthesize view = _view;
@synthesize fullscreenWindow = _fullscreenWindow;
@synthesize standardWindow = _standardWindow;
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self)
{
// Initialize to nil since it indicates app is not fullscreen
self.fullscreenWindow = nil;
}
return self;
}
- (IBAction)toggleFullScreen:(id)sender
{
if (self.fullscreenWindow)
{
[self goWindow];
}
else
{
[self goFullscreen];
}
}
- (void)goFullscreen
{
// If app is already fullscreen...
if (self.fullscreenWindow)
{
//...don't do anything
return;
}
// Allocate a new fullscreen window
self.fullscreenWindow = [[[EmulatorFullscreenWindow alloc] init] autorelease];
// Resize the view to screensize
NSRect viewRect = [self.fullscreenWindow frame];
// Set the view to the size of the fullscreen window
[self.view setFrameSize: viewRect.size];
// Set the view in the fullscreen window
[self.fullscreenWindow setContentView:self.view];
self.standardWindow = [self window];
// Hide non-fullscreen window so it doesn't show up when switching out
// of this app (i.e. with CMD-TAB)
[self.standardWindow orderOut:self];
// Set controller to the fullscreen window so that all input will go to
// this controller (self)
[self setWindow:self.fullscreenWindow];
// Show the window and make it the key window for input
[self.fullscreenWindow makeKeyAndOrderFront:self];
}
- (void)goWindow
{
// If controller doesn't have a full screen window...
if (self.fullscreenWindow == nil)
{
//...app is already windowed so don't do anything
return;
}
// Get the rectangle of the original window
NSRect viewRect = [self.standardWindow frame];
// Set the view rect to the new size
[self.view setFrame:viewRect];
// Set controller to the standard window so that all input will go to
// this controller (self)
[self setWindow:self.standardWindow];
// Set the content of the orginal window to the view
[[self window] setContentView:self.view];
// Show the window and make it the key window for input
[[self window] makeKeyAndOrderFront:self];
// Release/nilify fullscreenWindow
self.fullscreenWindow = nil;
}
- (void)keyDown:(NSEvent *)event
{
unichar c = [[event charactersIgnoringModifiers] characterAtIndex:0];
switch (c)
{
case 27:
NSLog(@"key ESC");
return;
case 'f':
NSLog(@"key 'f'");
return;
}
// Allow other character to be handled (or not and beep)
[super keyDown:event];
}
@end

View File

@ -1,13 +0,0 @@
//
// EmulatorView.h
// Apple2Mac
//
// Created by Aaron Culliney on 6/21/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface EmulatorView : NSView
@end

View File

@ -1,59 +0,0 @@
//
// EmulatorView.m
// Apple2Mac
//
// Created by Aaron Culliney on 6/21/14.
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
#import "EmulatorView.h"
void video_driver_init() {
// TBD ... initialize main game GL view
}
void video_driver_shutdown() {
// TBD ... destroy main game GL view
}
void video_sync(int ignored) {
// TBD ...
}
@implementation EmulatorView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
NSString* hws = @"Hello World!";
NSPoint p;
NSMutableDictionary* attribs;
NSColor* c;
NSFont* fnt;
p = NSMakePoint( 10, 100 );
attribs = [[[NSMutableDictionary alloc] init] autorelease];
c = [NSColor redColor];
fnt = [NSFont fontWithName:@"Times Roman" size:48];
[attribs setObject:c forKey:NSForegroundColorAttributeName];
[attribs setObject:fnt forKey:NSFontAttributeName];
[hws drawAtPoint:p withAttributes:attribs];
}
@end

View File

@ -6,14 +6,28 @@
// Copyright (c) 2014 deadc0de.org. All rights reserved.
//
#if ESSENTIAL_GL_PRACTICES_IOS
#import <UIKit/UIKit.h>
#else
#import <Cocoa/Cocoa.h>
#endif
extern int argc;
extern const char **argv;
int main(int argc_, const char *argv_[])
{
int retVal = 1;
argc = argc_;
argv = argv_;
return NSApplicationMain(argc, argv);
#if ESSENTIAL_GL_PRACTICES_IOS
@autoreleasepool {
retVal = UIApplicationMain(argc, argv, nil, nil);
}
#else
retVal = NSApplicationMain(argc, argv);
#endif
return retVal;
}

View File

@ -58,7 +58,7 @@
#if VIDEO_OPENGL
#include "video/vgl.h"
#else
#define GLint int
#define GLenum int
#define glGetError() 0
#endif
@ -103,36 +103,42 @@ extern FILE *error_log;
#define LOG(...) \
if (do_logging) { \
errno = 0; \
GLint _glerr = 0; \
GLenum _glerr = 0; \
_LOG(__VA_ARGS__); \
}
#define ERRLOG(...) \
if (do_logging) { \
GLint _glerr = glGetError(); \
GLenum _glerr = glGetError(); \
_LOG(__VA_ARGS__); \
while ( (_glerr = glGetError()) ) { \
_LOG(__VA_ARGS__); \
} \
}
#define GL_ERRLOG(...) \
if (do_logging) { \
GLint _glerr = glGetError(); \
if (_glerr) { \
GLenum _glerr = 0; \
while ( (_glerr = glGetError()) ) { \
_LOG(__VA_ARGS__); \
} \
}
#define ERRQUIT(...) \
do { \
GLint _glerr = glGetError(); \
GLenum _glerr = glGetError(); \
_LOG(__VA_ARGS__); \
while ( (_glerr = glGetError()) ) { \
_LOG(__VA_ARGS__); \
} \
QUIT_FUNCTION(1); \
} while(0)
#define GL_ERRQUIT(...) \
do { \
GLint _glerr = glGetError(); \
if (_glerr) { \
_LOG( __VA_ARGS__); \
GLenum _glerr = 0; \
while ( (_glerr = glGetError()) ) { \
_LOG(__VA_ARGS__); \
QUIT_FUNCTION(_glerr); \
} \
} while(0)
@ -157,7 +163,7 @@ extern FILE *error_log;
#define RELEASE_LOG(...) \
do { \
GLint _glerr = glGetError(); \
GLenum _glerr = glGetError(); \
errno = 0; \
_LOG(__VA_ARGS__); \
} while(0);
@ -168,4 +174,12 @@ extern FILE *error_log;
(x) = NULL; \
} while (0);
#ifdef __APPLE__
#define CFRELEASE(x) \
do { \
CFRelease((x)); \
(x) = NULL; \
} while (0);
#endif
#endif // whole file

View File

@ -15,6 +15,7 @@
*/
#include "common.h"
#include "video/renderer.h"
#define DYNAMIC_SZ 11 // 7 pixels (as bytes) + 2pre + 2post
@ -564,12 +565,6 @@ void video_plotchar( int x, int y, int scheme, uint8_t c ) {
_plot_char80(&d,&s);
}
#if !HEADLESS
extern void video_driver_init(void);
extern void video_driver_main_loop(void);
extern void video_driver_sync(void);
extern void video_driver_shutdown(void);
#endif
void video_init(void) {
video__fb1 = vga_mem_page_0;
@ -581,10 +576,12 @@ void video_init(void) {
video_initialize_color();
#if !HEADLESS
#if !defined(__APPLE__)
if (!is_headless) {
video_driver_init();
video_driver_init((void *)0);
}
#endif
#endif
}
void video_main_loop(void) {
@ -598,8 +595,10 @@ void video_shutdown(void) {
if (!is_headless) {
video_driver_shutdown();
}
#if !defined(__APPLE__)
exit(0);
#endif
#endif
}
/* -------------------------------------------------------------------------

View File

@ -634,7 +634,7 @@ int main(int _argc, char **_argv) {
c_initialize_firsttime(); /* init svga graphics and vm */
// spin off cpu thread
pthread_create(&cpu_thread_id, NULL, (void *) &cpu_thread,(void *)NULL);
pthread_create(&cpu_thread_id, NULL, (void *)&cpu_thread, (void *)NULL);
c_keys_set_key(kF8); // show credits

View File

@ -1,13 +1,30 @@
static const char * fragmentShader =
"#version 100\n"
#ifdef GL_ES
precision highp float;
#endif
"varying lowp vec4 DestinationColor;\n"
"varying mediump vec2 TextureCoordOut;\n"
// Declare inputs and outputs
// varTexcoord : TexCoord for the fragment computed by the rasterizer based on
// the varTexcoord values output in the vertex shader.
// gl_FragColor : Implicitly declare in fragments shaders less than 1.40.
// Output color of our fragment.
// fragColor : Output color of our fragment. Basically the same as gl_FragColor,
// but we must explicitly declared this in shaders version 1.40 and
// above.
"uniform sampler2D Sampler;\n"
#if __VERSION__ >= 140
in vec2 varTexcoord;
out vec4 fragColor;
#else
varying vec2 varTexcoord;
#endif
"void main(void) {\n"
" //gl_FragColor = texture2D(Sampler, TextureCoordOut) * DestinationColor;\n"
" gl_FragColor = texture2D(Sampler, TextureCoordOut);\n"
"}"
;
uniform sampler2D diffuseTexture;
void main(void)
{
#if __VERSION__ >= 140
fragColor = texture(diffuseTexture, varTexcoord.st, 0.0);
#else
gl_FragColor = texture2D(diffuseTexture, varTexcoord.st, 0.0);
#endif
}

View File

@ -1,24 +1,35 @@
static const char * vertexShader =
"#version 100\n"
#ifdef GL_ES
precision highp float;
#endif
"attribute vec4 Position;\n"
"attribute vec2 TextureCoord;\n"
"//attribute vec4 TestColor;\n"
// Declare our modelViewProjection matrix that we'll compute
// outside the shader and set each frame
uniform mat4 modelViewProjectionMatrix;
"// base screen scolor\n"
"uniform vec4 SourceColor;\n"
// Declare inputs and outputs
// inPosition : Position attributes from the VAO/VBOs
// inTexcoord : Texcoord attributes from the VAO/VBOs
// varTexcoord : TexCoord we'll pass to the rasterizer
// gl_Position : implicitly declared in all vertex shaders. Clip space position
// passed to rasterizer used to build the triangles
"uniform mat4 Projection;\n"
"uniform mat4 Modelview;\n"
#if __VERSION__ >= 140
in vec4 inPosition;
in vec2 inTexcoord;
out vec2 varTexcoord;
#else
attribute vec4 inPosition;
attribute vec2 inTexcoord;
varying vec2 varTexcoord;
#endif
"varying vec4 DestinationColor;\n"
"varying vec2 TextureCoordOut;\n"
void main(void)
{
// Transform the vertex by the model view projection matrix so
// the polygon shows up in the right place
gl_Position = modelViewProjectionMatrix * inPosition;
"void main(void) {\n"
" DestinationColor = SourceColor;\n"
" //DestinationColor = TestColor;\n"
" //gl_Position = Projection * Modelview * Position;\n"
" gl_Position = Position;\n"
" TextureCoordOut = TextureCoord;\n"
"}\n"
;
// Pass the unmodified texture coordinate from the vertex buffer
// directly down to the rasterizer.
varTexcoord = inTexcoord;
}

View File

@ -14,44 +14,23 @@
#include "common.h"
#include "video/glinput.h"
#include "video/vgl.h"
#if 0
#include "video/matmath.h"
#include "video/renderer.h"
#include "video_util/modelUtil.h"
#include "video_util/sourceUtil.h"
#ifdef __APPLE__
#import <CoreFoundation/CoreFoundation.h>
#endif
#include "video/Basic.vert"
#include "video/Basic.frag"
// TODO: implement 3D CRT object, possibly with perspective drawing?
#define PERSPECTIVE 0
#define DEBUG_GEOMETRY 0
typedef struct UniformHandles {
GLuint modelview;
GLuint projection;
GLuint sourceColor;
} UniformHandles;
typedef struct AttributeHandles {
GLuint position;
GLuint texCoord;
#if DEBUG_GEOMETRY
GLuint testColor;
#endif
} AttributeHandles;
typedef struct Drawable {
GLuint vertexBuffer;
GLuint indexBuffer;
int vertexCount;
int indexCount;
bool allocated;
} Drawable;
typedef struct ShaderInfo {
GLuint shader;
GLenum type;// GL shader type
const char *shadername;
const GLchar *source;
UT_hash_handle hh;
} ShaderInfo;
enum {
POS_ATTRIB_IDX,
NORMAL_ATTRIB_IDX,
TEXCOORD_ATTRIB_IDX
};
static int windowWidth = SCANWIDTH*1.5;
static int windowHeight = SCANHEIGHT*1.5;
@ -61,306 +40,603 @@ static int viewportY = 0;
static int viewportWidth = SCANWIDTH*1.5;
static int viewportHeight = SCANHEIGHT*1.5;
#if 0
static matT translation = {};
#endif
static GLint uniformMVPIdx;
static GLuint crtVAOName;
static GLenum crtElementType;
static GLuint crtNumElements;
static GLuint a2framebufferTexture = 0;
static UniformHandles uniforms = { 0 };
static AttributeHandles attributes = { 0 };
static Drawable crtDrawable = { 0 };
static ShaderInfo *allShaders = NULL;
static GLuint a2TextureName = 0;
static GLuint defaultFBO = 0;
static GLuint program = 0;
//----------------------------------------------------------------------------
//
// compile/link/load shaders
// OpenGL helper routines
//
static GLuint _load_shaders(ShaderInfo *shaders) {
if (shaders == NULL) {
return 0;
static GLsizei _get_gl_type_size(GLenum type) {
switch (type) {
case GL_BYTE:
return sizeof(GLbyte);
case GL_UNSIGNED_BYTE:
return sizeof(GLubyte);
case GL_SHORT:
return sizeof(GLshort);
case GL_UNSIGNED_SHORT:
return sizeof(GLushort);
case GL_INT:
return sizeof(GLint);
case GL_UNSIGNED_INT:
return sizeof(GLuint);
case GL_FLOAT:
return sizeof(GLfloat);
}
GLuint program = glCreateProgram();
if (!program) {
GL_ERRLOG("glCreateProgram");
return 0;
}
ShaderInfo *entry = shaders;
while (entry->type != GL_NONE) {
GLuint shader = glCreateShader(entry->type);
entry->shader = shader;
if (!shader || !entry->source) {
for (entry = shaders; entry->type != GL_NONE; ++entry) {
glDeleteShader(entry->shader);
entry->shader = 0;
}
return 0;
}
glShaderSource(shader, 1, &entry->source, NULL);
glCompileShader( shader );
GL_ERRLOG("glCompileShader");
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLsizei len = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
GLchar* log = (GLchar*)malloc(sizeof(GLchar)*(len+1));
glGetShaderInfoLog(shader, len, &len, log);
ERRQUIT("Shader '%s' compilation failed: %s", entry->shadername, log);
free(log);
return 0;
}
glAttachShader(program, shader);
++entry;
}
glLinkProgram(program);
GL_ERRLOG("glLinkProgram");
GLint linked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) {
GLsizei len;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
GLchar* log = (GLchar*)malloc(sizeof(GLchar)*(len+1));
glGetProgramInfoLog(program, len, &len, log);
ERRQUIT("Shader '%s' linking failed: %s", entry->shadername, log);
free(log);
for (entry = shaders; entry->type != GL_NONE; ++entry) {
glDeleteShader(entry->shader);
entry->shader = 0;
}
return 0;
}
return program;
return 0;
}
static void _create_gl_program(void) {
ShaderInfo shaders[] = {
{ .type=GL_VERTEX_SHADER, .shadername="vertex shader", .source=vertexShader },
{ .type=GL_FRAGMENT_SHADER, .shadername="fragment shader", .source=fragmentShader },
{ .type=GL_NONE, .shadername=NULL, .source=NULL }
};
program = _load_shaders(shaders);
glUseProgram(program);
GL_ERRLOG("glUseProgram");
ShaderInfo *info = calloc(1, sizeof(ShaderInfo));
memcpy(info, &shaders[0], sizeof(ShaderInfo));
HASH_ADD_INT(allShaders, /*index*/shader, /*new node*/info);
info = calloc(1, sizeof(ShaderInfo));
memcpy(info, &shaders[1], sizeof(ShaderInfo));
HASH_ADD_INT(allShaders, /*index*/shader, /*new node*/info);
// TODO : other shader effects, for example NTSC noise, CRT glitches, pixel bloom, etc ...
}
//----------------------------------------------------------------------------
//
// generate/manage vertices for the Cathode Ray Tube object
//
static void _generate_crt_object(void) {
// TODO FIXME: use actual 3D CRT surface with vertices/indices dynamically generated based on
// screen dimensions / device DPI
if (crtDrawable.allocated) {
glDeleteBuffers(1, &crtDrawable.vertexBuffer);
glDeleteBuffers(1, &crtDrawable.indexBuffer);
crtDrawable.allocated = false;
}
static demoModel *_create_CRT_model() {
#define STRIDE 9*sizeof(GLfloat)
#define TEST_COLOR_OFF (GLvoid *)(3*sizeof(GLfloat))
#define TEX_COORD_OFF (GLvoid *)(7*sizeof(GLfloat))
// NOTE: vertices in Normalized Device Coordinates
const GLuint numverts = 6;
GLfloat vrt[] = {
-1.0, -1.0, 0.0, /*color*/1.0,1.0,1.0,1.0, /*interleaved tex coord:*/0.0, 1.0,// Triangle 1
1.0, -1.0, 0.0, /*color*/1.0,1.0,1.0,1.0, /*interleaved tex coord:*/1.0, 1.0,
-1.0, 1.0, 0.0, /*color*/1.0,1.0,1.0,1.0, /*interleaved tex coord:*/0.0, 0.0,
-1.0, 1.0, 0.0, /*color*/1.0,1.0,1.0,1.0, /*interleaved tex coord:*/0.0, 0.0,// Triangle 2
1.0, -1.0, 0.0, /*color*/1.0,1.0,1.0,1.0, /*interleaved tex coord:*/1.0, 1.0,
1.0, 1.0, 0.0, /*color*/1.0,1.0,1.0,1.0, /*interleaved tex coord:*/1.0, 0.0,
const GLfloat crt_positions[] = {
// CRT screen quad
-1.0, -1.0, 0.0, 1.0,
1.0, -1.0, 0.0, 1.0,
-1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 0.0, 1.0,
#if PERSPECTIVE
// CRT back side point
0.0, 0.0, -1.0, 1.0,
#endif
};
const GLuint numindices = 6;
const GLushort ind[] = {
0, 1, 2, 3, 4, 5
const GLfloat crt_texcoords[] = {
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
};
const GLushort indices[] = {
// CRT screen quad
0, 1, 2, 2, 1, 3
#if PERSPECTIVE
// ...
#endif
};
// Create VBO for the vertices
glGenBuffers(1, &crtDrawable.vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, crtDrawable.vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vrt), &vrt[0], GL_STATIC_DRAW);
GL_ERRLOG("vertex buffer setup");
demoModel *crt = calloc(1, sizeof(demoModel));
crt->numVertices = 4;
crt->numElements = 6;
// Create VBO for the indices
glGenBuffers(1, &crtDrawable.indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, crtDrawable.indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ind), &ind[0], GL_STATIC_DRAW);
GL_ERRLOG("element buffer setup");
crt->positions = malloc(sizeof(crt_positions));
memcpy(crt->positions, &crt_positions[0], sizeof(crt_positions));
crt->positionType = GL_FLOAT;
crt->positionSize = 4; // x,y,z coordinates
crt->positionArraySize = sizeof(crt_positions);
crtDrawable.vertexCount = numverts;
crtDrawable.indexCount = numindices;
crtDrawable.allocated = true;
crt->texcoords = malloc(sizeof(crt_texcoords));
memcpy(crt->texcoords, &crt_texcoords[0], sizeof(crt_texcoords));
crt->texcoordType = GL_FLOAT;
crt->texcoordSize = 2; // s,t coordinates
crt->texcoordArraySize = sizeof(crt_texcoords);
crt->normals = NULL;
crt->normalType = GL_NONE;
crt->normalSize = GL_NONE;
crt->normalArraySize = 0;
crt->elements = malloc(sizeof(indices));
memcpy(crt->elements, &indices[0], sizeof(indices));
crt->elementType = GL_UNSIGNED_SHORT;
crt->elementArraySize = sizeof(indices);
return crt;
}
//----------------------------------------------------------------------------
//
// initialization routines
//
static GLuint _create_VAO(demoModel *model) {
GLuint vaoName;
// Create a vertex array object (VAO) to cache model parameters
glGenVertexArrays(1, &vaoName);
glBindVertexArray(vaoName);
GLuint posBufferName;
// Create a vertex buffer object (VBO) to store positions and load data
glGenBuffers(1, &posBufferName);
glBindBuffer(GL_ARRAY_BUFFER, posBufferName);
glBufferData(GL_ARRAY_BUFFER, model->positionArraySize, model->positions, GL_STATIC_DRAW);
// Enable the position attribute for this VAO
glEnableVertexAttribArray(POS_ATTRIB_IDX);
// Get the size of the position type so we can set the stride properly
GLsizei posTypeSize = _get_gl_type_size(model->positionType);
// Set up parmeters for position attribute in the VAO including,
// size, type, stride, and offset in the currenly bound VAO
// This also attaches the position VBO to the VAO
glVertexAttribPointer(POS_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
model->positionSize, // How many elements are there per position?
model->positionType, // What is the type of this data?
GL_FALSE, // Do we want to normalize this data (0-1 range for fixed-pont types)
model->positionSize*posTypeSize, // What is the stride (i.e. bytes between positions)?
0); // What is the offset in the VBO to the position data?
if (model->normals) {
GLuint normalBufferName;
// Create a vertex buffer object (VBO) to store positions
glGenBuffers(1, &normalBufferName);
glBindBuffer(GL_ARRAY_BUFFER, normalBufferName);
// Allocate and load normal data into the VBO
glBufferData(GL_ARRAY_BUFFER, model->normalArraySize, model->normals, GL_STATIC_DRAW);
// Enable the normal attribute for this VAO
glEnableVertexAttribArray(NORMAL_ATTRIB_IDX);
// Get the size of the normal type so we can set the stride properly
GLsizei normalTypeSize = _get_gl_type_size(model->normalType);
// Set up parmeters for position attribute in the VAO including,
// size, type, stride, and offset in the currenly bound VAO
// This also attaches the position VBO to the VAO
glVertexAttribPointer(NORMAL_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
model->normalSize, // How many elements are there per normal?
model->normalType, // What is the type of this data?
GL_FALSE, // Do we want to normalize this data (0-1 range for fixed-pont types)
model->normalSize*normalTypeSize, // What is the stride (i.e. bytes between normals)?
0); // What is the offset in the VBO to the normal data?
}
if (model->texcoords) {
GLuint texcoordBufferName;
// Create a VBO to store texcoords
glGenBuffers(1, &texcoordBufferName);
glBindBuffer(GL_ARRAY_BUFFER, texcoordBufferName);
// Allocate and load texcoord data into the VBO
glBufferData(GL_ARRAY_BUFFER, model->texcoordArraySize, model->texcoords, GL_STATIC_DRAW);
// Enable the texcoord attribute for this VAO
glEnableVertexAttribArray(TEXCOORD_ATTRIB_IDX);
// Get the size of the texcoord type so we can set the stride properly
GLsizei texcoordTypeSize = _get_gl_type_size(model->texcoordType);
// Set up parmeters for texcoord attribute in the VAO including,
// size, type, stride, and offset in the currenly bound VAO
// This also attaches the texcoord VBO to VAO
glVertexAttribPointer(TEXCOORD_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
model->texcoordSize, // How many elements are there per texture coord?
model->texcoordType, // What is the type of this data in the array?
GL_TRUE, // Do we want to normalize this data (0-1 range for fixed-point types)
model->texcoordSize*texcoordTypeSize, // What is the stride (i.e. bytes between texcoords)?
0); // What is the offset in the VBO to the texcoord data?
}
GLuint elementBufferName;
// Create a VBO to vertex array elements
// This also attaches the element array buffer to the VAO
glGenBuffers(1, &elementBufferName);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferName);
// Allocate and load vertex array element data into VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, model->elementArraySize, model->elements, GL_STATIC_DRAW);
GL_ERRLOG("finished creating VAO/VBOs")
return vaoName;
}
static void _destroy_VAO(GLuint vaoName) {
GLuint index;
GLuint bufName;
// Bind the VAO so we can get data from it
glBindVertexArray(vaoName);
// For every possible attribute set in the VAO
for (index = 0; index < 16; index++) {
// Get the VBO set for that attibute
glGetVertexAttribiv(index , GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint*)&bufName);
// If there was a VBO set...
if (bufName) {
//...delete the VBO
glDeleteBuffers(1, &bufName);
}
}
// Get any element array VBO set in the VAO
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&bufName);
// If there was a element array VBO set in the VAO
if(bufName) {
//...delete the VBO
glDeleteBuffers(1, &bufName);
}
// Finally, delete the VAO
glDeleteVertexArrays(1, &vaoName);
GL_ERRLOG("destroying VAO/VBOs");
}
static GLuint _create_CRT_texture(void) {
GLuint texName;
// Create a texture object to apply to model
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
// Set up filter and wrap modes for this texture object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Indicate that pixel rows are tightly packed
// (defaults to stride of 4 which is kind of only good for
// RGBA or FLOAT data types)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Allocate and load image data into texture
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, SCANWIDTH, SCANHEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, NULL);
GL_ERRLOG("finished creating CRT texture");
return texName;
}
static GLuint _build_program(demoSource *vertexSource, demoSource *fragmentSource, bool hasNormal, bool hasTexcoord) {
GLuint prgName;
GLint logLength, status;
// String to pass to glShaderSource
GLchar *sourceString = NULL;
// Determine if GLSL version 140 is supported by this context.
// We'll use this info to generate a GLSL shader source string
// with the proper version preprocessor string prepended
float glLanguageVersion;
#if ESSENTIAL_GL_PRACTICES_IOS
sscanf((char *)glGetString(GL_SHADING_LANGUAGE_VERSION), "OpenGL ES GLSL ES %f", &glLanguageVersion);
#else
sscanf((char *)glGetString(GL_SHADING_LANGUAGE_VERSION), "%f", &glLanguageVersion);
#endif
// GL_SHADING_LANGUAGE_VERSION returns the version standard version form
// with decimals, but the GLSL version preprocessor directive simply
// uses integers (thus 1.10 should 110 and 1.40 should be 140, etc.)
// We multiply the floating point number by 100 to get a proper
// number for the GLSL preprocessor directive
GLuint version = 100 * glLanguageVersion;
// Get the size of the version preprocessor string info so we know
// how much memory to allocate for our sourceString
const GLsizei versionStringSize = sizeof("#version 123\n");
// Create a program object
prgName = glCreateProgram();
// Indicate the attribute indicies on which vertex arrays will be
// set with glVertexAttribPointer
// See buildVAO to see where vertex arrays are actually set
glBindAttribLocation(prgName, POS_ATTRIB_IDX, "inPosition");
if (hasNormal) {
glBindAttribLocation(prgName, NORMAL_ATTRIB_IDX, "inNormal");
}
if (hasTexcoord) {
glBindAttribLocation(prgName, TEXCOORD_ATTRIB_IDX, "inTexcoord");
}
//////////////////////////////////////
// Specify and compile VertexShader //
//////////////////////////////////////
// Allocate memory for the source string including the version preprocessor information
sourceString = malloc(vertexSource->byteSize + versionStringSize);
// Prepend our vertex shader source string with the supported GLSL version so
// the shader will work on ES, Legacy, and OpenGL 3.2 Core Profile contexts
sprintf(sourceString, "#version %d\n%s", version, vertexSource->string);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, (const GLchar **)&(sourceString), NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(vertexShader, logLength, &logLength, log);
LOG("Vtx Shader compile log:%s\n", log);
free(log);
}
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if (status == 0) {
LOG("Failed to compile vtx shader:\n%s\n", sourceString);
return 0;
}
free(sourceString);
sourceString = NULL;
// Attach the vertex shader to our program
glAttachShader(prgName, vertexShader);
// Delete the vertex shader since it is now attached
// to the program, which will retain a reference to it
glDeleteShader(vertexShader);
/////////////////////////////////////////
// Specify and compile Fragment Shader //
/////////////////////////////////////////
// Allocate memory for the source string including the version preprocessor information
sourceString = malloc(fragmentSource->byteSize + versionStringSize);
// Prepend our fragment shader source string with the supported GLSL version so
// the shader will work on ES, Legacy, and OpenGL 3.2 Core Profile contexts
sprintf(sourceString, "#version %d\n%s", version, fragmentSource->string);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, (const GLchar **)&(sourceString), NULL);
glCompileShader(fragShader);
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(fragShader, logLength, &logLength, log);
LOG("Frag Shader compile log:\n%s\n", log);
free(log);
}
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &status);
if (status == 0) {
LOG("Failed to compile frag shader:\n%s\n", sourceString);
return 0;
}
free(sourceString);
sourceString = NULL;
// Attach the fragment shader to our program
glAttachShader(prgName, fragShader);
// Delete the fragment shader since it is now attached
// to the program, which will retain a reference to it
glDeleteShader(fragShader);
//////////////////////
// Link the program //
//////////////////////
glLinkProgram(prgName);
glGetProgramiv(prgName, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*)malloc(logLength);
glGetProgramInfoLog(prgName, logLength, &logLength, log);
LOG("Program link log:\n%s\n", log);
free(log);
}
glGetProgramiv(prgName, GL_LINK_STATUS, &status);
if (status == 0) {
LOG("Failed to link program");
return 0;
}
glValidateProgram(prgName);
glGetProgramiv(prgName, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*)malloc(logLength);
glGetProgramInfoLog(prgName, logLength, &logLength, log);
LOG("Program validate log:\n%s\n", log);
free(log);
}
glGetProgramiv(prgName, GL_VALIDATE_STATUS, &status);
if (status == 0) {
LOG("Failed to validate program");
return 0;
}
glUseProgram(prgName);
///////////////////////////////////////
// Setup common program input points //
///////////////////////////////////////
GLint samplerLoc = glGetUniformLocation(prgName, "diffuseTexture");
// Indicate that the diffuse texture will be bound to texture unit 0
GLint unit = 0;
glUniform1i(samplerLoc, unit);
GL_ERRLOG("build program");
return prgName;
}
static demoSource *_create_shader_source(const char *fileName) {
demoSource *src = NULL;
#ifdef __APPLE__
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFStringRef fileString = CFStringCreateWithCString(/*allocator*/NULL, fileName, CFStringGetSystemEncoding());
CFURLRef fileURL = CFBundleCopyResourceURL(mainBundle, fileString, NULL, NULL);
CFRELEASE(fileString);
CFStringRef filePath = CFURLCopyFileSystemPath(fileURL, kCFURLPOSIXPathStyle);
CFRELEASE(fileURL);
src = srcLoadSource(CFStringGetCStringPtr(filePath, CFStringGetSystemEncoding()));
CFRELEASE(filePath);
#else
#error FIXME TODO need to leveage GNU build system install_dir or somesuch stuff ...
#endif
return src;
}
static void gldriver_init_common(void) {
LOG("%s %s", glGetString(GL_RENDERER), glGetString(GL_VERSION));
_generate_crt_object();
viewportWidth = 400;
viewportHeight = 400;
_create_gl_program();
// ----------------------------
// Create CRT model VAO/VBOs
// Extract the handles to attributes and uniforms
attributes.position = glGetAttribLocation(program, "Position");
GL_ERRLOG("glGetAttribLocation");
#if DEBUG_GEOMETRY
attributes.testColor = glGetAttribLocation(program, "TestColor");
GL_ERRQUIT("cannot get TestColor attribute location for DEBUG_GEOMETRY preprocessor configuration");
#endif
attributes.texCoord = glGetAttribLocation(program, "TextureCoord");
uniforms.projection = glGetUniformLocation(program, "Projection");
LOG("projection = %d", uniforms.projection);
uniforms.modelview = glGetUniformLocation(program, "Modelview");
LOG("modelview = %d", uniforms.modelview);
uniforms.sourceColor = glGetUniformLocation(program, "SourceColor");
LOG("sourceColor = %d", uniforms.sourceColor);
// create CRT model
demoModel *crtModel = _create_CRT_model();
// Set up to use Apple //e framebuffer as texture
glGenTextures(1, &a2framebufferTexture);
GL_ERRLOG("glGenTextures");
glBindTexture(GL_TEXTURE_2D, a2framebufferTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*GL_NEAREST*/);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR/*GL_NEAREST*/);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Build Vertex Buffer Objects (VBOs) and Vertex Array Object (VAOs) with our model data
crtVAOName = _create_VAO(crtModel);
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, windowWidth, windowHeight, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, 0);
GL_ERRLOG("glTexImage2D");
// Cache the number of element and primType to use later in our glDrawElements calls
crtNumElements = crtModel->numElements;
crtElementType = crtModel->elementType;
// Initialize various state
glEnableVertexAttribArray(attributes.position);
GL_ERRLOG("glEnableVertexAttribArray");
#if DEBUG_GEOMETRY
glEnableVertexAttribArray(attributes.testColor);
GL_ERRLOG("glEnableVertexAttribArray");
#endif
glEnableVertexAttribArray(attributes.texCoord);
GL_ERRLOG("glEnableVertexAttribArray");
// We're using VBOs we can destroy all this memory since buffers are
// loaded into GL and we've saved anything else we need
mdlDestroyModel(crtModel);
crtModel = NULL;
//glEnable(GL_DEPTH_TEST);
glClearColor(0.2, 0.2f, 0.2f, 1);
// Build a default texture object with our image data
a2TextureName = _create_CRT_texture();
#if 0
// Set up transforms
translation = mat4_translate_xyz(0.f, 0.f, -7.f, MAT4);
#endif
// ----------------------------
// Load/setup shaders
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
ERRQUIT("framebuffer status: %04X", status);
demoSource *vtxSource = _create_shader_source("Basic.vert");
demoSource *frgSource = _create_shader_source("Basic.frag");
// Build Program
program = _build_program(vtxSource, frgSource, /*withNormal:*/false, /*withTexcoord:*/true);
glUseProgram(program);
srcDestroySource(vtxSource);
srcDestroySource(frgSource);
uniformMVPIdx = glGetUniformLocation(program, "modelViewProjectionMatrix");
if (uniformMVPIdx < 0) {
LOG("No modelViewProjectionMatrix in character shader");
}
// ----------------------------
// setup static OpenGL state
// Depth test will always be enabled
glEnable(GL_DEPTH_TEST);
// We will always cull back faces for better performance
glEnable(GL_CULL_FACE);
// Always use this clear color
glClearColor(0.5f, 0.4f, 0.5f, 1.0f);
// Draw our scene once without presenting the rendered image.
// This is done in order to pre-warm OpenGL
// We don't need to present the buffer since we don't actually want the
// user to see this, we're only drawing as a pre-warm stage
video_driver_render();
// Check for errors to make sure all of our setup went ok
GL_ERRLOG("finished initialization");
}
static void gldriver_shutdown(void) {
// Cleanup all OpenGL objects
glDeleteTextures(1, &a2TextureName);
_destroy_VAO(crtVAOName);
glDeleteProgram(program);
}
//----------------------------------------------------------------------------
//
// update, display, reshape
// update, render, reshape
//
static void gldriver_update(void) {
#if !defined(__APPLE__)
// HACK MAYBE FIXME : pumps the joystick sampling code that is currently integrated into the keys routine
c_keys_handle_input(-1, 0, 0);
#endif
#if USE_GLUT
glutPostRedisplay();
#endif
}
static void gldriver_display(void) {
static void gldriver_render(void) {
if (is_headless) {
return;
}
glClear(GL_COLOR_BUFFER_BIT/*| GL_DEPTH_BUFFER_BIT*/);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set the viewport transform.
glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
// Set the source color
GLfloat sourceColor[] = { 1.f, 1.f, 1.f, 1.f };
glUniform4fv(uniforms.sourceColor, 1, &sourceColor[0]);
GL_ERRQUIT("glUniform4fv");
#if 0
// Set the model-view transform.
matT rotation = mat_identity();
matT modelview = mat_mult_mat(rotation, translation, MAT4);
glUniformMatrix4fv(uniforms.modelview, 1, 0, MAT_POINTER(modelview));
GL_ERRQUIT("glUniformMatrix4fv");
// Set the projection transform.
float h = 4.0f * windowHeight / windowWidth;
matT projectionMatrix = mat4_frustum(-2, 2, -h / 2, h / 2, 5, 10);
glUniformMatrix4fv(uniforms.projection, 1, 0, MAT_POINTER(projectionMatrix));
GL_ERRQUIT("glUniformMatrix4fv");
#if PERSPECTIVE
// Calculate modelview and projection matrices
GLfloat modelView[16];
GLfloat projection[16];
mtxLoadPerspective(projection, 90, (float)viewportWidth / (float)viewportHeight, 5.0, 10000);
#endif
// texture ...
// Calculate the modelview matrix to render our character
// at the proper position and rotation
GLfloat mvp[16];
#if PERSPECTIVE
// Create model-view-projection matrix
//mtxLoadTranslate(modelView, 0, 150, -450);
//mtxRotateXApply(modelView, -90.0f);
//mtxRotateApply(modelView, -45.0f, 0.7, 0.3, 1);
mtxMultiply(mvp, projection, modelView);
#else
// Just load an identity matrix for a pure orthographic/non-perspective viewing
mtxLoadIdentity(mvp);
#endif
// Have our shader use the modelview projection matrix
// that we calculated above
glUniformMatrix4fv(uniformMVPIdx, 1, GL_FALSE, mvp);
// Update texture from Apple //e internal framebuffer
const uint8_t * const fb = video_current_framebuffer();
uint8_t index;
#warning FIXME TODO use memcpy?
unsigned int count = SCANWIDTH * SCANHEIGHT;
char pixels[SCANWIDTH * SCANHEIGHT * 4];
for (unsigned int i=0, j=0; i<count; i++, j+=4) {
index = *(fb + i);
*( (uint32_t*)(pixels + j) ) = (uint32_t)(
((uint32_t)(colormap[index].red) << 0 ) |
((uint32_t)(colormap[index].green) << 8 ) |
((uint32_t)(colormap[index].blue) << 16) |
((uint32_t)0xff << 24)
);
if (fb != NULL) {
for (unsigned int i=0, j=0; i<count; i++, j+=4) {
index = *(fb + i);
*( (uint32_t*)(pixels + j) ) = (uint32_t)(
((uint32_t)(colormap[index].red) << 0 ) |
((uint32_t)(colormap[index].green) << 8 ) |
((uint32_t)(colormap[index].blue) << 16) |
((uint32_t)0xff << 24)
);
}
}
glBindTexture(GL_TEXTURE_2D, a2framebufferTexture);
#if 0
int width, height;
void *test_pixels = test_texture(&width, &height);
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, width, height, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, test_pixels);
#else
glBindTexture(GL_TEXTURE_2D, a2TextureName);
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, SCANWIDTH, SCANHEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)&pixels[0]);
#endif
GL_ERRLOG("glTexImage2D");
glGetError();
// Draw the CRT object and the apple2 framebuffer as a texture
glBindBuffer(GL_ARRAY_BUFFER, crtDrawable.vertexBuffer);
glVertexAttribPointer(attributes.position, 3, GL_FLOAT, GL_FALSE, STRIDE, 0);
#if DEBUG_GEOMETRY
glVertexAttribPointer(attributes.testColor, 4, GL_FLOAT, GL_FALSE, STRIDE, TEST_COLOR_OFF);
#endif
glVertexAttribPointer(attributes.texCoord, 2, GL_FLOAT, GL_FALSE, STRIDE, TEX_COORD_OFF);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, crtDrawable.indexBuffer);
glDrawElements(GL_TRIANGLES, crtDrawable.indexCount, GL_UNSIGNED_SHORT, 0);
GL_ERRLOG("glDrawElements");
// Bind our vertex array object
glBindVertexArray(crtVAOName);
glutSwapBuffers();
// Cull back faces now that we no longer render
// with an inverted matrix
glCullFace(GL_BACK);
// Draw the CRT object
glDrawElements(GL_TRIANGLES, crtNumElements, crtElementType, 0);
}
static void gldriver_reshape(int w, int h) {
LOG("reshape to w:%d h:%d", w, h);
//LOG("reshape to w:%d h:%d", w, h);
windowWidth = w;
windowHeight = h;
@ -373,34 +649,28 @@ static void gldriver_reshape(int w, int h) {
viewportY = 0;
viewportWidth = w2;
viewportHeight = h;
LOG("OK1 : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
//LOG("OK1 : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
} else if (h2 <= h) {
viewportX = 0;
viewportY = (h-h2)/2;
viewportWidth = w;
viewportHeight = h2;
LOG("OK2 : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
//LOG("OK2 : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
} else {
viewportX = 0;
viewportY = 0;
viewportWidth = w;
viewportHeight = h;
LOG("small viewport : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
//LOG("small viewport : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
}
glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
}
//----------------------------------------------------------------------------
void video_set_mode(a2_video_mode_t mode) {
// no-op ...
}
void video_driver_init(void) {
#if defined(__APPLE__)
gldriver_init_common();
#else
#if USE_GLUT
static void _init_with_glut(GLuint fbo) {
glutInit(&argc, argv);
glutInitDisplayMode(/*GLUT_DOUBLE|*/GLUT_RGBA/*|GLUT_DEPTH*/);
glutInitDisplayMode(/*GLUT_DOUBLE|*/GLUT_RGBA|GLUT_DEPTH);
glutInitWindowSize(windowWidth, windowHeight);
//glutInitContextVersion(4, 0); -- Is this needed?
glutInitContextProfile(GLUT_CORE_PROFILE);
@ -414,7 +684,7 @@ void video_driver_init(void) {
gldriver_init_common();
glutIdleFunc(gldriver_update);
glutDisplayFunc(gldriver_display);
glutDisplayFunc(gldriver_render);
glutReshapeFunc(gldriver_reshape);
//glutMouseFunc(gldriver_mouse);
//glutMotionFunc(gldriver_mouse_drag);
@ -425,21 +695,46 @@ void video_driver_init(void) {
glutSpecialFunc(gldriver_on_key_special_down);
glutSpecialUpFunc(gldriver_on_key_special_up);
#endif
#endif // !__APPLE__
}
#endif
//----------------------------------------------------------------------------
// renderer API
void video_driver_init(void *fbo) {
defaultFBO = (GLuint)fbo;
#if defined(__APPLE__)
gldriver_init_common();
#elif USE_GLUT
gldriver_init_glut();
#else
#error no working codepaths
#endif
}
void video_driver_main_loop(void) {
#if USE_GLUT
glutMainLoop();
#endif
}
void video_driver_render(void) {
gldriver_render();
}
void video_driver_reshape(int w, int h) {
gldriver_reshape(w, h);
}
void video_driver_sync(void) {
if (is_headless) {
return;
}
#if USE_GLUT
glutPostRedisplay();
#endif
}
void video_driver_shutdown(void) {
// FIXME TODO ...
gldriver_shutdown();
}

18
src/video/renderer.h Normal file
View File

@ -0,0 +1,18 @@
/*
* Apple // emulator for *nix
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
// glvideo -- Created by Aaron Culliney
void video_driver_init(void *context);
void video_driver_main_loop(void);
void video_driver_reshape(int width, int height);
void video_driver_render(void);
void video_driver_shutdown(void);

View File

@ -14,8 +14,14 @@
// #define USE_GL3W
#if defined(__APPLE__)
# include <OpenGLES/ES2/gl.h>
# include <OpenGLES/ES2/glext.h>
# include <TargetConditionals.h>
# if TARGET_OS_MAC
# include <OpenGL/OpenGL.h>
# include <OpenGL/gl3.h>
# else
# include <OpenGLES/ES2/gl.h>
# include <OpenGLES/ES2/glext.h>
# endif
#elif defined(USE_GL3W)
# include <GL3/gl3.h>
# include <GL3/gl3w.h>

View File

@ -109,8 +109,6 @@ void video_loadfont_int(int first, int qty, const uint8_t *data);
*/
void video_plotchar(int row, int col, int color, uint8_t code);
void video_set_mode(a2_video_mode_t mode);
/*
* Get a reference to current internal framebuffer
*/

View File

@ -430,7 +430,7 @@ static void c_flash_cursor(int on) {
}
}
void video_driver_sync(void) {
static void video_driver_sync(void) {
if (is_headless) {
return;
}
@ -676,7 +676,7 @@ void video_set_mode(a2_video_mode_t mode) {
_size_hints_set_fixed();
}
void video_driver_init() {
void video_driver_init(void *context) {
XSetWindowAttributes attribs;
unsigned long attribmask;
int x, y; /* window position */

145
src/video_util/glUtil.h Normal file
View File

@ -0,0 +1,145 @@
/*
File: glUtil.h
Abstract:
Includes the appropriate OpenGL headers (depending on whether this
is built for iOS or OSX) and provides some API utility functions
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#ifndef __GL_UTIL_H__
#define __GL_UTIL_H__
#if ESSENTIAL_GL_PRACTICES_IOS
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#else
#import <OpenGL/OpenGL.h>
// OpenGL 3.2 is only supported on MacOS X Lion and later
// CGL_VERSION_1_3 is defined as 1 on MacOS X Lion and later
#if CGL_VERSION_1_3
// Set to 0 to run on the Legacy OpenGL Profile
#define ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 1
#else
#define ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 0
#endif //!CGL_VERSION_1_3
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#import <OpenGL/gl3.h>
#else
#import <OpenGL/gl.h>
#endif //!ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#endif // !ESSENTIAL_GL_PRACTICES_IOS
//The name of the VertexArrayObject are slightly different in
// OpenGLES, OpenGL Core Profile, and OpenGL Legacy
// The arguments are exactly the same across these APIs however
#if ESSENTIAL_GL_PRACTICES_IOS
#define glBindVertexArray glBindVertexArrayOES
#define glGenVertexArrays glGenVertexArraysOES
#define glDeleteVertexArrays glDeleteVertexArraysOES
#else
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#define glBindVertexArray glBindVertexArray
#define glGenVertexArrays glGenVertexArrays
#define glGenerateMipmap glGenerateMipmap
#define glDeleteVertexArrays glDeleteVertexArrays
#else
#define glBindVertexArray glBindVertexArrayAPPLE
#define glGenVertexArrays glGenVertexArraysAPPLE
#define glGenerateMipmap glGenerateMipmapEXT
#define glDeleteVertexArrays glDeleteVertexArraysAPPLE
#endif //!ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#endif //!ESSENTIAL_GL_PRACTICES_IOS
static inline const char * GetGLErrorString(GLenum error)
{
const char *str;
switch( error )
{
case GL_NO_ERROR:
str = "GL_NO_ERROR";
break;
case GL_INVALID_ENUM:
str = "GL_INVALID_ENUM";
break;
case GL_INVALID_VALUE:
str = "GL_INVALID_VALUE";
break;
case GL_INVALID_OPERATION:
str = "GL_INVALID_OPERATION";
break;
#if defined __gl_h_ || defined __gl3_h_
case GL_OUT_OF_MEMORY:
str = "GL_OUT_OF_MEMORY";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
str = "GL_INVALID_FRAMEBUFFER_OPERATION";
break;
#endif
#if defined __gl_h_
case GL_STACK_OVERFLOW:
str = "GL_STACK_OVERFLOW";
break;
case GL_STACK_UNDERFLOW:
str = "GL_STACK_UNDERFLOW";
break;
case GL_TABLE_TOO_LARGE:
str = "GL_TABLE_TOO_LARGE";
break;
#endif
default:
str = "(ERROR: Unknown Error Enum)";
break;
}
return str;
}
#endif // __GL_UTIL_H__

View File

@ -0,0 +1,75 @@
/*
File: imageUtil.h
Abstract:
Functions for loading an image files for textures.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#ifndef __IMAGE_UTIL_H__
#define __IMAGE_UTIL_H__
#include "glUtil.h"
typedef struct demoImageRec
{
GLubyte* data;
GLsizei size;
GLuint width;
GLuint height;
GLenum format;
GLenum type;
GLuint rowByteSize;
} demoImage;
demoImage* imgLoadImage(const char* filepathname, int flipVertical);
void imgDestroyImage(demoImage* image);
#endif //__IMAGE_UTIL_H__

116
src/video_util/imageUtil.m Normal file
View File

@ -0,0 +1,116 @@
/*
File: imageUtil.m
Abstract:
Functions for loading an image files for textures.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#include "imageUtil.h"
#if ESSENTIAL_GL_PRACTICES_IOS
#import <UIKit/UIKit.h>
#else
#import <Cocoa/Cocoa.h>
#endif
demoImage* imgLoadImage(const char* filepathname, int flipVertical)
{
NSString *filepathString = [[NSString alloc] initWithUTF8String:filepathname];
#if ESSENTIAL_GL_PRACTICES_IOS
UIImage* imageClass = [[UIImage alloc] initWithContentsOfFile:filepathString];
#else
NSImage *nsimage = [[NSImage alloc] initWithContentsOfFile: filepathString];
NSBitmapImageRep *imageClass = [[NSBitmapImageRep alloc] initWithData:[nsimage TIFFRepresentation]];
[nsimage release];
#endif
CGImageRef cgImage = imageClass.CGImage;
if (!cgImage)
{
[filepathString release];
[imageClass release];
return NULL;
}
demoImage* image = malloc(sizeof(demoImage));
image->width = CGImageGetWidth(cgImage);
image->height = CGImageGetHeight(cgImage);
image->rowByteSize = image->width * 4;
image->data = malloc(image->height * image->rowByteSize);
image->format = GL_RGBA;
image->type = GL_UNSIGNED_BYTE;
CGContextRef context = CGBitmapContextCreate(image->data, image->width, image->height, 8, image->rowByteSize, CGImageGetColorSpace(cgImage), kCGImageAlphaNoneSkipLast);
CGContextSetBlendMode(context, kCGBlendModeCopy);
if(flipVertical)
{
CGContextTranslateCTM(context, 0.0, image->height);
CGContextScaleCTM(context, 1.0, -1.0);
}
CGContextDrawImage(context, CGRectMake(0.0, 0.0, image->width, image->height), cgImage);
CGContextRelease(context);
if(NULL == image->data)
{
[filepathString release];
[imageClass release];
imgDestroyImage(image);
return NULL;
}
[filepathString release];
[imageClass release];
return image;
}
void imgDestroyImage(demoImage* image)
{
free(image->data);
free(image);
}

990
src/video_util/matrixUtil.c Normal file
View File

@ -0,0 +1,990 @@
/*
File: matrixUtil.c
Abstract:
Functions for performing matrix math.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#include "matrixUtil.h"
#include "vectorUtil.h"
#include <math.h>
#include <memory.h>
void mtxMultiply(float* ret, const float* lhs, const float* rhs)
{
// [ 0 4 8 12 ] [ 0 4 8 12 ]
// [ 1 5 9 13 ] x [ 1 5 9 13 ]
// [ 2 6 10 14 ] [ 2 6 10 14 ]
// [ 3 7 11 15 ] [ 3 7 11 15 ]
ret[ 0] = lhs[ 0]*rhs[ 0] + lhs[ 4]*rhs[ 1] + lhs[ 8]*rhs[ 2] + lhs[12]*rhs[ 3];
ret[ 1] = lhs[ 1]*rhs[ 0] + lhs[ 5]*rhs[ 1] + lhs[ 9]*rhs[ 2] + lhs[13]*rhs[ 3];
ret[ 2] = lhs[ 2]*rhs[ 0] + lhs[ 6]*rhs[ 1] + lhs[10]*rhs[ 2] + lhs[14]*rhs[ 3];
ret[ 3] = lhs[ 3]*rhs[ 0] + lhs[ 7]*rhs[ 1] + lhs[11]*rhs[ 2] + lhs[15]*rhs[ 3];
ret[ 4] = lhs[ 0]*rhs[ 4] + lhs[ 4]*rhs[ 5] + lhs[ 8]*rhs[ 6] + lhs[12]*rhs[ 7];
ret[ 5] = lhs[ 1]*rhs[ 4] + lhs[ 5]*rhs[ 5] + lhs[ 9]*rhs[ 6] + lhs[13]*rhs[ 7];
ret[ 6] = lhs[ 2]*rhs[ 4] + lhs[ 6]*rhs[ 5] + lhs[10]*rhs[ 6] + lhs[14]*rhs[ 7];
ret[ 7] = lhs[ 3]*rhs[ 4] + lhs[ 7]*rhs[ 5] + lhs[11]*rhs[ 6] + lhs[15]*rhs[ 7];
ret[ 8] = lhs[ 0]*rhs[ 8] + lhs[ 4]*rhs[ 9] + lhs[ 8]*rhs[10] + lhs[12]*rhs[11];
ret[ 9] = lhs[ 1]*rhs[ 8] + lhs[ 5]*rhs[ 9] + lhs[ 9]*rhs[10] + lhs[13]*rhs[11];
ret[10] = lhs[ 2]*rhs[ 8] + lhs[ 6]*rhs[ 9] + lhs[10]*rhs[10] + lhs[14]*rhs[11];
ret[11] = lhs[ 3]*rhs[ 8] + lhs[ 7]*rhs[ 9] + lhs[11]*rhs[10] + lhs[15]*rhs[11];
ret[12] = lhs[ 0]*rhs[12] + lhs[ 4]*rhs[13] + lhs[ 8]*rhs[14] + lhs[12]*rhs[15];
ret[13] = lhs[ 1]*rhs[12] + lhs[ 5]*rhs[13] + lhs[ 9]*rhs[14] + lhs[13]*rhs[15];
ret[14] = lhs[ 2]*rhs[12] + lhs[ 6]*rhs[13] + lhs[10]*rhs[14] + lhs[14]*rhs[15];
ret[15] = lhs[ 3]*rhs[12] + lhs[ 7]*rhs[13] + lhs[11]*rhs[14] + lhs[15]*rhs[15];}
void mtxLoadPerspective(float* mtx, float fov, float aspect, float nearZ, float farZ)
{
float f = 1.0f / tanf( (fov * (M_PI/180)) / 2.0f);
mtx[0] = f / aspect;
mtx[1] = 0.0f;
mtx[2] = 0.0f;
mtx[3] = 0.0f;
mtx[4] = 0.0f;
mtx[5] = f;
mtx[6] = 0.0f;
mtx[7] = 0.0f;
mtx[8] = 0.0f;
mtx[9] = 0.0f;
mtx[10] = (farZ+nearZ) / (nearZ-farZ);
mtx[11] = -1.0f;
mtx[12] = 0.0f;
mtx[13] = 0.0f;
mtx[14] = 2 * farZ * nearZ / (nearZ-farZ);
mtx[15] = 0.0f;
}
void mtxLoadOrthographic(float* mtx,
float left, float right,
float bottom, float top,
float nearZ, float farZ)
{
//See appendix G of OpenGL Red Book
mtx[ 0] = 2.0f / (right - left);
mtx[ 1] = 0.0;
mtx[ 2] = 0.0;
mtx[ 3] = 0.0;
mtx[ 4] = 0.0;
mtx[ 5] = 2.0f / (top - bottom);
mtx[ 6] = 0.0;
mtx[ 7] = 0.0;
mtx[ 8] = 0.0;
mtx[ 9] = 0.0;
mtx[10] = -2.0f / (farZ - nearZ);
mtx[11] = 0.0;
mtx[12] = -(right + left) / (right - left);
mtx[13] = -(top + bottom) / (top - bottom);
mtx[14] = -(farZ + nearZ) / (farZ - nearZ);
mtx[15] = 1.0f;
}
static inline float sgn(float val)
{
return (val > 0.0f) ? 1.0f : ((val < 0.0f) ? -1.0f : 0.0f);
}
void mtxModifyObliqueProjection(float* mtx, const float* src, const float* plane)
{
float vec[4];
memcpy(mtx, src, 16 * sizeof(float));
vec[0] = (sgn(plane[0]) + mtx[8]) / mtx[0];
vec[1] = (sgn(plane[1]) + mtx[9]) / mtx[5];
vec[2] = -1.0f;
vec[3] = (1.0f + mtx[10]) / mtx[14];
float dot = vec4DotProduct(plane, vec);
vec[0] = plane[0] * (2.0f / dot);
vec[1] = plane[1] * (2.0f / dot);
vec[2] = plane[2] * (2.0f / dot);
vec[3] = plane[3] * (2.0f / dot);
// Replace the third row of the projection matrix
mtx[ 2] = vec[0];
mtx[ 6] = vec[1];
mtx[10] = vec[2];
mtx[14] = vec[3];
}
void mtxTranspose(float* mtx, const float* src)
{
//Use a temp to swap in case mtx == src
float tmp;
mtx[0] = src[0];
mtx[5] = src[5];
mtx[10] = src[10];
mtx[15] = src[15];
tmp = src[4];
mtx[4] = src[1];
mtx[1] = tmp;
tmp = src[8];
mtx[8] = src[2];
mtx[2] = tmp;
tmp = src[12];
mtx[12] = src[3];
mtx[3] = tmp;
tmp = src[9];
mtx[9] = src[6];
mtx[6] = tmp;
tmp = src[13];
mtx[13] = src[7];
mtx[ 7] = tmp;
tmp = src[14];
mtx[14] = src[11];
mtx[11] = tmp;
}
void mtxInvert(float* mtx, const float* src)
{
float tmp[16];
float val, val2, val_inv;
int i, j, i4, i8, i12, ind;
mtxTranspose(tmp, src);
mtxLoadIdentity(mtx);
for(i = 0; i != 4; i++)
{
val = tmp[(i << 2) + i];
ind = i;
i4 = i + 4;
i8 = i + 8;
i12 = i + 12;
for (j = i + 1; j != 4; j++)
{
if(fabsf(tmp[(i << 2) + j]) > fabsf(val))
{
ind = j;
val = tmp[(i << 2) + j];
}
}
if(ind != i)
{
val2 = mtx[i];
mtx[i] = mtx[ind];
mtx[ind] = val2;
val2 = tmp[i];
tmp[i] = tmp[ind];
tmp[ind] = val2;
ind += 4;
val2 = mtx[i4];
mtx[i4] = mtx[ind];
mtx[ind] = val2;
val2 = tmp[i4];
tmp[i4] = tmp[ind];
tmp[ind] = val2;
ind += 4;
val2 = mtx[i8];
mtx[i8] = mtx[ind];
mtx[ind] = val2;
val2 = tmp[i8];
tmp[i8] = tmp[ind];
tmp[ind] = val2;
ind += 4;
val2 = mtx[i12];
mtx[i12] = mtx[ind];
mtx[ind] = val2;
val2 = tmp[i12];
tmp[i12] = tmp[ind];
tmp[ind] = val2;
}
if(val == 0)
{
mtxLoadIdentity(mtx);
return;
}
val_inv = 1.0f / val;
tmp[i] *= val_inv;
mtx[i] *= val_inv;
tmp[i4] *= val_inv;
mtx[i4] *= val_inv;
tmp[i8] *= val_inv;
mtx[i8] *= val_inv;
tmp[i12] *= val_inv;
mtx[i12] *= val_inv;
if(i != 0)
{
val = tmp[i << 2];
tmp[0] -= tmp[i] * val;
mtx[0] -= mtx[i] * val;
tmp[4] -= tmp[i4] * val;
mtx[4] -= mtx[i4] * val;
tmp[8] -= tmp[i8] * val;
mtx[8] -= mtx[i8] * val;
tmp[12] -= tmp[i12] * val;
mtx[12] -= mtx[i12] * val;
}
if(i != 1)
{
val = tmp[(i << 2) + 1];
tmp[1] -= tmp[i] * val;
mtx[1] -= mtx[i] * val;
tmp[5] -= tmp[i4] * val;
mtx[5] -= mtx[i4] * val;
tmp[9] -= tmp[i8] * val;
mtx[9] -= mtx[i8] * val;
tmp[13] -= tmp[i12] * val;
mtx[13] -= mtx[i12] * val;
}
if(i != 2)
{
val = tmp[(i << 2) + 2];
tmp[2] -= tmp[i] * val;
mtx[2] -= mtx[i] * val;
tmp[6] -= tmp[i4] * val;
mtx[6] -= mtx[i4] * val;
tmp[10] -= tmp[i8] * val;
mtx[10] -= mtx[i8] * val;
tmp[14] -= tmp[i12] * val;
mtx[14] -= mtx[i12] * val;
}
if(i != 3)
{
val = tmp[(i << 2) + 3];
tmp[3] -= tmp[i] * val;
mtx[3] -= mtx[i] * val;
tmp[7] -= tmp[i4] * val;
mtx[7] -= mtx[i4] * val;
tmp[11] -= tmp[i8] * val;
mtx[11] -= mtx[i8] * val;
tmp[15] -= tmp[i12] * val;
mtx[15] -= mtx[i12] * val;
}
}
}
void mtxLoadIdentity(float* mtx)
{
// [ 0 4 8 12 ]
// [ 1 5 9 13 ]
// [ 2 6 10 14 ]
// [ 3 7 11 15 ]
mtx[ 0] = mtx[ 5] = mtx[10] = mtx[15] = 1.0f;
mtx[ 1] = mtx[ 2] = mtx[ 3] = mtx[ 4] =
mtx[ 6] = mtx[ 7] = mtx[ 8] = mtx[ 9] =
mtx[11] = mtx[12] = mtx[13] = mtx[14] = 0.0;
}
void mtxLoadTranslate(float* mtx, float xTrans, float yTrans, float zTrans)
{
// [ 0 4 8 x ]
// [ 1 5 9 y ]
// [ 2 6 10 z ]
// [ 3 7 11 15 ]
mtx[ 0] = mtx[ 5] = mtx[10] = mtx[15] = 1.0f;
mtx[ 1] = mtx[ 2] = mtx[ 3] = mtx[ 4] =
mtx[ 6] = mtx[ 7] = mtx[ 8] = mtx[ 9] =
mtx[11] = 0.0;
mtx[12] = xTrans;
mtx[13] = yTrans;
mtx[14] = zTrans;
}
void mtxLoadScale(float* mtx, float xScale, float yScale, float zScale)
{
// [ x 4 8 12 ]
// [ 1 y 9 13 ]
// [ 2 6 z 14 ]
// [ 3 7 11 15 ]
mtx[ 0] = xScale;
mtx[ 5] = yScale;
mtx[10] = zScale;
mtx[15] = 1.0f;
mtx[ 1] = mtx[ 2] = mtx[ 3] = mtx[ 4] =
mtx[ 6] = mtx[ 7] = mtx[ 8] = mtx[ 9] =
mtx[11] = mtx[12] = mtx[13] = mtx[14] = 0.0;
}
void mtxLoadRotateX(float* mtx, float rad)
{
// [ 0 4 8 12 ]
// [ 1 cos -sin 13 ]
// [ 2 sin cos 14 ]
// [ 3 7 11 15 ]
mtx[10] = mtx[ 5] = cosf(rad);
mtx[ 6] = sinf(rad);
mtx[ 9] = -mtx[ 6];
mtx[ 0] = mtx[15] = 1.0f;
mtx[ 1] = mtx[ 2] = mtx[ 3] = mtx[ 4] =
mtx[ 7] = mtx[ 8] = mtx[11] = mtx[12] =
mtx[13] = mtx[14] = 0.0;
}
void mtxLoadRotateY(float* mtx, float rad)
{
// [ cos 4 -sin 12 ]
// [ 1 5 9 13 ]
// [ sin 6 cos 14 ]
// [ 3 7 11 15 ]
mtx[ 0] = mtx[10] = cosf(rad);
mtx[ 2] = sinf(rad);
mtx[ 8] = -mtx[2];
mtx[ 5] = mtx[15] = 1.0;
mtx[ 1] = mtx[ 3] = mtx[ 4] = mtx[ 6] =
mtx[ 7] = mtx[ 9] = mtx[11] = mtx[12] =
mtx[13] = mtx[14] = 0.0;
}
void mtxLoadRotateZ(float* mtx, float rad)
{
// [ cos -sin 8 12 ]
// [ sin cos 9 13 ]
// [ 2 6 10 14 ]
// [ 3 7 11 15 ]
mtx[ 0] = mtx[ 5] = cosf(rad);
mtx[ 1] = sinf(rad);
mtx[ 4] = -mtx[1];
mtx[10] = mtx[15] = 1.0;
mtx[ 2] = mtx[ 3] = mtx[ 6] = mtx[ 7] =
mtx[ 8] = mtx[ 9] = mtx[11] = mtx[12] =
mtx[13] = mtx[14] = 0.0;
}
void mtxLoadRotate(float* mtx, float deg, float xAxis, float yAxis, float zAxis)
{
float rad = deg * M_PI/180.0f;
float sin_a = sinf(rad);
float cos_a = cosf(rad);
// Calculate coeffs. No need to check for zero magnitude because we wouldn't be here.
float magnitude = sqrtf(xAxis * xAxis + yAxis * yAxis + zAxis * zAxis);
float p = 1.0f / magnitude;
float cos_am = 1.0f - cos_a;
float xp = xAxis * p;
float yp = yAxis * p;
float zp = zAxis * p;
float xx = xp * xp;
float yy = yp * yp;
float zz = zp * zp;
float xy = xp * yp * cos_am;
float yz = yp * zp * cos_am;
float zx = zp * xp * cos_am;
xp *= sin_a;
yp *= sin_a;
zp *= sin_a;
// Load coefs
float m0 = xx + cos_a * (1.0f - xx);
float m1 = xy + zp;
float m2 = zx - yp;
float m4 = xy - zp;
float m5 = yy + cos_a * (1.0f - yy);
float m6 = yz + xp;
float m8 = zx + yp;
float m9 = yz - xp;
float m10 = zz + cos_a * (1.0f - zz);
// Apply rotation
float c1 = mtx[0];
float c2 = mtx[4];
float c3 = mtx[8];
mtx[0] = c1 * m0 + c2 * m1 + c3 * m2;
mtx[4] = c1 * m4 + c2 * m5 + c3 * m6;
mtx[8] = c1 * m8 + c2 * m9 + c3 * m10;
c1 = mtx[1];
c2 = mtx[5];
c3 = mtx[9];
mtx[1] = c1 * m0 + c2 * m1 + c3 * m2;
mtx[5] = c1 * m4 + c2 * m5 + c3 * m6;
mtx[9] = c1 * m8 + c2 * m9 + c3 * m10;
c1 = mtx[2];
c2 = mtx[6];
c3 = mtx[10];
mtx[2] = c1 * m0 + c2 * m1 + c3 * m2;
mtx[6] = c1 * m4 + c2 * m5 + c3 * m6;
mtx[10] = c1 * m8 + c2 * m9 + c3 * m10;
c1 = mtx[3];
c2 = mtx[7];
c3 = mtx[11];
mtx[3] = c1 * m0 + c2 * m1 + c3 * m2;
mtx[7] = c1 * m4 + c2 * m5 + c3 * m6;
mtx[11] = c1 * m8 + c2 * m9 + c3 * m10;
mtx[12] = mtx[13] = mtx[14] = 0.0;
mtx[15] = 1.0f;
}
void mtxTranslateApply(float* mtx, float xTrans, float yTrans, float zTrans)
{
// [ 0 4 8 12 ] [ 1 0 0 x ]
// [ 1 5 9 13 ] x [ 0 1 0 y ]
// [ 2 6 10 14 ] [ 0 0 1 z ]
// [ 3 7 11 15 ] [ 0 0 0 1 ]
mtx[12] += mtx[0]*xTrans + mtx[4]*yTrans + mtx[ 8]*zTrans;
mtx[13] += mtx[1]*xTrans + mtx[5]*yTrans + mtx[ 9]*zTrans;
mtx[14] += mtx[2]*xTrans + mtx[6]*yTrans + mtx[10]*zTrans;
}
void mtxScaleApply(float* mtx, float xScale, float yScale, float zScale)
{
// [ 0 4 8 12 ] [ x 0 0 0 ]
// [ 1 5 9 13 ] x [ 0 y 0 0 ]
// [ 2 6 10 14 ] [ 0 0 z 0 ]
// [ 3 7 11 15 ] [ 0 0 0 1 ]
mtx[ 0] *= xScale;
mtx[ 4] *= yScale;
mtx[ 8] *= zScale;
mtx[ 1] *= xScale;
mtx[ 5] *= yScale;
mtx[ 9] *= zScale;
mtx[ 2] *= xScale;
mtx[ 6] *= yScale;
mtx[10] *= zScale;
mtx[ 3] *= xScale;
mtx[ 7] *= yScale;
mtx[11] *= xScale;
}
void mtxTranslateMatrix(float* mtx, float xTrans, float yTrans, float zTrans)
{
// [ 1 0 0 x ] [ 0 4 8 12 ]
// [ 0 1 0 y ] x [ 1 5 9 13 ]
// [ 0 0 1 z ] [ 2 6 10 14 ]
// [ 0 0 0 1 ] [ 3 7 11 15 ]
mtx[ 0] += xTrans * mtx[ 3];
mtx[ 1] += yTrans * mtx[ 3];
mtx[ 2] += zTrans * mtx[ 3];
mtx[ 4] += xTrans * mtx[ 7];
mtx[ 5] += yTrans * mtx[ 7];
mtx[ 6] += zTrans * mtx[ 7];
mtx[ 8] += xTrans * mtx[11];
mtx[ 9] += yTrans * mtx[11];
mtx[10] += zTrans * mtx[11];
mtx[12] += xTrans * mtx[15];
mtx[13] += yTrans * mtx[15];
mtx[14] += zTrans * mtx[15];
}
void mtxRotateXApply(float* mtx, float deg)
{
// [ 0 4 8 12 ] [ 1 0 0 0 ]
// [ 1 5 9 13 ] x [ 0 cos -sin 0 ]
// [ 2 6 10 14 ] [ 0 sin cos 0 ]
// [ 3 7 11 15 ] [ 0 0 0 1 ]
float rad = deg * (M_PI/180.0f);
float cosrad = cosf(rad);
float sinrad = sinf(rad);
float mtx04 = mtx[4];
float mtx05 = mtx[5];
float mtx06 = mtx[6];
float mtx07 = mtx[7];
mtx[ 4] = mtx[ 8]*sinrad + mtx04*cosrad;
mtx[ 8] = mtx[ 8]*cosrad - mtx04*sinrad;
mtx[ 5] = mtx[ 9]*sinrad + mtx05*cosrad;
mtx[ 9] = mtx[ 9]*cosrad - mtx05*sinrad;
mtx[ 6] = mtx[10]*sinrad + mtx06*cosrad;
mtx[10] = mtx[10]*cosrad - mtx06*sinrad;
mtx[ 7] = mtx[11]*sinrad + mtx07*cosrad;
mtx[11] = mtx[11]*cosrad - mtx07*sinrad;
}
void mtxRotateYApply(float* mtx, float deg)
{
// [ 0 4 8 12 ] [ cos 0 -sin 0 ]
// [ 1 5 9 13 ] x [ 0 1 0 0 ]
// [ 2 6 10 14 ] [ sin 0 cos 0 ]
// [ 3 7 11 15 ] [ 0 0 0 1 ]
float rad = deg * (M_PI/180.0f);
float cosrad = cosf(rad);
float sinrad = sinf(rad);
float mtx00 = mtx[0];
float mtx01 = mtx[1];
float mtx02 = mtx[2];
float mtx03 = mtx[3];
mtx[ 0] = mtx[ 8]*sinrad + mtx00*cosrad;
mtx[ 8] = mtx[ 8]*cosrad - mtx00*sinrad;
mtx[ 1] = mtx[ 9]*sinrad + mtx01*cosrad;
mtx[ 9] = mtx[ 9]*cosrad - mtx01*sinrad;
mtx[ 2] = mtx[10]*sinrad + mtx02*cosrad;
mtx[10] = mtx[10]*cosrad - mtx02*sinrad;
mtx[ 3] = mtx[11]*sinrad + mtx03*cosrad;
mtx[11] = mtx[11]*cosrad - mtx03*sinrad;
}
void mtxRotateZApply(float* mtx, float deg)
{
// [ 0 4 8 12 ] [ cos -sin 0 0 ]
// [ 1 5 9 13 ] x [ sin cos 0 0 ]
// [ 2 6 10 14 ] [ 0 0 1 0 ]
// [ 3 7 11 15 ] [ 0 0 0 1 ]
float rad = deg * (M_PI/180.0f);
float cosrad = cosf(rad);
float sinrad = sinf(rad);
float mtx00 = mtx[0];
float mtx01 = mtx[1];
float mtx02 = mtx[2];
float mtx03 = mtx[3];
mtx[ 0] = mtx[ 4]*sinrad + mtx00*cosrad;
mtx[ 4] = mtx[ 4]*cosrad - mtx00*sinrad;
mtx[ 1] = mtx[ 5]*sinrad + mtx01*cosrad;
mtx[ 5] = mtx[ 5]*cosrad - mtx01*sinrad;
mtx[ 2] = mtx[ 6]*sinrad + mtx02*cosrad;
mtx[ 6] = mtx[ 6]*cosrad - mtx02*sinrad;
mtx[ 3] = mtx[ 7]*sinrad + mtx03*cosrad;
mtx[ 7] = mtx[ 7]*cosrad - mtx03*sinrad;
}
void mtxRotateApply(float* mtx, float deg, float xAxis, float yAxis, float zAxis)
{
if(yAxis == 0.0f && zAxis == 0.0f)
{
mtxRotateXApply(mtx, deg);
}
else if(xAxis == 0.0f && zAxis == 0.0f)
{
mtxRotateYApply(mtx, deg);
}
else if(xAxis == 0.0f && yAxis == 0.0f)
{
mtxRotateZApply(mtx, deg);
}
else
{
float rad = deg * M_PI/180.0f;
float sin_a = sinf(rad);
float cos_a = cosf(rad);
// Calculate coeffs. No need to check for zero magnitude because we wouldn't be here.
float magnitude = sqrtf(xAxis * xAxis + yAxis * yAxis + zAxis * zAxis);
float p = 1.0f / magnitude;
float cos_am = 1.0f - cos_a;
float xp = xAxis * p;
float yp = yAxis * p;
float zp = zAxis * p;
float xx = xp * xp;
float yy = yp * yp;
float zz = zp * zp;
float xy = xp * yp * cos_am;
float yz = yp * zp * cos_am;
float zx = zp * xp * cos_am;
xp *= sin_a;
yp *= sin_a;
zp *= sin_a;
// Load coefs
float m0 = xx + cos_a * (1.0f - xx);
float m1 = xy + zp;
float m2 = zx - yp;
float m4 = xy - zp;
float m5 = yy + cos_a * (1.0f - yy);
float m6 = yz + xp;
float m8 = zx + yp;
float m9 = yz - xp;
float m10 = zz + cos_a * (1.0f - zz);
// Apply rotation
float c1 = mtx[0];
float c2 = mtx[4];
float c3 = mtx[8];
mtx[0] = c1 * m0 + c2 * m1 + c3 * m2;
mtx[4] = c1 * m4 + c2 * m5 + c3 * m6;
mtx[8] = c1 * m8 + c2 * m9 + c3 * m10;
c1 = mtx[1];
c2 = mtx[5];
c3 = mtx[9];
mtx[1] = c1 * m0 + c2 * m1 + c3 * m2;
mtx[5] = c1 * m4 + c2 * m5 + c3 * m6;
mtx[9] = c1 * m8 + c2 * m9 + c3 * m10;
c1 = mtx[2];
c2 = mtx[6];
c3 = mtx[10];
mtx[2] = c1 * m0 + c2 * m1 + c3 * m2;
mtx[6] = c1 * m4 + c2 * m5 + c3 * m6;
mtx[10] = c1 * m8 + c2 * m9 + c3 * m10;
c1 = mtx[3];
c2 = mtx[7];
c3 = mtx[11];
mtx[3] = c1 * m0 + c2 * m1 + c3 * m2;
mtx[7] = c1 * m4 + c2 * m5 + c3 * m6;
mtx[11] = c1 * m8 + c2 * m9 + c3 * m10;
}
}
void mtxScaleMatrix(float* mtx, float xScale, float yScale, float zScale)
{
// [ x 0 0 0 ] [ 0 4 8 12 ]
// [ 0 y 0 0 ] x [ 1 5 9 13 ]
// [ 0 0 z 0 ] [ 2 6 10 14 ]
// [ 0 0 0 1 ] [ 3 7 11 15 ]
mtx[ 0] *= xScale;
mtx[ 4] *= xScale;
mtx[ 8] *= xScale;
mtx[12] *= xScale;
mtx[ 1] *= yScale;
mtx[ 5] *= yScale;
mtx[ 9] *= yScale;
mtx[13] *= yScale;
mtx[ 2] *= zScale;
mtx[ 6] *= zScale;
mtx[10] *= zScale;
mtx[14] *= zScale;
}
void mtxRotateXMatrix(float* mtx, float rad)
{
// [ 1 0 0 0 ] [ 0 4 8 12 ]
// [ 0 cos -sin 0 ] x [ 1 5 9 13 ]
// [ 0 sin cos 0 ] [ 2 6 10 14 ]
// [ 0 0 0 1 ] [ 3 7 11 15 ]
float cosrad = cosf(rad);
float sinrad = sinf(rad);
float mtx01 = mtx[ 1];
float mtx05 = mtx[ 5];
float mtx09 = mtx[ 9];
float mtx13 = mtx[13];
mtx[ 1] = cosrad*mtx01 - sinrad*mtx[ 2];
mtx[ 2] = sinrad*mtx01 + cosrad*mtx[ 2];
mtx[ 5] = cosrad*mtx05 - sinrad*mtx[ 6];
mtx[ 6] = sinrad*mtx05 + cosrad*mtx[ 6];
mtx[ 9] = cosrad*mtx09 - sinrad*mtx[10];
mtx[10] = sinrad*mtx09 + cosrad*mtx[10];
mtx[13] = cosrad*mtx13 - sinrad*mtx[14];
mtx[14] = sinrad*mtx13 + cosrad*mtx[14];
}
void mtxRotateYMatrix(float* mtx, float rad)
{
// [ cos 0 -sin 0 ] [ 0 4 8 12 ]
// [ 0 1 0 0 ] x [ 1 5 9 13 ]
// [ sin 0 cos 0 ] [ 2 6 10 14 ]
// [ 0 0 0 1 ] [ 3 7 11 15 ]
float cosrad = cosf(rad);
float sinrad = sinf(rad);
float mtx00 = mtx[ 0];
float mtx04 = mtx[ 4];
float mtx08 = mtx[ 8];
float mtx12 = mtx[12];
mtx[ 0] = cosrad*mtx00 - sinrad*mtx[ 2];
mtx[ 2] = sinrad*mtx00 + cosrad*mtx[ 2];
mtx[ 4] = cosrad*mtx04 - sinrad*mtx[ 6];
mtx[ 6] = sinrad*mtx04 + cosrad*mtx[ 6];
mtx[ 8] = cosrad*mtx08 - sinrad*mtx[10];
mtx[10] = sinrad*mtx08 + cosrad*mtx[10];
mtx[12] = cosrad*mtx12 - sinrad*mtx[14];
mtx[14] = sinrad*mtx12 + cosrad*mtx[14];
}
void mtxRotateZMatrix(float* mtx, float rad)
{
// [ cos -sin 0 0 ] [ 0 4 8 12 ]
// [ sin cos 0 0 ] x [ 1 5 9 13 ]
// [ 0 0 1 0 ] [ 2 6 10 14 ]
// [ 0 0 0 1 ] [ 3 7 11 15 ]
float cosrad = cosf(rad);
float sinrad = sinf(rad);
float mtx00 = mtx[ 0];
float mtx04 = mtx[ 4];
float mtx08 = mtx[ 8];
float mtx12 = mtx[12];
mtx[ 0] = cosrad*mtx00 - sinrad*mtx[ 1];
mtx[ 1] = sinrad*mtx00 + cosrad*mtx[ 1];
mtx[ 4] = cosrad*mtx04 - sinrad*mtx[ 5];
mtx[ 5] = sinrad*mtx04 + cosrad*mtx[ 5];
mtx[ 8] = cosrad*mtx08 - sinrad*mtx[ 9];
mtx[ 9] = sinrad*mtx08 + cosrad*mtx[ 9];
mtx[12] = cosrad*mtx12 - sinrad*mtx[13];
mtx[13] = sinrad*mtx12 + cosrad*mtx[13];
}
void mtxRotateMatrix(float* mtx, float rad, float xAxis, float yAxis, float zAxis)
{
float rotMtx[16];
mtxLoadRotate(rotMtx, rad, xAxis, yAxis, zAxis);
mtxMultiply(mtx, rotMtx, mtx);
}
void mtx3x3LoadIdentity(float* mtx)
{
mtx[0] = mtx[4] = mtx[8] = 1.0f;
mtx[1] = mtx[2] = mtx[3] =
mtx[5] = mtx[6] = mtx[7] = 0.0f;
}
void mtx3x3FromTopLeftOf4x4(float* mtx, const float* src)
{
mtx[0] = src[0];
mtx[1] = src[1];
mtx[2] = src[2];
mtx[3] = src[4];
mtx[4] = src[5];
mtx[5] = src[6];
mtx[6] = src[8];
mtx[7] = src[9];
mtx[8] = src[10];
}
void mtx3x3Transpose(float* mtx, const float* src)
{
float tmp;
mtx[0] = src[0];
mtx[4] = src[4];
mtx[8] = src[8];
tmp = src[1];
mtx[1] = src[3];
mtx[3] = tmp;
tmp = src[2];
mtx[2] = src[6];
mtx[6] = tmp;
tmp = src[5];
mtx[5] = src[7];
mtx[7] = tmp;
}
void mtx3x3Invert(float* mtx, const float* src)
{
float cpy[9];
float det =
src[0] * (src[4]*src[8] - src[7]*src[5]) -
src[1] * (src[3]*src[8] - src[6]*src[5]) +
src[2] * (src[3]*src[7] - src[6]*src[4]);
if ( fabs( det ) < 0.0005 )
{
mtx3x3LoadIdentity(mtx);
return;
}
memcpy(cpy, src, 9 * sizeof(float));
mtx[0] = cpy[4]*cpy[8] - cpy[5]*cpy[7] / det;
mtx[1] = -(cpy[1]*cpy[8] - cpy[7]*cpy[2]) / det;
mtx[2] = cpy[1]*cpy[5] - cpy[4]*cpy[2] / det;
mtx[3] = -(cpy[3]*cpy[8] - cpy[5]*cpy[6]) / det;
mtx[4] = cpy[0]*cpy[8] - cpy[6]*cpy[2] / det;
mtx[5] = -(cpy[0]*cpy[5] - cpy[3]*cpy[2]) / det;
mtx[6] = cpy[3]*cpy[7] - cpy[6]*cpy[4] / det;
mtx[7] = -(cpy[0]*cpy[7] - cpy[6]*cpy[1]) / det;
mtx[8] = cpy[0]*cpy[4] - cpy[1]*cpy[3] / det;
}
void mtx3x3Multiply(float* mtx, const float* lhs, const float* rhs)
{
mtx[0] = lhs[0]*rhs[0] + lhs[3] * rhs[1] + lhs[6] * rhs[2];
mtx[1] = lhs[1]*rhs[0] + lhs[4] * rhs[1] + lhs[7] * rhs[2];
mtx[2] = lhs[2]*rhs[0] + lhs[5] * rhs[1] + lhs[8] * rhs[2];
mtx[3] = lhs[0]*rhs[3] + lhs[3] * rhs[4] + lhs[6] * rhs[5];
mtx[4] = lhs[1]*rhs[3] + lhs[4] * rhs[4] + lhs[7] * rhs[5];
mtx[5] = lhs[2]*rhs[3] + lhs[5] * rhs[4] + lhs[8] * rhs[5];
mtx[6] = lhs[0]*rhs[6] + lhs[3] * rhs[7] + lhs[6] * rhs[8];
mtx[7] = lhs[1]*rhs[6] + lhs[4] * rhs[7] + lhs[7] * rhs[8];
mtx[8] = lhs[2]*rhs[6] + lhs[5] * rhs[7] + lhs[8] * rhs[8];
}

158
src/video_util/matrixUtil.h Normal file
View File

@ -0,0 +1,158 @@
/*
File: matrixUtil.h
Abstract:
Functions for performing matrix math.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#ifndef __MATRIX_UTIL_H__
#define __MATRIX_UTIL_H__
// Matrix is a column major floating point array
// All matrices are 4x4 by unless the mtx3x3 prefix is specified in the function name
// [ 0 4 8 12 ]
// [ 1 5 9 13 ]
// [ 2 6 10 14 ]
// [ 3 7 11 15 ]
// MTX = LeftHandSideMatrix * RightHandSideMatrix
void mtxMultiply(float* ret, const float* lhs, const float* rhs);
// MTX = IdentityMatrix
void mtxLoadIdentity(float* mtx);
// MTX = Transpos(SRC)
void mtxTranspose(float* mtx, const float* src);
// MTX = src^-1
void mtxInvert(float* mtx, const float* src);
// MTX = PerspectiveProjectionMatrix
void mtxLoadPerspective(float* mtx, float fov, float aspect, float nearZ, float farZ);
// MTX = OrthographicProjectionMatrix
void mtxLoadOrthographic(float* mtx,
float left, float right,
float bottom, float top,
float nearZ, float farZ);
// MTX = ObliqueProjectionMatrix(src, clipPlane)
void mtxModifyObliqueProjection(float* mtx, const float* src, const float* plane);
// MTX = TranlationMatrix
void mtxLoadTranslate(float* mtx, float xTrans, float yTrans, float zTrans);
// MTX = ScaleMatrix
void mtxLoadScale(float* mtx, float xScale, float yScale, float zScale);
// MTX = RotateXYZMatrix
void mtxLoadRotate(float*mtx, float deg, float xAxis, float , float zAxis);
// MTX = RotateXMatrix
void mtxLoadRotateX(float* mtx, float deg);
// MTX = RotateYMatrix
void mtxLoadRotateY(float* mtx, float deg);
// MTX = RotateZMatrix
void mtxLoadRotateZ(float* mtx, float deg);
// MTX = MTX * TranslationMatrix - Similar to glTranslate
void mtxTranslateApply(float* mtx, float xTrans, float yTrans, float zTrans);
// MTX = MTX * ScaleMatrix - Similar to glScale
void mtxScaleApply(float* mtx, float xScale, float yScale, float zScale);
// MTX = MTX * RotateXYZMatrix - Similar to glRotate
void mtxRotateApply(float* mtx, float deg, float xAxis, float yAxis, float zAxis);
// MTX = MTX * RotateXMatrix
void mtxRotateXApply(float* mtx, float rad);
// MTX = MTX * RotateYMatrix
void mtxRotateYApply(float* mtx, float rad);
// MTX = MTX * RotateZMatrix
void mtxRotateZApply(float* mtx, float rad);
// MTX = TranslationMatrix * MTX
void mtxTranslateMatrix(float* mtx, float xTrans, float yTrans, float zTrans);
// MTX = ScaleMatrix * MTX
void mtxScaleMatrix(float* mtx, float xScale, float yScale, float zScale);
// MTX = RotateXYZMatrix * MTX
void mtxRotateMatrix(float* mtx, float rad, float xAxis, float yAxis, float zAxis);
// MTX = RotateXMatrix * MTX
void mtxRotateXMatrix(float* mtx, float rad);
// MTX = RotateYMatrix * MTX
void mtxRotateYMatrix(float* mtx, float rad);
// MTX = RotateZMatrix * MTX
void mtxRotateZMatrix(float* mtx, float rad);
// 3x3 MTX = 3x3 IdendityMatrix
void mtx3x3LoadIdentity(float* mtx);
// 3x3 MTX = 3x3 LHS x 3x3 RHS
void mtx3x3Multiply(float* mtx, const float* lhs, const float* rhs);
// 3x3 MTX = TopLeft of MTX
void mtx3x3FromTopLeftOf4x4(float* mtx, const float* src);
// 3x3 MTX = Transpose(3x3 SRC)
void mtx3x3Transpose(float* mtx, const float* src);
// 3x3 MTX = 3x3 SRC^-1
void mtx3x3Invert(float* mtx, const float* src);
#endif //__MATRIX_UTIL_H__

422
src/video_util/modelUtil.c Normal file
View File

@ -0,0 +1,422 @@
/*
File: modelUtil.c
Abstract:
Functions for loading a model file for vertex arrays. The model file
format used is a simple "binary blob" invented for the purpose of
this sample code.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#include "modelUtil.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct modelHeaderRec
{
char fileIdentifier[30];
unsigned int majorVersion;
unsigned int minorVersion;
} modelHeader;
typedef struct modelTOCRec
{
unsigned int attribHeaderSize;
unsigned int byteElementOffset;
unsigned int bytePositionOffset;
unsigned int byteTexcoordOffset;
unsigned int byteNormalOffset;
} modelTOC;
typedef struct modelAttribRec
{
unsigned int byteSize;
GLenum datatype;
GLenum primType; //If index data
unsigned int sizePerElement;
unsigned int numElements;
} modelAttrib;
demoModel* mdlLoadModel(const char* filepathname)
{
if(NULL == filepathname)
{
return NULL;
}
demoModel* model = (demoModel*) calloc(sizeof(demoModel), 1);
if(NULL == model)
{
return NULL;
}
size_t sizeRead;
int error;
FILE* curFile = fopen(filepathname, "r");
if(!curFile)
{
mdlDestroyModel(model);
return NULL;
}
modelHeader header;
sizeRead = fread(&header, 1, sizeof(modelHeader), curFile);
if(sizeRead != sizeof(modelHeader))
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
if(strncmp(header.fileIdentifier, "AppleOpenGLDemoModelWWDC2010", sizeof(header.fileIdentifier)))
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
if(header.majorVersion != 0 && header.minorVersion != 1)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
modelTOC toc;
sizeRead = fread(&toc, 1, sizeof(modelTOC), curFile);
if(sizeRead != sizeof(modelTOC))
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
if(toc.attribHeaderSize > sizeof(modelAttrib))
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
modelAttrib attrib;
error = fseek(curFile, toc.byteElementOffset, SEEK_SET);
if(error < 0)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
sizeRead = fread(&attrib, 1, toc.attribHeaderSize, curFile);
if(sizeRead != toc.attribHeaderSize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
model->elementArraySize = attrib.byteSize;
model->elementType = attrib.datatype;
model->numElements = attrib.numElements;
// OpenGL ES cannot use UNSIGNED_INT elements
// So if the model has UI element...
if(GL_UNSIGNED_INT == model->elementType)
{
//...Load the UI elements and convert to UNSIGNED_SHORT
GLubyte* uiElements = (GLubyte*) malloc(model->elementArraySize);
size_t ushortElementArraySize = model->numElements * sizeof(GLushort);
model->elements = (GLubyte*)malloc(ushortElementArraySize);
sizeRead = fread(uiElements, 1, model->elementArraySize, curFile);
if(sizeRead != model->elementArraySize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
GLuint elemNum = 0;
for(elemNum = 0; elemNum < model->numElements; elemNum++)
{
//We can't handle this model if an element is out of the UNSIGNED_INT range
if(((GLuint*)uiElements)[elemNum] >= 0xFFFF)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
((GLushort*)model->elements)[elemNum] = ((GLuint*)uiElements)[elemNum];
}
free(uiElements);
model->elementType = GL_UNSIGNED_SHORT;
model->elementArraySize = model->numElements * sizeof(GLushort);
}
else
{
model->elements = (GLubyte*)malloc(model->elementArraySize);
sizeRead = fread(model->elements, 1, model->elementArraySize, curFile);
if(sizeRead != model->elementArraySize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
}
fseek(curFile, toc.bytePositionOffset, SEEK_SET);
sizeRead = fread(&attrib, 1, toc.attribHeaderSize, curFile);
if(sizeRead != toc.attribHeaderSize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
model->positionArraySize = attrib.byteSize;
model->positionType = attrib.datatype;
model->positionSize = attrib.sizePerElement;
model->numVertices = attrib.numElements;
model->positions = (GLubyte*) malloc(model->positionArraySize);
sizeRead = fread(model->positions, 1, model->positionArraySize, curFile);
if(sizeRead != model->positionArraySize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
error = fseek(curFile, toc.byteTexcoordOffset, SEEK_SET);
if(error < 0)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
sizeRead = fread(&attrib, 1, toc.attribHeaderSize, curFile);
if(sizeRead != toc.attribHeaderSize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
model->texcoordArraySize = attrib.byteSize;
model->texcoordType = attrib.datatype;
model->texcoordSize = attrib.sizePerElement;
//Must have the same number of texcoords as positions
if(model->numVertices != attrib.numElements)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
model->texcoords = (GLubyte*) malloc(model->texcoordArraySize);
sizeRead = fread(model->texcoords, 1, model->texcoordArraySize, curFile);
if(sizeRead != model->texcoordArraySize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
error = fseek(curFile, toc.byteNormalOffset, SEEK_SET);
if(error < 0)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
sizeRead = fread(&attrib, 1, toc.attribHeaderSize, curFile);
if(sizeRead != toc.attribHeaderSize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
model->normalArraySize = attrib.byteSize;
model->normalType = attrib.datatype;
model->normalSize = attrib.sizePerElement;
//Must have the same number of normals as positions
if(model->numVertices != attrib.numElements)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
model->normals = (GLubyte*) malloc(model->normalArraySize );
sizeRead = fread(model->normals, 1, model->normalArraySize , curFile);
if(sizeRead != model->normalArraySize)
{
fclose(curFile);
mdlDestroyModel(model);
return NULL;
}
fclose(curFile);
return model;
}
demoModel* mdlLoadQuadModel()
{
GLfloat posArray[] = {
-200.0f, 0.0f, -200.0f,
200.0f, 0.0f, -200.0f,
200.0f, 0.0f, 200.0f,
-200.0f, 0.0f, 200.0f
};
GLfloat texcoordArray[] = {
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f
};
GLfloat normalArray[] = {
0.0f, 0.0f, 1.0,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
};
GLushort elementArray[] =
{
0, 2, 1,
0, 3, 2
};
demoModel* model = (demoModel*) calloc(sizeof(demoModel), 1);
if(NULL == model)
{
return NULL;
}
model->positionType = GL_FLOAT;
model->positionSize = 3;
model->positionArraySize = sizeof(posArray);
model->positions = (GLubyte*)malloc(model->positionArraySize);
memcpy(model->positions, posArray, model->positionArraySize);
model->texcoordType = GL_FLOAT;
model->texcoordSize = 2;
model->texcoordArraySize = sizeof(texcoordArray);
model->texcoords = (GLubyte*)malloc(model->texcoordArraySize);
memcpy(model->texcoords, texcoordArray, model->texcoordArraySize );
model->normalType = GL_FLOAT;
model->normalSize = 3;
model->normalArraySize = sizeof(normalArray);
model->normals = (GLubyte*)malloc(model->normalArraySize);
memcpy(model->normals, normalArray, model->normalArraySize);
model->elementArraySize = sizeof(elementArray);
model->elements = (GLubyte*)malloc(model->elementArraySize);
memcpy(model->elements, elementArray, model->elementArraySize);
model->primType = GL_TRIANGLES;
model->numElements = sizeof(elementArray) / sizeof(GLushort);
model->elementType = GL_UNSIGNED_SHORT;
model->numVertices = model->positionArraySize / (model->positionSize * sizeof(GLfloat));
return model;
}
void mdlDestroyModel(demoModel* model)
{
if(NULL == model)
{
return;
}
free(model->elements);
free(model->positions);
free(model->normals);
free(model->texcoords);
free(model);
}

View File

@ -0,0 +1,91 @@
/*
File: modelUtil.h
Abstract:
Functions for loading a model file for vertex arrays. The model file
format used is a simple "binary blob" invented for the purpose of
this sample code.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#ifndef __MODEL_UTIL_H__
#define __MODEL_UTIL_H__
#include "glUtil.h"
typedef struct demoModelRec
{
GLuint numVertices;
GLubyte *positions;
GLenum positionType;
GLuint positionSize;
GLsizei positionArraySize;
GLubyte *texcoords;
GLenum texcoordType;
GLuint texcoordSize;
GLsizei texcoordArraySize;
GLubyte *normals;
GLenum normalType;
GLuint normalSize;
GLsizei normalArraySize;
GLubyte *elements;
GLenum elementType;
GLuint numElements;
GLsizei elementArraySize;
GLenum primType;
} demoModel;
demoModel* mdlLoadModel(const char* filepathname);
demoModel* mdlLoadQuadModel();
void mdlDestroyModel(demoModel* model);
#endif //__MODEL_UTIL_H__

105
src/video_util/sourceUtil.c Normal file
View File

@ -0,0 +1,105 @@
/*
File: sourceUtil.c
Abstract:
Functions for loading source files for shaders.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#include "sourceUtil.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
demoSource* srcLoadSource(const char* filepathname)
{
demoSource* source = (demoSource*) calloc(sizeof(demoSource), 1);
// Check the file name suffix to determine what type of shader this is
const char* suffixBegin = filepathname + strlen(filepathname) - 4;
if(0 == strncmp(suffixBegin, ".fsh", 4))
{
source->shaderType = GL_FRAGMENT_SHADER;
}
else if(0 == strncmp(suffixBegin, ".vsh", 4))
{
source->shaderType = GL_VERTEX_SHADER;
}
else
{
// Unknown suffix
source->shaderType = 0;
}
FILE* curFile = fopen(filepathname, "r");
// Get the size of the source
fseek(curFile, 0, SEEK_END);
GLsizei fileSize = ftell (curFile);
// Add 1 to the file size to include the null terminator for the string
source->byteSize = fileSize + 1;
// Alloc memory for the string
source->string = malloc(source->byteSize);
// Read entire file into the string from beginning of the file
fseek(curFile, 0, SEEK_SET);
fread(source->string, 1, fileSize, curFile);
fclose(curFile);
// Insert null terminator
source->string[fileSize] = 0;
return source;
}
void srcDestroySource(demoSource* source)
{
free(source->string);
free(source);
}

View File

@ -0,0 +1,69 @@
/*
File: sourceUtil.h
Abstract:
Functions for loading source files for shaders.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#ifndef __SOURCE_UTIL_H__
#define __SOURCE_UTIL_H__
#include "glUtil.h"
typedef struct demoSourceRec
{
GLchar* string;
GLsizei byteSize;
GLenum shaderType; // Vertex or Fragment
} demoSource;
demoSource* srcLoadSource(const char* filepathname);
void srcDestroySource(demoSource* source);
#endif // __SOURCE_UTIL_H__

157
src/video_util/vectorUtil.c Executable file
View File

@ -0,0 +1,157 @@
/*
File: vectorUtil.c
Abstract:
Functions for performing vector math.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#include "vectorUtil.h"
#include <math.h>
#include <memory.h>
void vec4Add(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[0] + rhs[0];
vec[1] = lhs[1] + rhs[1];
vec[2] = lhs[2] + rhs[2];
vec[3] = lhs[3] + rhs[3];
}
void vec4Subtract(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[0] - rhs[0];
vec[1] = lhs[1] - rhs[1];
vec[2] = lhs[2] - rhs[2];
vec[3] = lhs[3] - rhs[3];
}
void vec4Multiply(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[0] * rhs[0];
vec[1] = lhs[1] * rhs[1];
vec[2] = lhs[2] * rhs[2];
vec[3] = lhs[3] * rhs[3];
}
void vec4Divide(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[0] / rhs[0];
vec[1] = lhs[1] / rhs[1];
vec[2] = lhs[2] / rhs[2];
vec[3] = lhs[3] / rhs[3];
}
void vec3Add(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[0] + rhs[0];
vec[1] = lhs[1] + rhs[1];
vec[2] = lhs[2] + rhs[2];
}
void vec3Subtract(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[0] - rhs[0];
vec[1] = lhs[1] - rhs[1];
vec[2] = lhs[2] - rhs[2];
}
void vec3Multiply(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[0] * rhs[0];
vec[1] = lhs[1] * rhs[1];
vec[2] = lhs[2] * rhs[2];
}
void vec3Divide(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[0] / rhs[0];
vec[1] = lhs[1] / rhs[1];
vec[2] = lhs[2] / rhs[2];
}
float vec3DotProduct(const float* lhs, const float* rhs)
{
return lhs[0]*rhs[0] + lhs[1]*rhs[1] + lhs[2]*rhs[2];
}
float vec4DotProduct(const float* lhs, const float* rhs)
{
return lhs[0]*rhs[0] + lhs[1]*rhs[1] + lhs[2]*rhs[2] + lhs[3]*rhs[3];
}
void vec3CrossProduct(float* vec, const float* lhs, const float* rhs)
{
vec[0] = lhs[1] * rhs[2] - lhs[2] * rhs[1];
vec[1] = lhs[2] * rhs[0] - lhs[0] * rhs[2];
vec[2] = lhs[0] * rhs[1] - lhs[1] * rhs[0];
}
float vec3Length(const float* vec)
{
return sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
}
float vec3Distance(const float* pointA, const float* pointB)
{
float diffx = pointA[0]-pointB[0];
float diffy = pointA[1]-pointB[1];
float diffz = pointA[2]-pointB[2];
return sqrtf(diffx*diffx + diffy*diffy + diffz*diffz);
}
void vec3Normalize(float* vec, const float* src)
{
float length = vec3Length(src);
vec[0] = src[0]/length;
vec[1] = src[1]/length;
vec[2] = src[2]/length;
}

100
src/video_util/vectorUtil.h Executable file
View File

@ -0,0 +1,100 @@
/*
File: vectorUtil.h
Abstract:
Functions for performing vector math.
Version: 1.7
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
*/
#ifndef __VECTOR_UTIL_H__
#define __VECTOR_UTIL_H__
// A Vector is floating point array with either 3 or 4 components
// functions with the vec4 prefix require 4 elements in the array
// functions with vec3 prefix require only 3 elements in the array
// Subtracts one 4D vector to another
void vec4Add(float* vec, const float* lhs, const float* rhs);
// Subtracts one 4D vector from another
void vec4Subtract(float* vec, const float* lhs, const float* rhs);
// Multiplys one 4D vector by another
void vec4Multiply(float* vec, const float* lhs, const float* rhs);
// Divides one 4D vector by another
void vec4Divide(float* vec, const float* lhs, const float* rhs);
// Subtracts one 4D vector to another
void vec3Add(float* vec, const float* lhs, const float* rhs);
// Subtracts one 4D vector from another
void vec3Subtract(float* vec, const float* lhs, const float* rhs);
// Multiplys one 4D vector by another
void vec3Multiply(float* vec, const float* lhs, const float* rhs);
// Divides one 4D vector by another
void vec3Divide(float* vec, const float* lhs, const float* rhs);
// Calculates the Cross Product of a 3D vector
void vec3CrossProduct(float* vec, const float* lhs, const float* rhs);
// Normalizes a 3D vector
void vec3Normalize(float* vec, const float* src);
// Returns the Dot Product of 2 3D vectors
float vec3DotProduct(const float* lhs, const float* rhs);
// Returns the Dot Product of 2 4D vectors
float vec4DotProduct(const float* lhs, const float* rhs);
// Returns the length of a 3D vector
// (i.e the distance of a point from the origin)
float vec3Length(const float* vec);
// Returns the distance between two 3D points
float vec3Distance(const float* pointA, const float* pointB);
#endif //__VECTOR_UTIL_H__