NSView in OS 10.11 El Capitan Throwing Errors - opengl

I have an OpenGL application I'm running in Xcode 7.0.1 on a 2011 MacBookPro.
I recently upgraded from OS 10.10 to 10.11 El Capitan, and now windows with NSViews are throwing this error (Deployment Target 10.11, 10.10 or 10.9):
invalid context 0x0. If you want to see the backtrace, please set
CG_CONTEXT_SHOW_BACKTRACE environmental variable.
In the NSView drawRect method, I get the CGContext with the following statement:
CGContextRef context = [[NSGraphicsContext currentContext] CGContext];
Also, my GLSL 4.1 shaders don't write anything to the OpenGL window anymore.
This code was not giving me any problems before I upgraded to El Capitan, and the (almost) exact same code runs fine without errors on a 2012 MacBookPro, OS 10.10, Xcode 6.4, Deployment Target 10.9 or 10.10. The only code difference is that the graphics context in the NSView drawRect method is obtained with:
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
I think my problem might be that the computer that has problems is a 2011 MacBookPro, and Metal requires 2012 or later. I'm not using Metal, but I still think this might be a factor.
Is the computer vintage the problem that generates the error, or is there some other syntax I should be using to get the graphics context?
I have no idea why the GLSL shaders don't work anymore. Any ideas there?
The application main window is an OpenGL view, but I use many NSViews in pop up user interface windows, custom buttons and various other uses. Below is the complete code for one of the simplest of those windows. Again, this all ran fine before I upgraded to EC and Xcode 7.0.1.
#implementation StatusView
// **************************** Init **********************************
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
}
return self;
}
// ************************** Draw Rect ********************************
- (void)drawRect:(NSRect)dirtyRect
{
if(windowManager)
{
CGContextRef context = [[NSGraphicsContext currentContext] CGContext];
// Define a color space variable
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
// Get the bounds
NSRect nsBounds = [self bounds];
// Set the graphics bounds
CGRect cgBounds = NSRectToCGRect(nsBounds);
// ****** Draw the Background in Transparent Black
CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 0.0f);
CGContextFillRect(context, cgBounds);
// Set the text matrix.
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
// Create a color that will be added as an attribute to the attrString for normal text.
CGFloat textColorComponents[] = { 1.0, 1.0, 1.0, 1.0 };
CGColorRef whiteColor = CGColorCreate(rgbColorspace, textColorComponents);
// Create a color that will be added as an attribute to the attrString for invisible text.
CGFloat invisibleTextColorComponents[] = { 0.0, 0.0, 0.0, 0.0 };
CGColorRef invisibleColor = CGColorCreate(rgbColorspace, invisibleTextColorComponents);
// Create a font for normal text.
CFStringRef stringFontName = CFSTR("AppleCasual");
CTFontRef stringFont = CTFontCreateWithName(stringFontName, 18.0, NULL);
CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 0.0f);
CGContextFillRect(context, cgBounds);
// ************* Box the Window in Gray ***************************
CGContextMoveToPoint(context, 0.0,1.0);
CGContextAddLineToPoint(context,0.0, cgBounds.size.height - 1.0);
CGContextAddLineToPoint(context,cgBounds.size.width - 2.0, cgBounds.size.height - 1.0);
CGContextAddLineToPoint(context,cgBounds.size.width - 2.0, 1.0);
CGContextAddLineToPoint(context,0.0, 1.0);
CGContextSetLineWidth(context, 2.0);
CGContextSetRGBStrokeColor(context, 0.7, 0.7, 0.7, 1.0);
CGContextStrokePath(context);
// *********** Draw String1
CGPoint endingTextPoint;
if(windowManager->statusTextBox1String)
{
// Create a mutable attributed string with a max length of 0 for normal text.
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
// Create a path which will bound the area where you will be drawing text.
CGMutablePathRef invisibleTextPath = CGPathCreateMutable();
// Create a path which will bound the area where you will be drawing text.
CGMutablePathRef string1TextPath = CGPathCreateMutable();
// Initialize a string.
CFStringRef textString = (__bridge CFStringRef)windowManager->statusTextBox1String;
CFIndex textStringLength = CFStringGetLength (textString);
// Measure the string length
CGRect invisibleTextBounds = CGRectMake(0.0, 0.0, cgBounds.size.width, 30.0);
CGPathAddRect(invisibleTextPath, NULL, invisibleTextBounds);
// Copy the textString into attrString
CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), textString);
// Set the color and font.
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTForegroundColorAttributeName, invisibleColor);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTFontAttributeName, stringFont);
// Create the framesetter with the attributed string.
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), invisibleTextPath, NULL);
// Draw the specified frame in the given context.
CTFrameDraw(frame, context);
endingTextPoint = CGContextGetTextPosition(context);
// Draw the Text
// Set a rectangular path.
CGRect textBounds = CGRectMake((cgBounds.size.width / 2.0) - (endingTextPoint.x / 2.0), 140.0, cgBounds.size.width, 30.0);
CGPathAddRect(string1TextPath, NULL, textBounds);
// Copy the textString into attrString
CFAttributedStringReplaceString (attrString, CFRangeMake(0, textStringLength), textString);
// Set the color and fontof the first chars.
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTForegroundColorAttributeName, whiteColor);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTFontAttributeName, stringFont);
// Create the framesetter with the attributed string.
framesetter = CTFramesetterCreateWithAttributedString(attrString);
// Create a frame.
frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), string1TextPath, NULL);
// Draw the specified frame in the given context.
CTFrameDraw(frame, context);
CFRelease(string1TextPath);
CFRelease(invisibleTextPath);
CFRelease(frame);
CFRelease(framesetter);
CFRelease(attrString);
}
// ****************** Draw String 2
if(windowManager->statusTextBox2String)
{
CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 0.0f);
CGContextFillRect(context, cgBounds);
// ********** Box the Window in Gray ***********************
CGContextMoveToPoint(context, 0.0,1.0);
CGContextAddLineToPoint(context,0.0, cgBounds.size.height - 1.0);
CGContextAddLineToPoint(context,cgBounds.size.width - 2.0, cgBounds.size.height - 1.0);
CGContextAddLineToPoint(context,cgBounds.size.width - 2.0, 1.0);
CGContextAddLineToPoint(context,0.0, 1.0);
CGContextSetLineWidth(context, 2.0);
CGContextSetRGBStrokeColor(context, 0.7, 0.7, 0.7, 1.0);
CGContextStrokePath(context);
// Create a mutable attributed string with a max length of 0 for normal text.
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
// Create a path which will bound the area where you will be drawing text.
CGMutablePathRef invisibleTextPath = CGPathCreateMutable();
// Create a path which will bound the area where you will be drawing text.
CGMutablePathRef string2TextPath = CGPathCreateMutable();
// Initialize a string.
CFStringRef textString = (__bridge CFStringRef)windowManager->statusTextBox2String;
CFIndex textStringLength = CFStringGetLength (textString);
// Measure the string length
CGRect invisibleTextBounds = CGRectMake(0.0, 0.0, cgBounds.size.width, 130.0);
CGPathAddRect(invisibleTextPath, NULL, invisibleTextBounds);
// Copy the textString into attrString
CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), textString);
// Set the color and font
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTForegroundColorAttributeName, invisibleColor);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTFontAttributeName, stringFont);
// Create the framesetter with the attributed string.
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), invisibleTextPath, NULL);
// Draw the specified frame in the given context.
CTFrameDraw(frame, context);
endingTextPoint = CGContextGetTextPosition(context);
// Draw the Text
// Set a rectangular path.
CGRect textBounds = CGRectMake((cgBounds.size.width / 2.0) - (endingTextPoint.x / 2.0), 100.0, cgBounds.size.width, 30.0);
CGPathAddRect(string2TextPath, NULL, textBounds);
// Copy the textString into attrString
CFAttributedStringReplaceString (attrString, CFRangeMake(0, textStringLength), textString);
// Set the color and fontof the first chars.
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTForegroundColorAttributeName, whiteColor);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTFontAttributeName, stringFont);
// Create the framesetter with the attributed string.
framesetter = CTFramesetterCreateWithAttributedString(attrString);
// Create a frame.
frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), string2TextPath, NULL);
// Draw the specified frame in the given context.
CTFrameDraw(frame, context);
CFRelease(string2TextPath);
CFRelease(invisibleTextPath);
CFRelease(frame);
CFRelease(framesetter);
CFRelease(attrString);
}
CFRelease(stringFont);
CFRelease(whiteColor);
CFRelease(invisibleColor);
CGContextFlush(context);
}
return;
}
#end
This is an image of what this particular window looks like:
The behavior is not consistent. For example, this status window should come up for each of several steps in the calculation process, but it looks like only every other window is displayed (e.g. steps 2, 4 and 6, but not 1, 3 or 5).
There are LOTS of errors being generated, but this is a sample backtrace from one of the errors:
Oct 9 10:23:30 WispFractals3D[746] <Error>: CGContextRestoreGState: invalid context 0x0. Backtrace:
<-[StatusWindowController updateStatusProgress:]+228>
<-[AppController updateStatusProgress:]+64>
<-[AppController runTheFractal:]+804>
<_os_activity_initiate+75>
<-[NSApplication sendAction:to:from:]+460>
<-[NSMenuItem _corePerformAction]+336>
<-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:]+114>
<_os_activity_initiate+75>
<-[NSMenu performActionForItemAtIndex:]+131>
<-[NSMenu _internalPerformActionForItemAtIndex:]+35>
<-[NSCarbonMenuImpl _carbonCommandProcessEvent:handlerCallRef:]+107>
<NSSLMMenuEventHandler+708>
<_ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec+1231>
<_ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec+404>
<SendEventToEventTarget+40>
<_ZL18SendHICommandEventjPK9HICommandjjhPKvP20OpaqueEventTargetRefS5_PP14OpaqueEventRef+411>
<SendMenuCommandWithContextAndModifiers+59>
<SendMenuItemSelectedEvent+188>
<_ZL19FinishMenuSelectionP13SelectionDataP10MenuResultS2_+96>
<_ZL14MenuSelectCoreP8MenuData5PointdjPP13OpaqueMenuRefPt+711>
<_HandleMenuSelection2+460>
<_NSHandleCarbonMenuEvent+277>
<_DPSNextEvent+1906>
<-[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:]+454>
<-[NSApplication run]+682>
<NSApplicationMain+1176>
<main+34>
The .xib file looks like this:
There's a custom progress indicator in this window (bounded by the two white squares) that's invisible, but it's there.
Sample code to display this window looks like:
[self showStatusWindowWithString1:#"Calculation Complete" String2:timeMessage ButtonOn:YES AbortOn:NO ProgressOn:NO ProgressMax:100.0 Title:#"Fractal Run Time"];
and the code for the showStatusWindow method is:
- (void)showStatusWindowWithString1:(NSString *)string1 String2:(NSString *)string2 ButtonOn:(BOOL)buttonon AbortOn:(BOOL)aborton ProgressOn:(BOOL)progresson ProgressMax:(double)progressmax Title:(NSString *)title
{
statusWindowTitle = title;
statusTextBox1String = string1;
statusTextBox2String = string2;
statusButtonOn = buttonon;
abortOn = aborton;
statusProgressOn = progresson;
statusProgressMax = progressmax;
if (!statusWindowController)
{
statusWindowController = [[StatusWindowController alloc] initWithWindowNibName:#"StatusWindow" Manager:self];
}
[[statusWindowController window] setTitle:statusWindowTitle];
[statusWindowController showWindow:self];
[fileStatusWindow makeKeyAndOrderFront:self];
appDelegate->fileStatusWindowOpenFlag = YES;
[appDelegate checkFlags];
return;
}
Ken Thomases diagnosed that the backtrace indicated that invalid context errors were being generated in [StatusWindowController updateStatusProgress:] (this updates a custom progress indicator).
I changed this method from:
- (void) updateStatusProgress:(double)statusprogress
{
[statusProgressIndicator setDoubleValue:statusprogress];
[statusProgressIndicator drawRect:[statusProgressIndicator bounds]];
}
To:
- (void) updateStatusProgress:(double)statusprogress
{
[statusProgressIndicator setDoubleValue:statusprogress];
[statusProgressIndicator setNeedsDisplay:YES];
}
It looked to me like the error messages were being generated in multiple places, but this one change stopped all error messages.
My next problem, was that the status window (image above) was not displaying every time it should, only sometimes. Again, this all worked fine in Yosemite, Xcode 6.4.
I've now found that when the status window does not display, I can get it to display by running it modally. Strange.
The last problem I'm working through is that the GLSL shaders are not writing to the OpenGL view as they should. I've tested that the shaders are loading and running by adding a line at the end of the fragment shader: fragColor = vec4(1.0, 0.0, 0.0, 1.0);, which turned the view totally red as it should.
The fragment shader actually should be sampling from a texture, so I loaded this texture with all (255, 0, 0, 255) to test the sampling by putting a simple sampling statement at the end of the fragment shader:
fragColor = texture(Texture, texCoord).rgba;
but nothing gets written, so there must be a problem with loading the texture into the shader. I'm working on that now.

The problem causing the "invalid context 0x0" messages was that you were directly calling -drawRect:. This has never been valid. -drawRect: is called by the framework after it has set up the appropriate graphics context and things like the coordinate transform to put the drawing in the right place in the window and clipping to the bounds of the view. If you call it at other times, then no context has been set up and nothing good can come of it.
If you must redraw immediately, you could call one of the -display... methods.
However, it's usually best to do as you've now done: simply mark the view as needing display and let Cocoa redraw it in due course.
You should probably post separate questions for the other issues.

I just did a quick build of one of my apps which hadn't been rebuilt under EC before. It all worked fine.
Perhaps you can post a bit more detail. The code and crash point?

Related

OGLFT draws text when GLStipple is used

I have an interesting bug that has been "bugging" me for a few days now.
I am currently using OpenGL to draw text on a screen. I am utilizing the OGLFT library to assist the drawing. This library actually uses the freetype2 library. I am actually not doing anything special with the text. I am only looking for monochromatic text.
Anyways, after implementing the library, I noticed that the text is only drawn correct when I have glStipple enabled. I believe that there is some interference issue between the OGLFT library and what I am enabling.
I was wondering if there is anyone out there with some experience on using the OGLFT library. I am posting a minimalist example of my code to demonstrate what is going on:
(Please note that there are some variables that are used to st the zoom factor of my glCanvas and the position of the camera and that this is only for 2D)
double _zoomX = 1.0;
double _zoomY = 1.0;
double _cameraX = 0;
double _cameraY = 0;
/* This function gets called everytime a draw routine is needed */
void modelDefinition::onPaintCanvas(wxPaintEvent &event)
{
wxGLCanvas::SetCurrent(*_geometryContext);// This will make sure the the openGL commands are routed to the wxGLCanvas object
wxPaintDC dc(this);// This is required for drawing
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
updateProjection();
OGLFT::Monochrome *testface = new OGLFT::Monochrome( "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 8);
testface->draw(0, 0, "test");
glEnable(GL_LINE_STIPPLE);// WHen I comment out this line, the text is unable to be drawn
glLineStipple(1, 0b0001100011000110);
glBegin(GL_LINES);
glVertex2d(_startPoint.x, _startPoint.y);
glVertex2d(_endPoint.x, _endPoint.y);
glEnd();
glDisable(GL_LINE_STIPPLE);
SwapBuffers();
}
void modelDefinition::updateProjection()
{
// First, load the projection matrix and reset the view to a default view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-_zoomX, _zoomX, -_zoomY, _zoomY, -1.0, 1.0);
//Reset to modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, (double)this->GetSize().GetWidth(), (double)this->GetSize().GetHeight());
/* This section will handle the translation (panning) and scaled (zooming).
* Needs to be called each time a draw occurs in order to update the placement of all the components */
if(_zoomX < 1e-9 || _zoomY < 1e-9)
{
_zoomX = 1e-9;
_zoomY = _zoomX;
}
if(_zoomX > 1e6 || _zoomY > 1e6)
{
_zoomX = 1e6;
_zoomY = _zoomX;
}
glTranslated(-_cameraX, -_cameraY, 0.0);
}
Also one thing to note is that the code below the glEnable(GL_LINE_STIPPLE); is required. It is as if the glStipple needs to be drawn correctly for the text to be displayed correctly.
Looking through your code, I believe that your intention is to render it as a greyscale? If so, then you can simply use the OGLFT::Grayscale *testface = new OGLFT::Grayscale( "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 8);
This will get what you need without having to worry about the issue that you posted. In fact, I recommend doing it this way too.

Cairo Fill with Transparency

I'm new to Cairo, trying to create text with transparent color and stroke. stroke color's transparency works but text fill color transparency transparency_value doesn't work.
If i reduce transparency_value , text color just gets darker(black) and increasing transparency_value makes text color brighter (green in my case)
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 640, 480);
cairo_t* cairo = cairo_create(surface);
cairo_set_font_face(cairo, myfont_face);
cairo_set_font_size(cairo, 25);
cairo_text_extents_t extents;
cairo_text_extents(cairo, "Hello World", &extents);
cairo_move_to(cairo, 200, 200);
cairo_text_path(cairo, "Hello World");
double transparency_value = 0.5;
cairo_set_source_rgba(cairo, 0,1,0,transparency_value ); //transparency doesn't work
//cairo_fill(cairo); //this didn't make a difference
cairo_fill_preserve(cairo);
cairo_set_source_rgba(cairo, 0.56, 0.76, 0.96, 0.5); //transparency works
cairo_set_line_width(cairo, 1.5);
cairo_stroke(cairo);
Could it be that you are drawing your text outside of the surface? In the following example I added a call to cairo_move_to(cr, 200, 200) and now I get the following result. (This is written in Lua and uses https://github.com/pavouk/lgi to call into cairo; comments indicate things that I changed compared to your version)
local cairo = require("lgi").cairo
local surface = cairo.ImageSurface.create(cairo.Format.ARGB32, 640, 480)
local cr = cairo.Context(surface)
local myfont_face = cr:get_font_face() -- I have to get this from somewhere
cr:move_to(200, 200) -- I added this line to make something appear
cr:set_font_face(myfont_face)
cr:set_font_size(25)
cr:text_path("Hello World")
local transparency_value = 0.5
cr:set_source_rgba(0, 1, 0, transparency_value)
-- cr:fill()
cr:fill_preserve()
cr:set_source_rgba(0.65, 0.76, 0.96, 0.5)
cr:set_line_width(5) -- changed from 1.5 to 5 to make it more prominent
cr:stroke()
surface:write_to_png("/tmp/out.png")
Edit: And this is the result when I change transparency_value to 0.1. Clearly, the result is different and transparency works correctly (when zooming in, you still see some faint green in the middle).

JOGL GL_SELECT picking fails

I am using the GL_SELECT method to achieve mouse selection in OpenGL using JOGL Java Library.
I know the method is deprecated and such, but it is a simple school assignment and this should do it.
However I am having some trouble: even though something is rendered in GL_SELECT mode, glRenderMode(GL_RENDER) returns zero hits. The problem is deterministic, but I don't see a kind of pattern; for example, if I have a sphere in the center, it works if I click on its upper part, but not on its lower part. For a cube, it only won't work on one specific face. For a rectangle it works alright.
I have tested commenting out the glRenderMode(GL_SELECT) to check if something was indeed being rendered and yes, I could see the shape, but even so glRenderMode(GL_RENDER) gave me zero.
EDIT: I have also tested removing the call to gluPickMatrix() and the glRenderMode(GL_SELECT), which gave me exactly the same as the normal (non-picking) render, so the projection and model view matrixes are set up correctly I think.
So, I don't think I am rendering incorrectly in select mode. What can be going on?
EDIT: maybe this could be a hardware problem, as the method is deprecated. Is that possible?
Thanks in advance.
// Get required information
point.y = getHeight() - point.y;
gl.glGetIntegerv(GL2.GL_VIEWPORT, view, 0);
// Setup OpenGL for selection
gl.glSelectBuffer(64, buffer);
gl.glRenderMode(GL2.GL_SELECT);
gl.glInitNames();
// Setup projection matrix
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
Util.glu.gluPickMatrix( point.x, point.y, 5.0, 5.0, view, 0 );
Util.glu.gluPerspective(camera.getFieldOfView(), getWidth() * 1.0 / getHeight(),
camera.getCloseDistance(), camera.getFarDistance() );
// Setup model view matrix for rendering
gl.glMatrixMode(GL2.GL_MODELVIEW);
camera.setView(gl); // Set to model view and use glLookAt
gl.glClear( GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );
// Render objects
for(int i = 0; i < shapeList.size(); i++) {
gl.glPushName(i);
// Execute transformations for translation/rotation/scale and render shape
shapeList.get(i).display(gl, false);
gl.glPopName();
}
// Process hits
hits = gl.glRenderMode(GL2.GL_RENDER);
System.out.println("Hits = " + hits);
// ... Process hits here ...
// Reset matrixes
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
camera.setView function:
public void setView( GL2 gl ) {
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
Util.glu.gluLookAt( eye[Axis.X], eye[Axis.Y], eye[Axis.Z],
target[Axis.X], target[Axis.Y], target[Axis.Z],
up[Axis.X], up[Axis.Y], up[Axis.Z] );
}

text in 3d space - how to carriage return? (openGL, C++, OSX)

Here is my if statement that detects a bomb threat (just a game I'm making)...
if (exodus2_bomb == 1)
{
float exodus2_theta_math = (exodus2_theta)/10.0*M_PI;
float exodus2_phi_math = (exodus2_phi)/10.0*2*M_PI;
r_exodus2_x = radius_exodus_pos * sin(exodus2_theta_math) * cos(exodus2_phi_math);
r_exodus2_y = radius_exodus_pos * sin(exodus2_theta_math) * sin(exodus2_phi_math);
r_exodus2_z = radius_exodus_pos * cos(exodus2_theta_math);
glPushMatrix();
glTranslatef(r_exodus2_x,r_exodus2_y,r_exodus2_z);
glColor3f (1.0, 0.0, 0.0);
glRasterPos3i(exodus2_x/10,exodus2_y/10,exodus2_z/10);
string exodus2 = "BOMB!!";
void * fontexodus2 = GLUT_BITMAP_HELVETICA_10;
for (string::iterator i = exodus2.begin(); i != exodus2.end(); ++i)
{
char c = *i;
glutBitmapCharacter(fontexodus2, c);
}
glEnd();
glPopMatrix();
glPushMatrix();
glTranslatef(r_exodus2_x,r_exodus2_y,r_exodus2_z);
glColor3f (1.0, 0.0, 0.0);
glRasterPos3i(exodus2_x/10,exodus2_y/10,exodus2_z/10);
string exodus2b = "\n THREAT LEVEL 1";
void * fontexodus2b = GLUT_BITMAP_HELVETICA_10;
for (string::iterator i = exodus2b.begin(); i != exodus2b.end(); ++i)
{
char c = *i;
glutBitmapCharacter(fontexodus2b, c);
}
glEnd();
glPopMatrix();
}
What I would like to have is a carriage return between "string exodus2" and "string exodus2b". However, it is always on one line. And I don't have the real estate onscreen for that.
Is it possible to add a carriage return somewhere in my string iterator?
Unfortunately, screwing around with "glTranslatef" and "glRasterPos3i" only results in the distance between the two lines of text NOT being consistent as I move the camera.
You need to render each string separately, and modify the raster position appropriate to reset the string's position. If you use glutBitmapHeight, you can determine how far you need to move the raster position "down" to emulate a new line.
If you want the strings to be positioned in 3D, but then to "act" like they're restricted to the same plane in 2D, you can use the glBitmap command to modify the raster position in screen space.
int lineHeight = glutBitmapHeight( font ); // number of pixels between "lines"
int stringLength = glutBitmapLength( font, s1 ); // returns length of string 1 in pixels
glutBitmap( 0, 0, 0, 0, -stringLength, lineHeight, NULL ); // move raster position
glutBitmapString( font, s2 );
the fifth and sixth parameters of glBitmap control how far the raster position is moved.
Alternatively, if you want these strings to be anchored in a position relative to the window, as compared to a point in your 3D space, check out glWindowPos.
By the way, all of these functions are deprecated with OpenGL 3.0, removed in OpenGL 3.1, unless you use a compatibility context in verisons of OpenGL greater than 3.2.

Java3d - Bad Normals using GeometryInfo

I'm working with Java3d under eclipse Indigo in windows. After finally modifying the StlLoader example and ObjLoad classes to get my STL files to load up, I get a result that looks like the below (I think from other questions these are definitely bad vector normals). Does anybody know why I might be having this problem? I am using SolidWorks to save the STL as an ASCII file and using a modification of the code for loading STL files given on java3d.org. Although I have only changed some appearance properties and fixed broken imports etc. I have confirmed that the facet normals put into "normList" below definitely match those from the file.
Example of Result:
Snippet of StlFile.java from http://www.java3d.org :
private SceneBase makeScene()
{
// Create Scene to pass back
SceneBase scene = new SceneBase();
BranchGroup group = new BranchGroup();
scene.setSceneGroup(group);
// Store the scene info on a GeometryInfo
GeometryInfo gi = new GeometryInfo(GeometryInfo.TRIANGLE_STRIP_ARRAY);
// Convert ArrayLists to arrays: only needed if file was not binary
if(this.Ascii)
{
coordArray = objectToPoint3Array(coordList);
normArray = objectToVectorArray(normList);
}
gi.setCoordinates(coordArray);
gi.setNormals(normArray);
gi.setStripCounts(stripCounts);
// Setting the Material Appearance
Appearance app = new Appearance();
// Coloring Attributes
ColoringAttributes catt = new ColoringAttributes();
catt.setShadeModel( ColoringAttributes.NICEST );
app.setColoringAttributes(catt);
Material mat = new Material(new Color3f(0.6f, 0.6f, 0.6f), // ambient
new Color3f(0, 0, 0), // emissive
new Color3f(0.6f, 0.6f, 0.6f), // diffuse
new Color3f(0.6f, 0.6f, 0.6f), // specular
10); // shininess
app.setMaterial(mat);
// Put geometry into Shape3d
Shape3D shape = new Shape3D(gi.getGeometryArray(), app);
group.addChild(shape);
scene.addNamedObject(objectName, shape);
return scene;
} // end of makeScene
If some areas on the surface are really black (0x000000), I would guess some of the normals are actually pointing inwards the model rather than to the outside.
You may check if vertices v1,v2,v3 for all the triangles are defined in right-hand order (just test if det(v1,v2,v3) > 0 ) and reorder points accordingly. Alternatively, detect the "opposite" normals and multiply them by -1