rays 0.1.15 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,236 @@
1
+ // -*- mode: objc -*-
2
+ #import "rays/camera.h"
3
+
4
+
5
+ #import <AVFoundation/AVFoundation.h>
6
+ #include "bitmap.h"
7
+
8
+
9
+ static int video_input_queue_index = 0;
10
+
11
+
12
+ @interface VideoInput : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
13
+ @end
14
+
15
+
16
+ @implementation VideoInput
17
+
18
+ {
19
+ AVCaptureSession* captureSession;
20
+ dispatch_queue_t captureQueue;
21
+ CGImageRef captureImage;
22
+ }
23
+
24
+ - (id) init
25
+ {
26
+ self = [super init];
27
+ if (self)
28
+ {
29
+ captureSession = nil;
30
+ captureQueue = nil;
31
+ captureImage = nil;
32
+ }
33
+ return self;
34
+ }
35
+
36
+ - (void) dealloc
37
+ {
38
+ [self stop];
39
+ [self clearImage];
40
+
41
+ if (captureQueue)
42
+ {
43
+ dispatch_release(captureQueue);
44
+ captureQueue = nil;
45
+ }
46
+
47
+ [super dealloc];
48
+ }
49
+
50
+ - (dispatch_queue_t) queue
51
+ {
52
+ if (!captureQueue)
53
+ {
54
+ auto name = Xot::stringf(
55
+ "org.xord.RaysVideoInputQueue_%d",
56
+ video_input_queue_index++);
57
+ captureQueue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
58
+ }
59
+ return captureQueue;
60
+ }
61
+
62
+ - (BOOL) start
63
+ {
64
+ [self stop];
65
+
66
+ AVCaptureSession* session = [[[AVCaptureSession alloc] init] autorelease];
67
+ session.sessionPreset = AVCaptureSessionPresetHigh;
68
+
69
+ AVCaptureDevice* device =
70
+ [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
71
+ if (!device) return NO;
72
+
73
+ //device.activeVideoMinFrameDuration = CMTimeMake(1, 30);
74
+
75
+ NSError* error = nil;
76
+ AVCaptureDeviceInput* input = [[[AVCaptureDeviceInput alloc]
77
+ initWithDevice: device error: &error]
78
+ autorelease];
79
+ if (!input || error || ![session canAddInput: input])
80
+ return NO;
81
+
82
+ AVCaptureVideoDataOutput* output =
83
+ [[[AVCaptureVideoDataOutput alloc] init] autorelease];
84
+ output.videoSettings = @{
85
+ (NSString*) kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)
86
+ };
87
+ output.alwaysDiscardsLateVideoFrames = YES;
88
+ [output setSampleBufferDelegate: self queue: self.queue];
89
+ if (![session canAddOutput: output])
90
+ return NO;
91
+
92
+ [session addInput: input];
93
+ [session addOutput: output];
94
+ [session startRunning];
95
+
96
+ captureSession = [session retain];
97
+ return YES;
98
+ }
99
+
100
+ - (void) captureOutput: (AVCaptureOutput*) output
101
+ didOutputSampleBuffer: (CMSampleBufferRef) sampleBuffer
102
+ fromConnection: (AVCaptureConnection*) connection
103
+ {
104
+ CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
105
+ if (!pixelBuffer) return;
106
+
107
+ CIImage* ciImage = [CIImage imageWithCVPixelBuffer: pixelBuffer];
108
+ if (!ciImage) return;
109
+
110
+ CIContext* context = [CIContext contextWithOptions: nil];
111
+ size_t width = CVPixelBufferGetWidth(pixelBuffer);
112
+ size_t height = CVPixelBufferGetHeight(pixelBuffer);
113
+ CGRect rect = CGRectMake(0, 0, width, height);
114
+ CGImageRef cgImage = [context createCGImage: ciImage fromRect: rect];
115
+
116
+ dispatch_async(dispatch_get_main_queue(), ^{
117
+ [self clearImage];
118
+ captureImage = cgImage;
119
+ });
120
+ }
121
+
122
+ - (void) stop
123
+ {
124
+ if (!captureSession) return;
125
+
126
+ [captureSession stopRunning];
127
+ [captureSession release];
128
+ captureSession = nil;
129
+ }
130
+
131
+ - (BOOL) isActive
132
+ {
133
+ return captureSession != nil;
134
+ }
135
+
136
+ - (void) clearImage
137
+ {
138
+ if (!captureImage) return;
139
+
140
+ CGImageRelease(captureImage);
141
+ captureImage = nil;
142
+ }
143
+
144
+ - (CGImageRef) getImage
145
+ {
146
+ return captureImage;
147
+ }
148
+
149
+ @end// VideoInput
150
+
151
+
152
+ namespace Rays
153
+ {
154
+
155
+
156
+ struct Camera::Data
157
+ {
158
+
159
+ mutable Image image;
160
+
161
+ VideoInput* video_input = nil;
162
+
163
+ void update_image_from_video_input () const
164
+ {
165
+ if (!video_input) return;
166
+
167
+ CGImageRef cgImage = [video_input getImage];
168
+ if (!cgImage) return;
169
+
170
+ if (!image)
171
+ {
172
+ Bitmap bmp(
173
+ (int) CGImageGetWidth(cgImage),
174
+ (int) CGImageGetHeight(cgImage));
175
+ image = Image(bmp);
176
+ }
177
+
178
+ Bitmap_copy_pixels(&image.bitmap(), cgImage);
179
+
180
+ [video_input clearImage];
181
+ }
182
+
183
+ };// Camera::Data
184
+
185
+
186
+ Camera::Camera ()
187
+ {
188
+ }
189
+
190
+ Camera::~Camera ()
191
+ {
192
+ stop();
193
+ if (self->video_input) [self->video_input release];
194
+ }
195
+
196
+ bool
197
+ Camera::start ()
198
+ {
199
+ if (!self->video_input) self->video_input = [[VideoInput alloc] init];
200
+ return [self->video_input start];
201
+ }
202
+
203
+ void
204
+ Camera::stop ()
205
+ {
206
+ if (!self->video_input) return;
207
+
208
+ [self->video_input stop];
209
+ }
210
+
211
+ bool
212
+ Camera::is_active () const
213
+ {
214
+ return self->video_input && [self->video_input isActive];
215
+ }
216
+
217
+ const Image*
218
+ Camera::image () const
219
+ {
220
+ self->update_image_from_video_input();
221
+ return self->image ? &self->image : NULL;
222
+ }
223
+
224
+ Camera::operator bool () const
225
+ {
226
+ return true;
227
+ }
228
+
229
+ bool
230
+ Camera::operator ! () const
231
+ {
232
+ return !operator bool();
233
+ }
234
+
235
+
236
+ }// Rays
@@ -652,7 +652,7 @@ namespace Rays
652
652
 
653
653
  //glEnable(GL_CULL_FACE);
654
654
  glEnable(GL_BLEND);
655
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
655
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
656
656
  OpenGL_check_error(__FILE__, __LINE__);
657
657
 
658
658
  FrameBuffer& fb = self->frame_buffer;
@@ -280,9 +280,11 @@ namespace Rays
280
280
  case JOIN_MITER: return clip::jtMiter;
281
281
  case JOIN_ROUND: return clip::jtRound;
282
282
  case JOIN_SQUARE: return clip::jtSquare;
283
+ default:
284
+ argument_error(__FILE__, __LINE__, "invalid join type -- %d", join);
283
285
  }
284
286
 
285
- argument_error(__FILE__, __LINE__);
287
+ return clip::jtMiter;// to avoid compiler warning
286
288
  }
287
289
 
288
290
  static clip::EndType
@@ -295,9 +297,11 @@ namespace Rays
295
297
  case CAP_BUTT: return clip::etOpenButt;
296
298
  case CAP_ROUND: return clip::etOpenRound;
297
299
  case CAP_SQUARE: return clip::etOpenSquare;
300
+ default:
301
+ argument_error(__FILE__, __LINE__, "invalid cap type -- %d", cap);
298
302
  }
299
303
 
300
- argument_error(__FILE__, __LINE__);
304
+ return clip::etOpenButt;// to avoid compiler warning
301
305
  }
302
306
 
303
307
  static bool
@@ -25,4 +25,9 @@ class TestFont < Test::Unit::TestCase
25
25
  assert_equal w * 2, font.width('XX')
26
26
  end
27
27
 
28
+ def test_height ()
29
+ f = font
30
+ assert_equal f.height, f.ascent + f.descent + f.leading
31
+ end
32
+
28
33
  end# TestFont
@@ -28,7 +28,7 @@ class TestPainter < Test::Unit::TestCase
28
28
  assert_equal color(1, 1, 1, 1), pa.background
29
29
  pa.background = 0
30
30
  assert_equal color(0, 0, 0, 1), pa.background
31
- pa.background 1
31
+ pa.background 1
32
32
  assert_equal color(1, 1, 1, 1), pa.background
33
33
  pa.push background: 0 do |_|
34
34
  assert_equal color(0, 0, 0, 1), pa.background
@@ -42,7 +42,7 @@ class TestPainter < Test::Unit::TestCase
42
42
  assert_equal color(1, 1, 1, 1), pa.fill
43
43
  pa.fill = 0
44
44
  assert_equal color(0, 0, 0, 1), pa.fill
45
- pa.fill 1
45
+ pa.fill 1
46
46
  assert_equal color(1, 1, 1, 1), pa.fill
47
47
  pa.push fill: 0 do |_|
48
48
  assert_equal color(0, 0, 0, 1), pa.fill
@@ -56,7 +56,7 @@ class TestPainter < Test::Unit::TestCase
56
56
  assert_equal color(1, 1, 1, 1), pa.stroke
57
57
  pa.stroke = 0
58
58
  assert_equal color(0, 0, 0, 1), pa.stroke
59
- pa.stroke 1
59
+ pa.stroke 1
60
60
  assert_equal color(1, 1, 1, 1), pa.stroke
61
61
  pa.push stroke: 0 do |_|
62
62
  assert_equal color(0, 0, 0, 1), pa.stroke
@@ -64,13 +64,73 @@ class TestPainter < Test::Unit::TestCase
64
64
  assert_equal color(1, 1, 1, 1), pa.stroke
65
65
  end
66
66
 
67
+ def test_stroke_width_accessor ()
68
+ pa = painter
69
+ assert_equal 0, pa.stroke_width
70
+ pa.stroke_width = 1
71
+ assert_equal 1, pa.stroke_width
72
+ pa.stroke_width = 0
73
+ assert_equal 0, pa.stroke_width
74
+ pa.stroke_width 2
75
+ assert_equal 2, pa.stroke_width
76
+ pa.push stroke_width: 3 do |_|
77
+ assert_equal 3, pa.stroke_width
78
+ end
79
+ assert_equal 2, pa.stroke_width
80
+ end
81
+
82
+ def test_stroke_cap_accessor ()
83
+ pa = painter
84
+ assert_equal :butt, pa.stroke_cap
85
+ pa.stroke_cap = :round
86
+ assert_equal :round, pa.stroke_cap
87
+ pa.stroke_cap :square
88
+ assert_equal :square, pa.stroke_cap
89
+ pa.push stroke_cap: :butt do |_|
90
+ assert_equal :butt, pa.stroke_cap
91
+ end
92
+ assert_equal :square, pa.stroke_cap
93
+ assert_raise(ArgumentError) {pa.stroke_cap :foo}
94
+ assert_raise(ArgumentError) {pa.stroke_cap :BUTT}
95
+ assert_raise(ArgumentError) {pa.stroke_cap Rays::CAP_BUTT}# ToDo: accept this
96
+ end
97
+
98
+ def test_stroke_join_accessor ()
99
+ pa = painter
100
+ assert_equal :miter, pa.stroke_join
101
+ pa.stroke_join = :round
102
+ assert_equal :round, pa.stroke_join
103
+ pa.stroke_join :square
104
+ assert_equal :square, pa.stroke_join
105
+ pa.push stroke_join: :miter do |_|
106
+ assert_equal :miter, pa.stroke_join
107
+ end
108
+ assert_equal :square, pa.stroke_join
109
+ assert_raise(ArgumentError) {pa.stroke_join :foo}
110
+ assert_raise(ArgumentError) {pa.stroke_join :MITER}
111
+ assert_raise(ArgumentError) {pa.stroke_join Rays::JOIN_MITER}# ToDo: accept this
112
+ end
113
+
114
+ def test_miter_limit_accessor ()
115
+ pa = painter
116
+ assert_equal 2, pa.miter_limit
117
+ pa.miter_limit = 3
118
+ assert_equal 3, pa.miter_limit
119
+ pa.miter_limit 4
120
+ assert_equal 4, pa.miter_limit
121
+ pa.push miter_limit: 9 do |_|
122
+ assert_equal 9, pa.miter_limit
123
+ end
124
+ assert_equal 4, pa.miter_limit
125
+ end
126
+
67
127
  def test_clip_accessor ()
68
128
  pa = painter
69
129
  pa.clip = [1, 2, 3, 4]
70
130
  assert_equal [1, 2, 3, 4], pa.clip.to_a
71
131
  pa.clip = [5, 6, 7, 8]
72
132
  assert_equal [5, 6, 7, 8], pa.clip.to_a
73
- pa.clip 1, 2, 3, 4
133
+ pa.clip 1, 2, 3, 4
74
134
  assert_equal [1, 2, 3, 4], pa.clip.to_a
75
135
  pa.push clip: [5, 6, 7, 8] do |_|
76
136
  assert_equal [5, 6, 7, 8], pa.clip.to_a
@@ -85,7 +145,7 @@ class TestPainter < Test::Unit::TestCase
85
145
  assert_equal f10, pa.font
86
146
  pa.font = f20
87
147
  assert_equal f20, pa.font
88
- pa.font f10
148
+ pa.font f10
89
149
  assert_equal f10, pa.font
90
150
  pa.push font: f20 do |_|
91
151
  assert_equal f20, pa.font
@@ -179,4 +179,12 @@ class TestPoint < Test::Unit::TestCase
179
179
  assert_equal "#<Rays::Point 1.0, 2.0, 3.0>", point(1, 2, 3).inspect
180
180
  end
181
181
 
182
+ def test_dot ()
183
+ assert_equal 1*4 + 2*5 + 3*6, Rays::Point::dot(point(1, 2, 3), point(4, 5, 6))
184
+ end
185
+
186
+ def test_cross ()
187
+ assert_equal point(0, 0, 1), Rays::Point::cross(point(1, 0, 0), point(0, 1, 0))
188
+ end
189
+
182
190
  end# TestPoint
@@ -68,6 +68,32 @@ class TestPolyline < Test::Unit::TestCase
68
68
  }
69
69
  end
70
70
 
71
+ def test_expand_with_cap ()
72
+ def pl; polyline [10,10], [20,20]; end
73
+ assert_nothing_raised {pl.expand 1, Rays::CAP_ROUND}
74
+ assert_nothing_raised {pl.expand 1, 'ROUND'}
75
+ assert_nothing_raised {pl.expand 1, :ROUND}
76
+ assert_nothing_raised {pl.expand 1, :round}
77
+ assert_nothing_raised {pl.expand 1, 1}
78
+ assert_raise(ArgumentError) {pl.expand 1, -1}
79
+ assert_raise(ArgumentError) {pl.expand 1, 99}
80
+ assert_raise(ArgumentError) {pl.expand 1, 'hoge'}
81
+ assert_raise(ArgumentError) {pl.expand 1, :hoge}
82
+ end
83
+
84
+ def test_expand_with_join ()
85
+ def pl; polyline [10,10], [20,20]; end
86
+ assert_nothing_raised {pl.expand 1, Rays::JOIN_ROUND}
87
+ assert_nothing_raised {pl.expand 1, 'ROUND'}
88
+ assert_nothing_raised {pl.expand 1, :ROUND}
89
+ assert_nothing_raised {pl.expand 1, :round}
90
+ assert_nothing_raised {pl.expand 1, 1}
91
+ assert_raise(ArgumentError) {pl.expand 1, 'hoge'}
92
+ assert_raise(ArgumentError) {pl.expand 1, :hoge}
93
+ assert_raise(ArgumentError) {pl.expand 1, -1}
94
+ assert_raise(ArgumentError) {pl.expand 1, 99}
95
+ end
96
+
71
97
  def test_transform_with_materix ()
72
98
  m = Rays::Matrix.translate 100, 200
73
99
  polyline([10,10], [20,20]).transform(m).tap {|o|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rays
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.15
4
+ version: 0.1.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - xordog
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-16 00:00:00.000000000 Z
11
+ date: 2020-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: xot
@@ -47,6 +47,7 @@ extra_rdoc_files:
47
47
  - ".doc/ext/rays/defs.cpp"
48
48
  - ".doc/ext/rays/image.cpp"
49
49
  - ".doc/ext/rays/bitmap.cpp"
50
+ - ".doc/ext/rays/camera.cpp"
50
51
  - ".doc/ext/rays/rays.cpp"
51
52
  - ".doc/ext/rays/font.cpp"
52
53
  - ".doc/ext/rays/color_space.cpp"
@@ -64,6 +65,7 @@ extra_rdoc_files:
64
65
  files:
65
66
  - ".doc/ext/rays/bitmap.cpp"
66
67
  - ".doc/ext/rays/bounds.cpp"
68
+ - ".doc/ext/rays/camera.cpp"
67
69
  - ".doc/ext/rays/color.cpp"
68
70
  - ".doc/ext/rays/color_space.cpp"
69
71
  - ".doc/ext/rays/defs.cpp"
@@ -85,6 +87,7 @@ files:
85
87
  - VERSION
86
88
  - ext/rays/bitmap.cpp
87
89
  - ext/rays/bounds.cpp
90
+ - ext/rays/camera.cpp
88
91
  - ext/rays/color.cpp
89
92
  - ext/rays/color_space.cpp
90
93
  - ext/rays/defs.cpp
@@ -105,6 +108,7 @@ files:
105
108
  - include/rays.h
106
109
  - include/rays/bitmap.h
107
110
  - include/rays/bounds.h
111
+ - include/rays/camera.h
108
112
  - include/rays/color.h
109
113
  - include/rays/color_space.h
110
114
  - include/rays/coord.h
@@ -124,6 +128,7 @@ files:
124
128
  - include/rays/ruby.h
125
129
  - include/rays/ruby/bitmap.h
126
130
  - include/rays/ruby/bounds.h
131
+ - include/rays/ruby/camera.h
127
132
  - include/rays/ruby/color.h
128
133
  - include/rays/ruby/color_space.h
129
134
  - include/rays/ruby/font.h
@@ -140,6 +145,7 @@ files:
140
145
  - lib/rays/autoinit.rb
141
146
  - lib/rays/bitmap.rb
142
147
  - lib/rays/bounds.rb
148
+ - lib/rays/camera.rb
143
149
  - lib/rays/color.rb
144
150
  - lib/rays/color_space.rb
145
151
  - lib/rays/ext.rb
@@ -168,7 +174,9 @@ files:
168
174
  - src/frame_buffer.h
169
175
  - src/image.cpp
170
176
  - src/image.h
177
+ - src/ios/bitmap.h
171
178
  - src/ios/bitmap.mm
179
+ - src/ios/camera.mm
172
180
  - src/ios/font.mm
173
181
  - src/ios/helper.h
174
182
  - src/ios/helper.mm
@@ -179,7 +187,9 @@ files:
179
187
  - src/noise.cpp
180
188
  - src/opengl.cpp
181
189
  - src/opengl.h
190
+ - src/osx/bitmap.h
182
191
  - src/osx/bitmap.mm
192
+ - src/osx/camera.mm
183
193
  - src/osx/font.mm
184
194
  - src/osx/helper.h
185
195
  - src/osx/helper.mm
@@ -227,7 +237,7 @@ files:
227
237
  homepage: https://github.com/xord/rays
228
238
  licenses: []
229
239
  metadata: {}
230
- post_install_message:
240
+ post_install_message:
231
241
  rdoc_options: []
232
242
  require_paths:
233
243
  - lib
@@ -243,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
243
253
  version: '0'
244
254
  requirements: []
245
255
  rubygems_version: 3.0.3
246
- signing_key:
256
+ signing_key:
247
257
  specification_version: 4
248
258
  summary: A Drawing Engine using OpenGL.
249
259
  test_files: