1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* aquaOpenGLView.m
*/
#import <Foundation/NSObjCRuntime.h>
#if defined (NSFoundationVersionNumber10_5) && MAC_OS_X_VERSION_MAX_ALLOWED < 1050
@class CALayer;
@class NSViewController;
typedef int NSColorRenderingIntent;
#endif
#include <Cocoa/Cocoa.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include "aquaOpenGLView.h"
@implementation AquaOpenGLView
+ (NSOpenGLPixelFormat*)defaultPixelFormat
{
// first simple implementation (let's see later with more complex )
NSOpenGLPixelFormatAttribute attributes [] =
{
NSOpenGLPFAWindow,
NSOpenGLPFADoubleBuffer, // double buffered
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer
(NSOpenGLPixelFormatAttribute)nil
};
return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease];
}
- (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format
{
self = [super initWithFrame:frameRect];
if (self != nil) {
_pixelFormat = [format retain];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_surfaceNeedsUpdate:) name:NSViewGlobalFrameDidChangeNotification object:self];
return self;
}
- (void)dealloc
{ // get rid of the context and pixel format
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewGlobalFrameDidChangeNotification object:self];
[self clearGLContext];
if (_pixelFormat)
[_pixelFormat release];
[super dealloc];
}
- (void)setOpenGLContext:(NSOpenGLContext*)context
{
[self clearGLContext];
_openGLContext = [context retain];
}
- (NSOpenGLContext*)openGLContext
{ // create a context the first time through
if (_openGLContext == NULL) {
_openGLContext = [[NSOpenGLContext alloc] initWithFormat:_pixelFormat != nil ? _pixelFormat : [[self class] defaultPixelFormat] shareContext:nil];
[_openGLContext makeCurrentContext];
[self prepareOpenGL]; // call to initialize OpenGL state here
}
return _openGLContext;
}
- (void)clearGLContext
{
if (_openGLContext != nil) {
if ([_openGLContext view] == self) {
[_openGLContext clearDrawable];
}
[_openGLContext release];
_openGLContext = nil;
}
}
- (void)prepareOpenGL
{
// for overriding to initialize OpenGL state, occurs after context creation
long swapInt = 1;
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; // set to vbl sync
// init GL stuff here
// FIXME: why is there garbage using prepareOpenGL ,
// but NOT, wen using the same content,
// directly in the OGLTrans instance ?
glShadeModel( GL_SMOOTH );
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glClearColor (0.0f, 0.0f, 0.0f, 0.0f); // R G B A
glClear(GL_COLOR_BUFFER_BIT);
glClearDepth( 1.0f );
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
GLfloat light_direction[] = { 0.0 , 0.0 , 1.0 };
GLfloat materialDiffuse[] = { 1.0 , 1.0 , 1.0 , 1.0};
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
glMaterialfv(GL_FRONT,GL_DIFFUSE,materialDiffuse);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
[[self openGLContext] flushBuffer];
}
- (BOOL)isOpaque
{
return YES;
}
- (void)drawRect
{
// get context. will create if we don't have one yet
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];
//perform drawing here
[context flushBuffer];
}
- (void)lockFocus
{
// get context. will create if we don't have one yet
NSOpenGLContext* context = [self openGLContext];
// make sure we are ready to draw
[super lockFocus];
// when we are about to draw, make sure we are linked to the view
if ([context view] != self) {
[context setView:self];
}
// make us the current OpenGL context
[context makeCurrentContext];
}
// no reshape will be called since NSView does not export a specific reshape method
- (void)update
{
if ([_openGLContext view] == self) {
[_openGLContext update];
}
}
- (void) _surfaceNeedsUpdate:(NSNotification*)notification
{
(void) notification; // unused
[self update];
}
- (void)setPixelFormat:(NSOpenGLPixelFormat*)pixelFormat
{
[_pixelFormat release];
_pixelFormat = [pixelFormat retain];
}
- (NSOpenGLPixelFormat*)pixelFormat
{
return _pixelFormat;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[super encodeWithCoder:coder];
if (![coder allowsKeyedCoding]) {
[coder encodeValuesOfObjCTypes:"@iii", &_pixelFormat];
} else {
[coder encodeObject:_pixelFormat forKey:@"NSPixelFormat"];
}
}
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (![coder allowsKeyedCoding]) {
[coder decodeValuesOfObjCTypes:"@iii", &_pixelFormat];
} else {
_pixelFormat = [[coder decodeObjectForKey:@"NSPixelFormat"] retain];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_surfaceNeedsUpdate:) name:NSViewGlobalFrameDidChangeNotification object:self];
return self;
}
@end
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|