aboutsummaryrefslogtreecommitdiffstats
path: root/ardor3d-jogl
diff options
context:
space:
mode:
Diffstat (limited to 'ardor3d-jogl')
-rw-r--r--ardor3d-jogl/.settings/org.eclipse.jdt.core.prefs276
-rw-r--r--ardor3d-jogl/.settings/org.eclipse.jdt.ui.prefs114
-rw-r--r--ardor3d-jogl/pom.xml52
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java46
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglAwtCanvas.java90
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvas.java285
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvasRenderer.java250
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglDrawerRunnable.java19
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglLibraryPaths.java59
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtAwtCanvas.java94
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtWindow.java240
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/NewtWindowContainer.java18
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtFocusWrapper.java54
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtKey.java151
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtKeyboardWrapper.java128
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtMouseManager.java79
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtMouseWrapper.java310
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java247
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglPbufferTextureRenderer.java368
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglRenderer.java1757
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRenderer.java571
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRendererProvider.java49
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglBlendStateUtil.java424
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglClipStateUtil.java73
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglColorMaskStateUtil.java47
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglCullStateUtil.java103
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFogStateUtil.java169
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFragmentProgramStateUtil.java125
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglLightStateUtil.java412
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglMaterialStateUtil.java214
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglOffsetStateUtil.java91
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShaderObjectsStateUtil.java384
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShadingStateUtil.java57
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglStencilStateUtil.java198
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglTextureStateUtil.java1730
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglVertexProgramStateUtil.java129
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglWireframeStateUtil.java86
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglZBufferStateUtil.java98
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/shader/JoglShaderUtil.java418
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglRendererUtil.java107
-rw-r--r--ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglTextureUtil.java611
41 files changed, 10733 insertions, 0 deletions
diff --git a/ardor3d-jogl/.settings/org.eclipse.jdt.core.prefs b/ardor3d-jogl/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..7858c9b
--- /dev/null
+++ b/ardor3d-jogl/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,276 @@
+#Tue Apr 06 11:30:42 CDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=_
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=1
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/ardor3d-jogl/.settings/org.eclipse.jdt.ui.prefs b/ardor3d-jogl/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f479490
--- /dev/null
+++ b/ardor3d-jogl/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,114 @@
+#Sun Jan 04 11:43:23 CST 2009
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=true
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_serial_version_id=true
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=true
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=true
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=false
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=_ArdorLabs
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_ArdorLabs
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=ex
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\r\n * @return the ${bare_field_name}\r\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\r\n * @param ${param} the ${bare_field_name} to set\r\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\r\n * \r\n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">/**\r\n * Copyright (c) 2008-2010 Ardor Labs, Inc.\r\n *\r\n * This file is part of Ardor3D.\r\n *\r\n * Ardor3D is free software\: you can redistribute it and/or modify it \r\n * under the terms of its license which may be found in the accompanying\r\n * LICENSE file or at &lt;http\://www.ardor3d.com/LICENSE&gt;.\r\n */\r\n\r\n${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\r\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\r\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\r\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/ardor3d-jogl/pom.xml b/ardor3d-jogl/pom.xml
new file mode 100644
index 0000000..56c0800
--- /dev/null
+++ b/ardor3d-jogl/pom.xml
@@ -0,0 +1,52 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.ardor3d</groupId>
+ <artifactId>ardor3d</artifactId>
+ <relativePath>../pom.xml</relativePath>
+ <version>0.9-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>ardor3d-jogl</artifactId>
+ <packaging>bundle</packaging>
+ <name>Ardor 3D JOGL</name>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ardor3d-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jogamp.gluegen</groupId>
+ <artifactId>gluegen-rt-main</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jogamp.jogl</groupId>
+ <artifactId>jogl-all-main</artifactId>
+ </dependency>
+ <!--
+ <dependency>
+ <groupId>org.jogamp.joal</groupId>
+ <artifactId>joal-main</artifactId>
+ <version>2.0-rc11</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jogamp.jocl</groupId>
+ <artifactId>jocl-main</artifactId>
+ <version>2.0-rc11</version>
+ </dependency> -->
+ </dependencies>
+</project>
+
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java
new file mode 100644
index 0000000..c23b8a0
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.framework.jogl;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.ardor3d.framework.DisplaySettings;
+import com.ardor3d.util.Ardor3dException;
+
+public class CapsUtil {
+
+ public static GLCapabilities getCapsForSettings(final DisplaySettings settings) {
+
+ // Validate window dimensions.
+ if (settings.getWidth() <= 0 || settings.getHeight() <= 0) {
+ throw new Ardor3dException("Invalid resolution values: " + settings.getWidth() + " " + settings.getHeight());
+ }
+
+ // Validate bit depth.
+ if ((settings.getColorDepth() != 32) && (settings.getColorDepth() != 16) && (settings.getColorDepth() != 24)
+ && (settings.getColorDepth() != -1)) {
+ throw new Ardor3dException("Invalid pixel depth: " + settings.getColorDepth());
+ }
+
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true));
+ caps.setHardwareAccelerated(true);
+ caps.setDoubleBuffered(true);
+ caps.setAlphaBits(settings.getAlphaBits());
+ caps.setDepthBits(settings.getDepthBits());
+ caps.setNumSamples(settings.getSamples());
+ caps.setSampleBuffers(settings.getSamples() != 0);
+ caps.setStereo(settings.isStereo());
+ caps.setStencilBits(settings.getStencilBits());
+ return caps;
+ }
+
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglAwtCanvas.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglAwtCanvas.java
new file mode 100644
index 0000000..5c95cd8
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglAwtCanvas.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.framework.jogl;
+
+import java.util.concurrent.CountDownLatch;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.awt.GLCanvas;
+import com.ardor3d.annotation.MainThread;
+import com.ardor3d.framework.Canvas;
+import com.ardor3d.framework.DisplaySettings;
+
+/**
+ * FIXME there is still a deadlock when using several instances of this class in the same container, see JOGL bug 572
+ * Rather use JoglNewtAwtCanvas in this case.
+ *
+ */
+public class JoglAwtCanvas extends GLCanvas implements Canvas {
+
+ private static final long serialVersionUID = 1L;
+
+ private final JoglCanvasRenderer _canvasRenderer;
+ private boolean _inited = false;
+
+ private final DisplaySettings _settings;
+
+ private final JoglDrawerRunnable _drawerGLRunnable;
+
+ public JoglAwtCanvas(final DisplaySettings settings, final JoglCanvasRenderer canvasRenderer) {
+ super(CapsUtil.getCapsForSettings(settings));
+ _drawerGLRunnable = new JoglDrawerRunnable(canvasRenderer);
+ _settings = settings;
+ _canvasRenderer = canvasRenderer;
+
+ setFocusable(true);
+ requestFocus();
+ setSize(_settings.getWidth(), _settings.getHeight());
+ setIgnoreRepaint(true);
+ setAutoSwapBufferMode(false);
+ }
+
+ @MainThread
+ public void init() {
+ if (_inited) {
+ return;
+ }
+
+ // Make the window visible to realize the OpenGL surface.
+ setVisible(true);
+
+ // Request the focus here as it cannot work when the window is not visible
+ requestFocus();
+
+ _canvasRenderer.setContext(getContext());
+
+ invoke(true, new GLRunnable() {
+ @Override
+ public boolean run(GLAutoDrawable glAutoDrawable) {
+ _canvasRenderer.init(_settings, true);// true - do swap in renderer.
+ return true;
+ }
+ });
+ _inited = true;
+ }
+
+ public void draw(final CountDownLatch latch) {
+ if (!_inited) {
+ init();
+ }
+
+ if (isShowing()) {
+ invoke(true, _drawerGLRunnable);
+ }
+ if (latch != null) {
+ latch.countDown();
+ }
+ }
+
+ public JoglCanvasRenderer getCanvasRenderer() {
+ return _canvasRenderer;
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvas.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvas.java
new file mode 100644
index 0000000..c08396b
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvas.java
@@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.framework.jogl;
+
+import java.awt.Dimension;
+import java.awt.DisplayMode;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Toolkit;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLRunnable;
+
+import com.ardor3d.annotation.MainThread;
+import com.ardor3d.framework.CanvasRenderer;
+import com.ardor3d.framework.DisplaySettings;
+import com.ardor3d.framework.NativeCanvas;
+import com.ardor3d.image.Image;
+import com.ardor3d.renderer.jogl.JoglPbufferTextureRenderer;
+
+/**
+ * A canvas implementation for use with native JOGL windows.
+ */
+public class JoglCanvas extends Frame implements NativeCanvas {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final Logger logger = Logger.getLogger(JoglCanvas.class.getName());
+
+ private final DisplaySettings _settings;
+ private boolean _inited = false;
+ private boolean _isClosing = false;
+
+ private JoglAwtCanvas _glCanvas;
+
+ public JoglCanvas(final JoglCanvasRenderer canvasRenderer, final DisplaySettings settings) {
+ _settings = settings;
+
+ // Create the OpenGL canvas
+ _glCanvas = new JoglAwtCanvas(_settings, canvasRenderer);
+
+ // Default is not-resizeable. If you turn on resizeable, know what you are doing.
+ setResizable(false);
+ }
+
+ @Override
+ public void addKeyListener(final KeyListener l) {
+ _glCanvas.addKeyListener(l);
+ }
+
+ @Override
+ public void addMouseListener(final MouseListener l) {
+ _glCanvas.addMouseListener(l);
+ }
+
+ @Override
+ public void addMouseMotionListener(final MouseMotionListener l) {
+ _glCanvas.addMouseMotionListener(l);
+ }
+
+ @Override
+ public void addMouseWheelListener(final MouseWheelListener l) {
+ _glCanvas.addMouseWheelListener(l);
+ }
+
+ @Override
+ public void addFocusListener(final FocusListener l) {
+ _glCanvas.addFocusListener(l);
+ }
+
+ @MainThread
+ public void init() {
+ privateInit();
+ }
+
+ @MainThread
+ protected void privateInit() {
+ if (_inited) {
+ return;
+ }
+
+ // FIXME: remove need for directly setting _parentContext.
+ JoglPbufferTextureRenderer._parentContext = _glCanvas.getContext();
+
+ this.add(_glCanvas);
+
+ final boolean isDisplayModeModified;
+ final GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
+ // Get the current display mode
+ final DisplayMode previousDisplayMode = gd.getDisplayMode();
+ // Handle full screen mode if requested.
+ if (_settings.isFullScreen()) {
+ setUndecorated(true);
+ // Check if the full-screen mode is supported by the OS
+ boolean isFullScreenSupported = gd.isFullScreenSupported();
+ if (isFullScreenSupported) {
+ gd.setFullScreenWindow(this);
+ // Check if display mode changes are supported by the OS
+ if (gd.isDisplayChangeSupported()) {
+ // Get all available display modes
+ final DisplayMode[] displayModes = gd.getDisplayModes();
+ DisplayMode multiBitsDepthSupportedDisplayMode = null;
+ DisplayMode refreshRateUnknownDisplayMode = null;
+ DisplayMode multiBitsDepthSupportedAndRefreshRateUnknownDisplayMode = null;
+ DisplayMode matchingDisplayMode = null;
+ DisplayMode currentDisplayMode;
+ // Look for the display mode that matches with our parameters
+ // Look for some display modes that are close to these parameters
+ // and that could be used as substitutes
+ // On some machines, the refresh rate is unknown and/or multi bit
+ // depths are supported. If you try to force a particular refresh
+ // rate or a bit depth, you might find no available display mode
+ // that matches exactly with your parameters
+ for (int i = 0; i < displayModes.length && matchingDisplayMode == null; i++) {
+ currentDisplayMode = displayModes[i];
+ if (currentDisplayMode.getWidth() == _settings.getWidth()
+ && currentDisplayMode.getHeight() == _settings.getHeight()) {
+ if (currentDisplayMode.getBitDepth() == _settings.getColorDepth()) {
+ if (currentDisplayMode.getRefreshRate() == _settings.getFrequency()) {
+ matchingDisplayMode = currentDisplayMode;
+ } else if (currentDisplayMode.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN) {
+ refreshRateUnknownDisplayMode = currentDisplayMode;
+ }
+ } else if (currentDisplayMode.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI) {
+ if (currentDisplayMode.getRefreshRate() == _settings.getFrequency()) {
+ multiBitsDepthSupportedDisplayMode = currentDisplayMode;
+ } else if (currentDisplayMode.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN) {
+ multiBitsDepthSupportedAndRefreshRateUnknownDisplayMode = currentDisplayMode;
+ }
+ }
+ }
+ }
+ DisplayMode nextDisplayMode = null;
+ if (matchingDisplayMode != null) {
+ nextDisplayMode = matchingDisplayMode;
+ } else if (multiBitsDepthSupportedDisplayMode != null) {
+ nextDisplayMode = multiBitsDepthSupportedDisplayMode;
+ } else if (refreshRateUnknownDisplayMode != null) {
+ nextDisplayMode = refreshRateUnknownDisplayMode;
+ } else if (multiBitsDepthSupportedAndRefreshRateUnknownDisplayMode != null) {
+ nextDisplayMode = multiBitsDepthSupportedAndRefreshRateUnknownDisplayMode;
+ } else {
+ isFullScreenSupported = false;
+ }
+ // If we have found a display mode that approximatively matches
+ // with the input parameters, use it
+ if (nextDisplayMode != null) {
+ gd.setDisplayMode(nextDisplayMode);
+ isDisplayModeModified = true;
+ } else {
+ isDisplayModeModified = false;
+ }
+ } else {
+ isDisplayModeModified = false;
+ // Resize the canvas if the display mode cannot be changed
+ // and the screen size is not equal to the canvas size
+ final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ if (screenSize.width != _settings.getWidth() || screenSize.height != _settings.getHeight()) {
+ _glCanvas.setSize(screenSize);
+ }
+ }
+ } else {
+ isDisplayModeModified = false;
+ }
+
+ // Software windowed full-screen mode
+ if (!isFullScreenSupported) {
+ final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ // Resize the canvas
+ _glCanvas.setSize(screenSize);
+ // Resize the frame so that it occupies the whole screen
+ this.setSize(screenSize);
+ // Set its location at the top left corner
+ this.setLocation(0, 0);
+ }
+ }
+ // Otherwise, center the window on the screen.
+ else {
+ isDisplayModeModified = false;
+ pack();
+
+ int x, y;
+ x = (Toolkit.getDefaultToolkit().getScreenSize().width - _settings.getWidth()) / 2;
+ y = (Toolkit.getDefaultToolkit().getScreenSize().height - _settings.getHeight()) / 2;
+ this.setLocation(x, y);
+ }
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(final WindowEvent e) {
+ _isClosing = true;
+ // If required, restore the previous display mode
+ if (isDisplayModeModified) {
+ gd.setDisplayMode(previousDisplayMode);
+ }
+ // If required, get back to the windowed mode
+ if (gd.getFullScreenWindow() == JoglCanvas.this) {
+ gd.setFullScreenWindow(null);
+ }
+ }
+ });
+
+ // Make the window visible to realize the OpenGL surface.
+ setVisible(true);
+
+ _glCanvas.init(); // true - do swap in renderer.
+ _inited = true;
+ }
+
+ public void draw(final CountDownLatch latch) {
+ if (!_inited) {
+ privateInit();
+ }
+
+ _glCanvas.draw(latch);
+ }
+
+ public CanvasRenderer getCanvasRenderer() {
+ return _glCanvas.getCanvasRenderer();
+ }
+
+ public void close() {
+ try {
+ if (GLContext.getCurrent() != null) {
+ // Release the OpenGL resources.
+ GLContext.getCurrent().release();
+ }
+ } catch (final GLException releaseFailure) {
+ logger.log(Level.WARNING, "Failed to release OpenGL Context: " + _glCanvas, releaseFailure);
+ } finally {
+ _glCanvas = null;
+ }
+
+ // Dispose of any window resources.
+ dispose();
+ }
+
+ @Override
+ public boolean isActive() {
+ return hasFocus();
+ }
+
+ public boolean isClosing() {
+ return _isClosing;
+ }
+
+ public void moveWindowTo(final int locX, final int locY) {
+ setLocation(locX, locY);
+ }
+
+ public void setIcon(final Image[] iconImages) {
+ // FIXME not implemented
+ }
+
+ public void setVSyncEnabled(final boolean enabled) {
+ _glCanvas.invoke(true, new GLRunnable() {
+ @Override
+ public boolean run(GLAutoDrawable glAutoDrawable) {
+ _glCanvas.getGL().setSwapInterval(enabled ? 1 : 0);
+ return false;
+ }
+ });
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvasRenderer.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvasRenderer.java
new file mode 100644
index 0000000..e6d8b00
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvasRenderer.java
@@ -0,0 +1,250 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.framework.jogl;
+
+import java.util.logging.Logger;
+
+import javax.media.opengl.DebugGL2;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.annotation.MainThread;
+import com.ardor3d.framework.CanvasRenderer;
+import com.ardor3d.framework.DisplaySettings;
+import com.ardor3d.framework.Scene;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.renderer.Camera;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.Camera.ProjectionMode;
+import com.ardor3d.renderer.jogl.JoglContextCapabilities;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.util.Ardor3dException;
+
+public class JoglCanvasRenderer implements CanvasRenderer {
+
+ private static final Logger LOGGER = Logger.getLogger(JoglCanvasRenderer.class.getName());
+
+ protected Scene _scene;
+ protected Camera _camera;
+ protected boolean _doSwap;
+ protected GLContext _context;
+ protected JoglRenderer _renderer;
+ protected int _frameClear = Renderer.BUFFER_COLOR_AND_DEPTH;
+
+ private RenderContext _currentContext;
+
+ /**
+ * <code>true</code> if debugging (checking for error codes on each GL call) is desired.
+ */
+ private final boolean _useDebug;
+
+ /**
+ * <code>true</code> if debugging is currently enabled for this GLContext.
+ */
+ private boolean _debugEnabled = false;
+
+ public JoglCanvasRenderer(final Scene scene) {
+ this(scene, false);
+ }
+
+ public JoglCanvasRenderer(final Scene scene, final boolean useDebug) {
+ _scene = scene;
+ _useDebug = useDebug;
+ }
+
+ public void makeCurrentContext() throws Ardor3dException {
+ int value = GLContext.CONTEXT_NOT_CURRENT;
+ int attempt = 0;
+ do {
+ try {
+ value = _context.makeCurrent();
+ } catch(GLException gle) {
+ gle.printStackTrace();
+ } finally {
+ attempt++;
+ if (attempt == MAX_CONTEXT_GRAB_ATTEMPTS) {
+ // failed, throw exception
+ throw new Ardor3dException("Failed to claim OpenGL context.");
+ }
+ }
+ try {
+ Thread.sleep(5);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ }
+ while(value == GLContext.CONTEXT_NOT_CURRENT);
+ if (value == GLContext.CONTEXT_CURRENT_NEW) {
+ ContextManager.getCurrentContext().contextLost();
+
+ // Whenever the context is created or replaced, the GL chain
+ // is lost. Debug will have to be added if desired.
+ _debugEnabled = false;
+ }
+
+ ContextManager.switchContext(_context);
+ }
+
+ public void releaseCurrentContext() {
+ if (_context.equals(GLContext.getCurrent())) {
+ try {
+ _context.release();
+ } catch(GLException gle) {
+ gle.printStackTrace();
+ }
+ }
+ }
+
+ @MainThread
+ protected ContextCapabilities createContextCapabilities() {
+ return new JoglContextCapabilities(_context.getGL());
+ }
+
+ @MainThread
+ public void init(final DisplaySettings settings, final boolean doSwap) {
+ _doSwap = doSwap;
+ if (_context == null) {
+ _context = GLDrawableFactory.getFactory(GLProfile.getMaxFixedFunc(true)).createExternalGLContext();
+ }
+
+ _context.makeCurrent();
+
+ try {
+
+ // Look up a shared context, if a shared JoglCanvasRenderer is given.
+ RenderContext sharedContext = null;
+ if (settings.getShareContext() != null) {
+ sharedContext = ContextManager.getContextForKey(settings.getShareContext().getRenderContext()
+ .getContextKey());
+ }
+
+ final ContextCapabilities caps = createContextCapabilities();
+ _currentContext = new RenderContext(_context, caps, sharedContext);
+
+ ContextManager.addContext(_context, _currentContext);
+ ContextManager.switchContext(_context);
+
+ _renderer = new JoglRenderer();
+
+ if (settings.getSamples() != 0 && caps.isMultisampleSupported()) {
+ final GL gl = GLU.getCurrentGL();
+ gl.glEnable(GL.GL_MULTISAMPLE);
+ }
+
+ _renderer.setBackgroundColor(ColorRGBA.BLACK);
+
+ if (_camera == null) {
+ /** Set up how our camera sees. */
+ _camera = new Camera(settings.getWidth(), settings.getHeight());
+ _camera.setFrustumPerspective(45.0f, (float) settings.getWidth() / (float) settings.getHeight(), 1, 1000);
+ _camera.setProjectionMode(ProjectionMode.Perspective);
+
+ final Vector3 loc = new Vector3(0.0f, 0.0f, 10.0f);
+ final Vector3 left = new Vector3(-1.0f, 0.0f, 0.0f);
+ final Vector3 up = new Vector3(0.0f, 1.0f, 0.0f);
+ final Vector3 dir = new Vector3(0.0f, 0f, -1.0f);
+ /** Move our camera to a correct place and orientation. */
+ _camera.setFrame(loc, left, up, dir);
+ } else {
+ // use new width and height to set ratio.
+ _camera.setFrustumPerspective(_camera.getFovY(),
+ (float) settings.getWidth() / (float) settings.getHeight(), _camera.getFrustumNear(), _camera
+ .getFrustumFar());
+ }
+ } finally {
+ _context.release();
+ }
+ }
+
+ public GLContext getContext() {
+ return _context;
+ }
+
+ public void setContext(final GLContext context) {
+ _context = context;
+ }
+
+ public int MAX_CONTEXT_GRAB_ATTEMPTS = 10;
+
+ @MainThread
+ public boolean draw() {
+
+ // set up context for rendering this canvas
+ makeCurrentContext();
+
+ // Enable Debugging if requested.
+ if (_useDebug != _debugEnabled) {
+ _context.setGL(new DebugGL2(_context.getGL().getGL2()));
+ _debugEnabled = true;
+
+ LOGGER.info("DebugGL Enabled");
+ }
+
+ // render stuff, first apply our camera if we have one
+ if (_camera != null) {
+ if (Camera.getCurrentCamera() != _camera) {
+ _camera.update();
+ }
+ _camera.apply(_renderer);
+ }
+ _renderer.clearBuffers(_frameClear);
+
+ final boolean drew = _scene.renderUnto(_renderer);
+ _renderer.flushFrame(drew && _doSwap);
+
+ // release the context if we're done (swapped and all)
+ if (_doSwap) {
+ releaseCurrentContext();
+ }
+
+ return drew;
+ }
+
+ public Camera getCamera() {
+ return _camera;
+ }
+
+ public Scene getScene() {
+ return _scene;
+ }
+
+ public void setScene(final Scene scene) {
+ _scene = scene;
+ }
+
+ public Renderer getRenderer() {
+ return _renderer;
+ }
+
+ public void setCamera(final Camera camera) {
+ _camera = camera;
+ }
+
+ public RenderContext getRenderContext() {
+ return _currentContext;
+ }
+
+ public int getFrameClear() {
+ return _frameClear;
+ }
+
+ public void setFrameClear(final int buffers) {
+ _frameClear = buffers;
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglDrawerRunnable.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglDrawerRunnable.java
new file mode 100644
index 0000000..a3c00e8
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglDrawerRunnable.java
@@ -0,0 +1,19 @@
+package com.ardor3d.framework.jogl;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLRunnable;
+
+public class JoglDrawerRunnable implements GLRunnable {
+
+ private final JoglCanvasRenderer _canvasRenderer;
+
+ public JoglDrawerRunnable(final JoglCanvasRenderer canvasRenderer) {
+ _canvasRenderer = canvasRenderer;
+ }
+
+ @Override
+ public boolean run(GLAutoDrawable glAutoDrawable) {
+ _canvasRenderer.draw();
+ return true;
+ }
+} \ No newline at end of file
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglLibraryPaths.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglLibraryPaths.java
new file mode 100644
index 0000000..668e74e
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglLibraryPaths.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.framework.jogl;
+
+/**
+ * TODO: document this class!
+ *
+ */
+public enum JoglLibraryPaths {
+ MACOSX("Mac OS X", null, new String[] {
+ "/macosx/libgluegen-rt.jnilib",
+ "/macosx/libjogl.jnilib",
+ "/macosx/libjogl_awt.jnilib",
+ "/macosx/libjogl_cg.jnilib",
+ }),
+ WINDOWS_XP("Windows XP", null, new String[] {
+ "/win32/gluegen-rt.dll",
+ "/win32/jogl.dll",
+ "/win32/jogl_awt.dll",
+ "/win32/jogl_cg.dll",
+ });
+
+ private final String _operatingSystem;
+ private final String _architecture;
+ private final String[] _libraryPaths;
+
+
+ JoglLibraryPaths(String operatingSystem, String architecture, String[] libraryPaths) {
+ _operatingSystem = operatingSystem;
+ _architecture = architecture;
+ _libraryPaths = libraryPaths;
+ }
+
+ public static String[] getLibraryPaths(String operatingSystem, String architecture) {
+ for (JoglLibraryPaths libraryPath : JoglLibraryPaths.values()) {
+ if (operatingSystem.equals(libraryPath._operatingSystem) &&
+ (libraryPath._architecture == null || architecture.equals(libraryPath._architecture))) {
+ return libraryPath._libraryPaths;
+ }
+ }
+
+ throw new IllegalStateException("No matching set of library paths found for " + operatingSystem + ", " + architecture);
+ }
+
+ public static void main(String[] args) {
+ System.out.println(System.getProperty("os.name"));
+ System.out.println(System.getProperty("os.arch"));
+
+ System.getProperties();
+ }
+} \ No newline at end of file
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtAwtCanvas.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtAwtCanvas.java
new file mode 100644
index 0000000..8b2517a
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtAwtCanvas.java
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.framework.jogl;
+
+import java.util.concurrent.CountDownLatch;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLRunnable;
+import com.ardor3d.annotation.MainThread;
+import com.ardor3d.framework.Canvas;
+import com.ardor3d.framework.DisplaySettings;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+
+
+public class JoglNewtAwtCanvas extends NewtCanvasAWT implements Canvas, NewtWindowContainer {
+
+ private static final long serialVersionUID = 1L;
+
+ private final JoglCanvasRenderer _canvasRenderer;
+ private boolean _inited = false;
+
+ private final DisplaySettings _settings;
+
+ private final JoglDrawerRunnable _drawerGLRunnable;
+
+ public JoglNewtAwtCanvas(final DisplaySettings settings, final JoglCanvasRenderer canvasRenderer) {
+ super(GLWindow.create(CapsUtil.getCapsForSettings(settings)));
+ _drawerGLRunnable = new JoglDrawerRunnable(canvasRenderer);
+ getNewtWindow().setUndecorated(true);
+ _settings = settings;
+ _canvasRenderer = canvasRenderer;
+
+ setFocusable(true);
+ setSize(_settings.getWidth(), _settings.getHeight());
+ setIgnoreRepaint(true);
+ getNewtWindow().setAutoSwapBufferMode(false);
+ }
+
+ @MainThread
+ public void init() {
+ if (_inited) {
+ return;
+ }
+
+ // Make the window visible to realize the OpenGL surface.
+ setVisible(true);
+ // Request the focus here as it cannot work when the window is not visible
+ requestFocus();
+ /**
+ * I do not understand why I cannot get the context earlier, I failed in
+ * getting it from addNotify() and setVisible(true)
+ * */
+ _canvasRenderer.setContext(getNewtWindow().getContext());
+
+ getNewtWindow().invoke(true, new GLRunnable() {
+ @Override
+ public boolean run(GLAutoDrawable glAutoDrawable) {
+ _canvasRenderer.init(_settings, true);// true - do swap in renderer.
+ return true;
+ }
+ });
+ _inited = true;
+ }
+
+ public void draw(final CountDownLatch latch) {
+ if (!_inited) {
+ init();
+ }
+
+ if (isShowing()) {
+ getNewtWindow().invoke(true, _drawerGLRunnable);
+ }
+ if (latch != null) {
+ latch.countDown();
+ }
+ }
+
+ public JoglCanvasRenderer getCanvasRenderer() {
+ return _canvasRenderer;
+ }
+
+ @Override
+ public GLWindow getNewtWindow() {
+ return (GLWindow) getNEWTChild();
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtWindow.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtWindow.java
new file mode 100644
index 0000000..3333d90
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtWindow.java
@@ -0,0 +1,240 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.framework.jogl;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLRunnable;
+import com.ardor3d.annotation.MainThread;
+import com.ardor3d.framework.DisplaySettings;
+import com.ardor3d.framework.NativeCanvas;
+import com.ardor3d.image.Image;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.ScreenMode;
+import com.jogamp.newt.event.KeyListener;
+import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.ScreenModeUtil;
+
+
+public class JoglNewtWindow implements NativeCanvas, NewtWindowContainer {
+
+ private final JoglCanvasRenderer _canvasRenderer;
+ private boolean _inited = false;
+ private boolean _isClosing = false;
+
+ private final DisplaySettings _settings;
+
+ private final JoglDrawerRunnable _drawerGLRunnable;
+
+ private final GLWindow _newtWindow;
+
+ public JoglNewtWindow(final JoglCanvasRenderer canvasRenderer, final DisplaySettings settings) {
+ _newtWindow = GLWindow.create(CapsUtil.getCapsForSettings(settings));
+ _drawerGLRunnable = new JoglDrawerRunnable(canvasRenderer);
+ _settings = settings;
+ _canvasRenderer = canvasRenderer;
+ setAutoSwapBufferMode(false);
+ }
+
+ /**
+ * Applies all settings not related to OpenGL (screen resolution,
+ * screen size, etc...)
+ * */
+ private void applySettings() {
+ _newtWindow.setUndecorated(_settings.isFullScreen());
+ _newtWindow.setFullscreen(_settings.isFullScreen());
+ //FIXME Ardor3D does not allow to change the resolution
+ /**
+ * uses the filtering relying on resolution with the size to fetch only the screen
+ * mode matching with the current resolution
+ */
+ if (_settings.isFullScreen()) {
+ Screen screen = _newtWindow.getScreen();
+ List<ScreenMode> screenModes = screen.getScreenModes();
+ //the resolution is provided by the user
+ Dimension dimension=new Dimension(_settings.getWidth(),_settings.getHeight());
+ screenModes = ScreenModeUtil.filterByResolution(screenModes,dimension);
+ screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
+ if (_settings.getFrequency() > 0) {
+ screenModes = ScreenModeUtil.filterByRate(screenModes, _settings.getFrequency());
+ } else {
+ screenModes = ScreenModeUtil.getHighestAvailableRate(screenModes);
+ }
+ screen.setCurrentScreenMode(screenModes.get(0));
+ }
+ }
+
+ public void addKeyListener(KeyListener keyListener) {
+ _newtWindow.addKeyListener(keyListener);
+ }
+
+ public void addMouseListener(MouseListener mouseListener) {
+ _newtWindow.addMouseListener(mouseListener);
+ }
+
+ public void addWindowListener(WindowListener windowListener) {
+ _newtWindow.addWindowListener(windowListener);
+ }
+
+ public GLContext getContext() {
+ return _newtWindow.getContext();
+ }
+
+ public int getWidth() {
+ return _newtWindow.getWidth();
+ }
+
+ public int getHeight() {
+ return _newtWindow.getHeight();
+ }
+
+ public int getX() {
+ return _newtWindow.getX();
+ }
+
+ public int getY() {
+ return _newtWindow.getY();
+ }
+
+ public boolean isVisible() {
+ return _newtWindow.isVisible();
+ }
+
+ public void setSize(int width, int height) {
+ _newtWindow.setTopLevelSize(width, height);
+ }
+
+ public void setVisible(boolean visible) {
+ _newtWindow.setVisible(visible);
+ }
+
+ public void setAutoSwapBufferMode(boolean autoSwapBufferModeEnabled) {
+ _newtWindow.setAutoSwapBufferMode(autoSwapBufferModeEnabled);
+ }
+
+ @MainThread
+ public void init() {
+ if (_inited) {
+ return;
+ }
+
+ _newtWindow.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
+ _isClosing = true;
+ }
+
+// public void windowResized(final WindowEvent e) {
+// _newtWindow.invoke(true, new GLRunnable() {
+//
+// @Override
+// public boolean run(GLAutoDrawable glAutoDrawable) {
+// _canvasRenderer._camera.resize(_newtWindow.getWidth(), _newtWindow.getHeight());
+// _canvasRenderer._camera.setFrustumPerspective(_canvasRenderer._camera.getFovY(),
+// (float) _newtWindow.getWidth() / (float) _newtWindow.getHeight(),
+// _canvasRenderer._camera.getFrustumNear(),
+// _canvasRenderer._camera.getFrustumFar());
+// return true;
+// }
+// });
+// }
+ });
+
+ // Set the size very early to prevent the default one from being used (typically when exiting full screen mode)
+ setSize(_settings.getWidth(), _settings.getHeight());
+ // Make the window visible to realize the OpenGL surface.
+ setVisible(true);
+ // Request the focus here as it cannot work when the window is not visible
+ _newtWindow.requestFocus();
+ applySettings();
+
+ _canvasRenderer.setContext(getContext());
+
+ _newtWindow.invoke(true, new GLRunnable() {
+ @Override
+ public boolean run(GLAutoDrawable glAutoDrawable) {
+ _canvasRenderer.init(_settings, true);// true - do swap in renderer.
+ return true;
+ }
+ });
+ _inited = true;
+ }
+
+ public void draw(final CountDownLatch latch) {
+ if (!_inited) {
+ init();
+ }
+
+ if (/*isShowing()*/isVisible()) {
+ _newtWindow.invoke(true, _drawerGLRunnable);
+ }
+ if (latch != null) {
+ latch.countDown();
+ }
+ }
+
+ public JoglCanvasRenderer getCanvasRenderer() {
+ return _canvasRenderer;
+ }
+
+ @Override
+ public void close() {
+ _newtWindow.destroy();
+ }
+
+ @Override
+ public boolean isActive() {
+ return _newtWindow.hasFocus();
+ }
+
+ @Override
+ public boolean isClosing() {
+ return _isClosing;
+ }
+
+ @Override
+ public void setVSyncEnabled(final boolean enabled) {
+ _newtWindow.invoke(true, new GLRunnable() {
+ @Override
+ public boolean run(GLAutoDrawable glAutoDrawable) {
+ _newtWindow.getGL().setSwapInterval(enabled ? 1 : 0);
+ return false;
+ }
+ });
+ }
+
+ @Override
+ public void setTitle(String title) {
+ _newtWindow.setTitle(title);
+ }
+
+ @Override
+ public void setIcon(Image[] iconImages) {
+ //FIXME not supported by NEWT
+ }
+
+ @Override
+ public void moveWindowTo(int locX, int locY) {
+ _newtWindow.setPosition(locX, locY);
+ }
+
+ @Override
+ public GLWindow getNewtWindow() {
+ return _newtWindow;
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/NewtWindowContainer.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/NewtWindowContainer.java
new file mode 100644
index 0000000..5470a36
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/NewtWindowContainer.java
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.framework.jogl;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+
+public interface NewtWindowContainer{
+ public GLWindow getNewtWindow();
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtFocusWrapper.java b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtFocusWrapper.java
new file mode 100644
index 0000000..5068e6c
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtFocusWrapper.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.input.jogl;
+
+import com.ardor3d.framework.jogl.NewtWindowContainer;
+import com.ardor3d.input.FocusWrapper;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.opengl.GLWindow;
+
+
+public class JoglNewtFocusWrapper extends WindowAdapter implements FocusWrapper {
+
+ protected volatile boolean _focusLost = false;
+
+ protected final GLWindow _newtWindow;
+
+ public JoglNewtFocusWrapper(final NewtWindowContainer newtWindowContainer) {
+ _newtWindow = newtWindowContainer.getNewtWindow();
+ }
+
+ @Override
+ public void windowGainedFocus(final WindowEvent e) {
+ // do nothing
+ }
+
+ @Override
+ public void windowLostFocus(final WindowEvent e) {
+ _focusLost = true;
+ }
+
+ @Override
+ public boolean getAndClearFocusLost() {
+ final boolean result = _focusLost;
+
+ _focusLost = false;
+
+ return result;
+ }
+
+ @Override
+ public void init() {
+ _newtWindow.addWindowListener(this);
+ }
+
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtKey.java b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtKey.java
new file mode 100644
index 0000000..30861a4
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtKey.java
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.input.jogl;
+
+import com.jogamp.newt.event.KeyEvent;
+import com.ardor3d.input.Key;
+
+
+public enum JoglNewtKey {
+
+ ZERO(KeyEvent.VK_0, Key.ZERO), //
+ ONE(KeyEvent.VK_1, Key.ONE), //
+ TWO(KeyEvent.VK_2, Key.TWO), //
+ THREE(KeyEvent.VK_3, Key.THREE), //
+ FOUR(KeyEvent.VK_4, Key.FOUR), //
+ FIVE(KeyEvent.VK_5, Key.FIVE), //
+ SIX(KeyEvent.VK_6, Key.SIX), //
+ SEVEN(KeyEvent.VK_7, Key.SEVEN), //
+ EIGHT(KeyEvent.VK_8, Key.EIGHT), //
+ NINE(KeyEvent.VK_9, Key.NINE), //
+ A(KeyEvent.VK_A, Key.A), //
+ ADD(KeyEvent.VK_ADD, Key.NUMPADADD), //
+ AT(KeyEvent.VK_AT, Key.AT), //
+ B(KeyEvent.VK_B, Key.B), //
+ BACK_QUOTE(KeyEvent.VK_BACK_QUOTE, Key.GRAVE), //
+ BACK_SPACE(KeyEvent.VK_BACK_SPACE, Key.BACK), //
+ BACK_SLASH(KeyEvent.VK_BACK_SLASH, Key.BACKSLASH), //
+ C(KeyEvent.VK_C, Key.C), //
+ CAPS_LOCK(KeyEvent.VK_CAPS_LOCK, Key.CAPITAL), //
+ CIRCUMFLEX(KeyEvent.VK_CIRCUMFLEX, Key.CIRCUMFLEX), //
+ COLON(KeyEvent.VK_COLON, Key.COLON), //
+ COMMA(KeyEvent.VK_COMMA, Key.COMMA), //
+ CONVERT(KeyEvent.VK_CONVERT, Key.CONVERT), //
+ D(KeyEvent.VK_D, Key.D), //
+ DECIMAL(KeyEvent.VK_DECIMAL, Key.DECIMAL), //
+ DELETE(KeyEvent.VK_DELETE, Key.DELETE), //
+ DIVIDE(KeyEvent.VK_DIVIDE, Key.DIVIDE), //
+ DOWN(KeyEvent.VK_DOWN, Key.DOWN), //
+ E(KeyEvent.VK_E, Key.E), //
+ END(KeyEvent.VK_END, Key.END), //
+ EQUALS(KeyEvent.VK_EQUALS, Key.EQUALS), //
+ ESCAPE(KeyEvent.VK_ESCAPE, Key.ESCAPE), //
+ F(KeyEvent.VK_F, Key.F), //
+ F1(KeyEvent.VK_F1, Key.F1), //
+ F2(KeyEvent.VK_F2, Key.F2), //
+ F3(KeyEvent.VK_F3, Key.F3), //
+ F4(KeyEvent.VK_F4, Key.F4), //
+ F5(KeyEvent.VK_F5, Key.F5), //
+ F6(KeyEvent.VK_F6, Key.F6), //
+ F7(KeyEvent.VK_F7, Key.F7), //
+ F8(KeyEvent.VK_F8, Key.F8), //
+ F9(KeyEvent.VK_F9, Key.F9), //
+ F10(KeyEvent.VK_F10, Key.F10), //
+ F11(KeyEvent.VK_F11, Key.F11), //
+ F12(KeyEvent.VK_F12, Key.F12), //
+ F13(KeyEvent.VK_F13, Key.F13), //
+ F14(KeyEvent.VK_F14, Key.F14), //
+ F15(KeyEvent.VK_F15, Key.F15), //
+ G(KeyEvent.VK_G, Key.G), //
+ H(KeyEvent.VK_H, Key.H), //
+ HOME(KeyEvent.VK_HOME, Key.HOME), //
+ I(KeyEvent.VK_I, Key.I), //
+ INSERT(KeyEvent.VK_INSERT, Key.INSERT), //
+ J(KeyEvent.VK_J, Key.J), //
+ K(KeyEvent.VK_K, Key.K), //
+ KANA(KeyEvent.VK_KANA, Key.KANA), //
+ KANJI(KeyEvent.VK_KANJI, Key.KANJI), //
+ L(KeyEvent.VK_L, Key.L), //
+ OPEN_BRACKET(KeyEvent.VK_OPEN_BRACKET, Key.LBRACKET), //
+ CONTROL(KeyEvent.VK_CONTROL, Key.LCONTROL), //
+ LEFT(KeyEvent.VK_LEFT, Key.LEFT), //
+ ALT(KeyEvent.VK_ALT, Key.LMENU), //
+ META(KeyEvent.VK_META, Key.LMETA), //
+ SHIFT(KeyEvent.VK_SHIFT, Key.LSHIFT), //
+ M(KeyEvent.VK_M, Key.M), //
+ MINUS(KeyEvent.VK_MINUS, Key.MINUS), //
+ MULTIPLY(KeyEvent.VK_MULTIPLY, Key.MULTIPLY), //
+ N(KeyEvent.VK_N, Key.N), //
+ PAGE_DOWN(KeyEvent.VK_PAGE_DOWN, Key.PAGEDOWN_NEXT), //
+ NONCONVERT(KeyEvent.VK_NONCONVERT, Key.NOCONVERT), //
+ NUM_LOCK(KeyEvent.VK_NUM_LOCK, Key.NUMLOCK), //
+ NUMPAD0(KeyEvent.VK_NUMPAD0, Key.NUMPAD0), //
+ NUMPAD1(KeyEvent.VK_NUMPAD1, Key.NUMPAD1), //
+ NUMPAD2(KeyEvent.VK_NUMPAD2, Key.NUMPAD2), //
+ NUMPAD3(KeyEvent.VK_NUMPAD3, Key.NUMPAD3), //
+ NUMPAD4(KeyEvent.VK_NUMPAD4, Key.NUMPAD4), //
+ NUMPAD5(KeyEvent.VK_NUMPAD5, Key.NUMPAD5), //
+ NUMPAD6(KeyEvent.VK_NUMPAD6, Key.NUMPAD6), //
+ NUMPAD7(KeyEvent.VK_NUMPAD7, Key.NUMPAD7), //
+ NUMPAD8(KeyEvent.VK_NUMPAD8, Key.NUMPAD8), //
+ NUMPAD9(KeyEvent.VK_NUMPAD9, Key.NUMPAD9), //
+ O(KeyEvent.VK_O, Key.O), //
+ P(KeyEvent.VK_P, Key.P), //
+ PAUSE(KeyEvent.VK_PAUSE, Key.PAUSE), //
+ PERIOD(KeyEvent.VK_PERIOD, Key.PERIOD), //
+ PAGE_UP(KeyEvent.VK_PAGE_UP, Key.PAGEUP_PRIOR), //
+ Q(KeyEvent.VK_Q, Key.Q), //
+ QUOTE(KeyEvent.VK_QUOTE, Key.APOSTROPHE), //
+ R(KeyEvent.VK_R, Key.R), //
+ CLOSE_BRACKET(KeyEvent.VK_CLOSE_BRACKET, Key.RBRACKET), //
+ ENTER(KeyEvent.VK_ENTER, Key.RETURN), //
+ RIGHT(KeyEvent.VK_RIGHT, Key.RIGHT), //
+ S(KeyEvent.VK_S, Key.S), //
+ SCROLL_LOCK(KeyEvent.VK_SCROLL_LOCK, Key.SCROLL), //
+ SEMICOLON(KeyEvent.VK_SEMICOLON, Key.SEMICOLON), //
+ SLASH(KeyEvent.VK_SLASH, Key.SLASH), //
+ SPACE(KeyEvent.VK_SPACE, Key.SPACE), //
+ STOP(KeyEvent.VK_STOP, Key.STOP), //
+ PRINTSCREEN(KeyEvent.VK_PRINTSCREEN, Key.SYSRQ), //
+ T(KeyEvent.VK_T, Key.T), //
+ TAB(KeyEvent.VK_TAB, Key.TAB), //
+ U(KeyEvent.VK_U, Key.U), //
+ UNDERSCORE(KeyEvent.VK_UNDERSCORE, Key.UNDERLINE), //
+ UP(KeyEvent.VK_UP, Key.UP), //
+ V(KeyEvent.VK_V, Key.V), //
+ W(KeyEvent.VK_W, Key.W), //
+ X(KeyEvent.VK_X, Key.X), //
+ Y(KeyEvent.VK_Y, Key.Y), //
+ Z(KeyEvent.VK_Z, Key.Z), //
+ UNDEFINED(KeyEvent.VK_UNDEFINED, Key.UNKNOWN);
+
+ private final int _newtCode;
+ private final Key _key;
+
+ private JoglNewtKey(final int newtCode, final Key key) {
+ _newtCode = newtCode;
+ _key = key;
+ }
+
+ public static Key findByCode(final int newtCode) {
+ for (final JoglNewtKey ak : values()) {
+ if (ak._newtCode == newtCode) {
+ return ak._key;
+ }
+ }
+
+ return Key.UNKNOWN;
+ }
+
+ public int getNewtCode() {
+ return _newtCode;
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtKeyboardWrapper.java b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtKeyboardWrapper.java
new file mode 100644
index 0000000..43bd01a
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtKeyboardWrapper.java
@@ -0,0 +1,128 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.input.jogl;
+
+import java.util.EnumSet;
+import java.util.LinkedList;
+import com.ardor3d.annotation.GuardedBy;
+import com.ardor3d.framework.jogl.NewtWindowContainer;
+import com.ardor3d.input.Key;
+import com.ardor3d.input.KeyEvent;
+import com.ardor3d.input.KeyState;
+import com.ardor3d.input.KeyboardWrapper;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.AbstractIterator;
+import com.google.common.collect.PeekingIterator;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyListener;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.opengl.GLWindow;
+
+
+public class JoglNewtKeyboardWrapper implements KeyboardWrapper, KeyListener {
+
+ @GuardedBy("this")
+ protected final LinkedList<KeyEvent> _upcomingEvents = new LinkedList<KeyEvent>();
+
+ @GuardedBy("this")
+ protected JoglNewtKeyboardIterator _currentIterator = null;
+
+ protected final GLWindow _newtWindow;
+
+ protected boolean _consumeEvents = false;
+
+ protected final EnumSet<Key> _pressedList = EnumSet.noneOf(Key.class);
+
+ public JoglNewtKeyboardWrapper(final NewtWindowContainer newtWindowContainer) {
+ _newtWindow = Preconditions.checkNotNull(newtWindowContainer.getNewtWindow(), "newtWindow");
+ }
+
+ public void init() {
+ _newtWindow.addKeyListener(this);
+ _newtWindow.addWindowListener(new WindowAdapter() {
+ public void windowLostFocus(final WindowEvent e) {}
+
+ public void windowGainedFocus(final WindowEvent e) {
+ _pressedList.clear();
+ }
+ });
+ }
+
+ public synchronized PeekingIterator<KeyEvent> getEvents() {
+ if (_currentIterator == null || !_currentIterator.hasNext()) {
+ _currentIterator = new JoglNewtKeyboardIterator();
+ }
+
+ return _currentIterator;
+ }
+
+ public synchronized void keyTyped(final com.jogamp.newt.event.KeyEvent e) {
+ if (_consumeEvents) {
+ e.setAttachment(InputEvent.consumedTag);
+ // ignore this event
+ }
+ }
+
+ public synchronized void keyPressed(final com.jogamp.newt.event.KeyEvent e) {
+ final Key pressed = fromKeyEventToKey(e);
+ if (!_pressedList.contains(pressed)) {
+ _upcomingEvents.add(new KeyEvent(pressed, KeyState.DOWN, e.getKeyChar()));
+ _pressedList.add(pressed);
+ }
+ if (_consumeEvents) {
+ e.setAttachment(InputEvent.consumedTag);
+ // ignore this event
+ }
+ }
+
+ public synchronized void keyReleased(final com.jogamp.newt.event.KeyEvent e) {
+ final Key released = fromKeyEventToKey(e);
+ _upcomingEvents.add(new KeyEvent(released, KeyState.UP, e.getKeyChar()));
+ _pressedList.remove(released);
+ if (_consumeEvents) {
+ e.setAttachment(InputEvent.consumedTag);
+ // ignore this event
+ }
+ }
+
+ /**
+ * Convert from NEWT key event to Ardor3D Key. Override to provide additional or custom behavior.
+ *
+ * @param e
+ * the NEWT KeyEvent received by the input system.
+ * @return an Ardor3D Key, to be forwarded to the Predicate/Trigger system.
+ */
+ public synchronized Key fromKeyEventToKey(final com.jogamp.newt.event.KeyEvent e) {
+ return JoglNewtKey.findByCode(e.getKeyCode());
+ }
+
+ private class JoglNewtKeyboardIterator extends AbstractIterator<KeyEvent> implements PeekingIterator<KeyEvent> {
+ @Override
+ protected KeyEvent computeNext() {
+ synchronized (JoglNewtKeyboardWrapper.this) {
+ if (_upcomingEvents.isEmpty()) {
+ return endOfData();
+ }
+
+ return _upcomingEvents.poll();
+ }
+ }
+ }
+
+ public boolean isConsumeEvents() {
+ return _consumeEvents;
+ }
+
+ public void setConsumeEvents(final boolean consumeEvents) {
+ _consumeEvents = consumeEvents;
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtMouseManager.java b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtMouseManager.java
new file mode 100644
index 0000000..1a9f8cc
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtMouseManager.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.input.jogl;
+
+import com.ardor3d.framework.jogl.NewtWindowContainer;
+import com.ardor3d.input.GrabbedState;
+import com.ardor3d.input.MouseCursor;
+import com.ardor3d.input.MouseManager;
+import com.jogamp.newt.opengl.GLWindow;
+
+
+public class JoglNewtMouseManager implements MouseManager{
+
+ /** our current grabbed state */
+ private GrabbedState _grabbedState;
+
+ private GLWindow _newtWindow;
+
+ public JoglNewtMouseManager(final NewtWindowContainer newtWindowContainer) {
+ _newtWindow = newtWindowContainer.getNewtWindow();
+ }
+
+ @Override
+ public void setCursor(MouseCursor cursor) {
+ //FIXME not supported by NEWT
+ }
+
+ @Override
+ public void setPosition(final int x, final int y) {
+ _newtWindow.warpPointer(x, _newtWindow.getHeight() - y);
+ }
+
+ @Override
+ public void setGrabbed(GrabbedState grabbedState) {
+ // check if we should be here.
+ if (_grabbedState == grabbedState) {
+ return;
+ }
+
+ // remember our grabbed state mode.
+ _grabbedState = grabbedState;
+ if (grabbedState == GrabbedState.GRABBED) {
+ //FIXME remember our old cursor
+
+ // set our cursor to be invisible
+ _newtWindow.setPointerVisible(false);
+ }
+ else {
+ //FIXME restore our old cursor
+
+ // set our cursor to be visible
+ _newtWindow.setPointerVisible(true);
+ }
+ }
+
+ @Override
+ public GrabbedState getGrabbed() {
+ return _grabbedState;
+ }
+
+ @Override
+ public boolean isSetPositionSupported() {
+ return true;
+ }
+
+ @Override
+ public boolean isSetGrabbedSupported() {
+ return true;
+ }
+
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtMouseWrapper.java b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtMouseWrapper.java
new file mode 100644
index 0000000..6ecf6bb
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/input/jogl/JoglNewtMouseWrapper.java
@@ -0,0 +1,310 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.input.jogl;
+
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.LinkedList;
+import com.ardor3d.annotation.GuardedBy;
+import com.ardor3d.framework.jogl.NewtWindowContainer;
+import com.ardor3d.input.ButtonState;
+import com.ardor3d.input.GrabbedState;
+import com.ardor3d.input.MouseButton;
+import com.ardor3d.input.MouseManager;
+import com.ardor3d.input.MouseState;
+import com.ardor3d.input.MouseWrapper;
+import com.google.common.collect.AbstractIterator;
+import com.google.common.collect.EnumMultiset;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.PeekingIterator;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.opengl.GLWindow;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+
+public class JoglNewtMouseWrapper implements MouseWrapper, MouseListener {
+
+ @GuardedBy("this")
+ protected final LinkedList<MouseState> _upcomingEvents = Lists.newLinkedList();
+
+ @GuardedBy("this")
+ protected JoglNewtMouseIterator _currentIterator = null;
+
+ @GuardedBy("this")
+ protected MouseState _lastState = null;
+
+ protected final GLWindow _newtWindow;
+
+ protected final MouseManager _manager;
+
+ protected boolean _consumeEvents = false;
+
+ protected final Multiset<MouseButton> _clicks = EnumMultiset.create(MouseButton.class);
+ protected final EnumMap<MouseButton, Long> _lastClickTime = Maps.newEnumMap(MouseButton.class);
+ protected final EnumSet<MouseButton> _clickArmed = EnumSet.noneOf(MouseButton.class);
+
+ protected int _ignoreX = Integer.MAX_VALUE;
+ protected int _ignoreY = Integer.MAX_VALUE;
+
+ public JoglNewtMouseWrapper(final NewtWindowContainer newtWindowContainer, final MouseManager manager) {
+ _newtWindow = checkNotNull(newtWindowContainer.getNewtWindow(), "newtWindow");
+ _manager = manager;
+ for (final MouseButton mb : MouseButton.values()) {
+ _lastClickTime.put(mb, 0L);
+ }
+ }
+
+ @Override
+ public void init() {
+ _newtWindow.addMouseListener(this);
+ }
+
+ @Override
+ public synchronized PeekingIterator<MouseState> getEvents() {
+ expireClickEvents();
+
+ if (_currentIterator == null || !_currentIterator.hasNext()) {
+ _currentIterator = new JoglNewtMouseIterator();
+ }
+
+ return _currentIterator;
+ }
+
+ private void expireClickEvents() {
+ if (!_clicks.isEmpty()) {
+ for (final MouseButton mb : MouseButton.values()) {
+ if (System.currentTimeMillis() - _lastClickTime.get(mb) > MouseState.CLICK_TIME_MS) {
+ _clicks.setCount(mb, 0);
+ }
+ }
+ }
+ }
+
+ @Override
+ public synchronized void mousePressed(MouseEvent me) {
+ final MouseButton b = getButtonForEvent(me);
+ if (_clickArmed.contains(b)) {
+ _clicks.setCount(b, 0);
+ }
+ _clickArmed.add(b);
+ _lastClickTime.put(b, System.currentTimeMillis());
+
+ initState(me);
+ if (_consumeEvents) {
+ me.setAttachment(InputEvent.consumedTag);
+ }
+
+ final EnumMap<MouseButton, ButtonState> buttons = _lastState.getButtonStates();
+
+ setStateForButton(me, buttons, ButtonState.DOWN);
+
+ addNewState(me, buttons, null);
+ }
+
+ @Override
+ public synchronized void mouseReleased(MouseEvent me) {
+ initState(me);
+ if (_consumeEvents) {
+ me.setAttachment(InputEvent.consumedTag);
+ }
+
+ final EnumMap<MouseButton, ButtonState> buttons = _lastState.getButtonStates();
+
+ setStateForButton(me, buttons, ButtonState.UP);
+
+ final MouseButton b = getButtonForEvent(me);
+ if (_clickArmed.contains(b) && (System.currentTimeMillis() - _lastClickTime.get(b) <= MouseState.CLICK_TIME_MS)) {
+ _clicks.add(b); // increment count of clicks for button b.
+ // XXX: Note the double event add... this prevents sticky click counts, but is it the best way?
+ addNewState(me, buttons, EnumMultiset.create(_clicks));
+ } else {
+ _clicks.setCount(b, 0); // clear click count for button b.
+ }
+ _clickArmed.remove(b);
+
+ addNewState(me, buttons, null);
+ }
+
+ @Override
+ public synchronized void mouseDragged(MouseEvent me) {
+ mouseMoved(me);
+ }
+
+ @Override
+ public synchronized void mouseMoved(MouseEvent me) {
+ _clickArmed.clear();
+ _clicks.clear();
+
+ // check that we have a valid _lastState
+ initState(me);
+ if (_consumeEvents) {
+ me.setAttachment(InputEvent.consumedTag);
+ }
+
+ // remember our current ardor3d position
+ final int oldX = _lastState.getX(), oldY = _lastState.getY();
+
+ // check the state against the "ignore next" values
+ if (_ignoreX != Integer.MAX_VALUE // shortcut to prevent dx/dy calculations
+ && (_ignoreX == getDX(me) && _ignoreY == getDY(me))) {
+
+ // we matched, so we'll consider this a "mouse pointer reset move"
+ // so reset ignore to let the next move event through.
+ _ignoreX = Integer.MAX_VALUE;
+ _ignoreY = Integer.MAX_VALUE;
+
+ // exit without adding an event to our queue
+ return;
+ }
+
+ // save our old "last state."
+ final MouseState _savedState = _lastState;
+
+ // Add our latest state info to the queue
+ addNewState(me, _lastState.getButtonStates(), null);
+
+ // If we have a valid move... should always be the case, but occasionally something slips through.
+ if (_lastState.getDx() != 0 || _lastState.getDy() != 0) {
+
+ // Ask our manager if we're currently "captured"
+ if (_manager.getGrabbed() == GrabbedState.GRABBED) {
+
+ // if so, set "ignore next" to the inverse of this move
+ _ignoreX = -_lastState.getDx();
+ _ignoreY = -_lastState.getDy();
+
+ // Move us back to our last position.
+ _manager.setPosition(oldX, oldY);
+
+ // And finally, revert our _lastState.
+ _lastState = _savedState;
+ } else {
+ // otherwise, set us to not ignore anything. This may be unnecessary, but prevents any possible
+ // "ignore" bleeding.
+ _ignoreX = Integer.MAX_VALUE;
+ _ignoreY = Integer.MAX_VALUE;
+ }
+ }
+ }
+
+ @Override
+ public void mouseWheelMoved(MouseEvent me) {
+ initState(me);
+
+ addNewState(me, _lastState.getButtonStates(), null);
+ if (_consumeEvents) {
+ me.setAttachment(InputEvent.consumedTag);
+ }
+ }
+
+ private void initState(final MouseEvent mouseEvent) {
+ if (_lastState == null) {
+ _lastState = new MouseState(mouseEvent.getX(), getArdor3DY(mouseEvent), 0, 0, 0, null, null);
+ }
+ }
+
+ private void addNewState(final MouseEvent mouseEvent, final EnumMap<MouseButton, ButtonState> enumMap,
+ final Multiset<MouseButton> clicks) {
+ final MouseState newState = new MouseState(mouseEvent.getX(), getArdor3DY(mouseEvent), getDX(mouseEvent),
+ getDY(mouseEvent), mouseEvent.getWheelRotation(), enumMap, clicks);
+
+ synchronized (JoglNewtMouseWrapper.this) {
+ _upcomingEvents.add(newState);
+ }
+ _lastState = newState;
+ }
+
+ private int getDX(final MouseEvent me) {
+ return me.getX() - _lastState.getX();
+ }
+
+ private int getDY(final MouseEvent me) {
+ return getArdor3DY(me) - _lastState.getY();
+ }
+
+ /**
+ * @param e
+ * our mouseEvent
+ * @return the Y coordinate of the event, flipped relative to the component since we expect an origin in the lower
+ * left corner.
+ */
+ private int getArdor3DY(final MouseEvent me) {
+ return _newtWindow.getHeight() - me.getY();
+ }
+
+ private void setStateForButton(final MouseEvent e, final EnumMap<MouseButton, ButtonState> buttons,
+ final ButtonState buttonState) {
+ final MouseButton button = getButtonForEvent(e);
+ buttons.put(button, buttonState);
+ }
+
+ private MouseButton getButtonForEvent(final MouseEvent me) {
+ MouseButton button;
+ switch(me.getButton()) {
+ case MouseEvent.BUTTON1:
+ button = MouseButton.LEFT;
+ break;
+ case MouseEvent.BUTTON2:
+ button = MouseButton.MIDDLE;
+ break;
+ case MouseEvent.BUTTON3:
+ button = MouseButton.RIGHT;
+ break;
+ default:
+ throw new RuntimeException("unknown button: " + me.getButton());
+ }
+ return button;
+ }
+
+ private class JoglNewtMouseIterator extends AbstractIterator<MouseState> implements PeekingIterator<MouseState> {
+
+ @Override
+ protected MouseState computeNext() {
+ synchronized (JoglNewtMouseWrapper.this) {
+ if (_upcomingEvents.isEmpty()) {
+ return endOfData();
+ }
+ return _upcomingEvents.poll();
+ }
+ }
+ }
+
+ @Override
+ public synchronized void mouseClicked(MouseEvent me) {
+ // Yes, we could use the click count here, but in the interests of this working the same way as SWT and Native,
+ // we
+ // will do it the same way they do it.
+
+ }
+
+ @Override
+ public synchronized void mouseEntered(MouseEvent me) {
+ // ignore this
+ }
+
+ @Override
+ public synchronized void mouseExited(MouseEvent me) {
+ // ignore this
+ }
+
+ public boolean isConsumeEvents() {
+ return _consumeEvents;
+ }
+
+ public void setConsumeEvents(final boolean consumeEvents) {
+ _consumeEvents = consumeEvents;
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java
new file mode 100644
index 0000000..7bc4e01
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java
@@ -0,0 +1,247 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.renderer.jogl;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLAutoDrawable;
+
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.util.geom.BufferUtils;
+
+public class JoglContextCapabilities extends ContextCapabilities {
+
+ public JoglContextCapabilities(final GLAutoDrawable autodrawable) {
+ init(autodrawable.getGL());
+ }
+
+ public JoglContextCapabilities(final GL gl) {
+ init(gl);
+ }
+
+ public JoglContextCapabilities(final ContextCapabilities caps) {
+ super(caps);
+ }
+
+ public void init(final GL gl) {
+ final IntBuffer buf = BufferUtils.createIntBuffer(16);
+
+ _supportsVBO = gl.isExtensionAvailable("GL_ARB_vertex_buffer_object");
+ _supportsGL1_2 = gl.isExtensionAvailable("GL_VERSION_1_2");
+ _supportsMultisample = gl.isExtensionAvailable("GL_ARB_multisample");
+
+ _supportsConstantColor = _supportsEq = gl.isExtensionAvailable("GL_ARB_imaging");
+ _supportsSeparateFunc = gl.isExtensionAvailable("GL_EXT_blend_func_separate");
+ _supportsSeparateEq = gl.isExtensionAvailable("GL_EXT_blend_equation_separate");
+ _supportsMinMax = gl.isExtensionAvailable("GL_EXT_blend_minmax");
+ _supportsSubtract = gl.isExtensionAvailable("GL_EXT_blend_subtract");
+
+ _supportsFogCoords = gl.isExtensionAvailable("GL_EXT_fog_coord");
+ _supportsFragmentProgram = gl.isExtensionAvailable("GL_ARB_fragment_program");
+ _supportsVertexProgram = gl.isExtensionAvailable("GL_ARB_vertex_program");
+
+ _supportsPointSprites = gl.isExtensionAvailable("GL_ARB_point_sprite");
+ _supportsPointParameters = gl.isExtensionAvailable("GL_ARB_point_parameters");
+
+ _supportsTextureLodBias = gl.isExtensionAvailable("GL_EXT_texture_lod_bias");
+ if (_supportsTextureLodBias) {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_TEXTURE_LOD_BIAS, buf);
+ _maxTextureLodBias = buf.get(0);
+ } else {
+ _maxTextureLodBias = 0f;
+ }
+
+ gl.glGetIntegerv(GL2ES1.GL_MAX_CLIP_PLANES, buf);
+ _maxUserClipPlanes = buf.get(0);
+
+ _glslSupported = gl.isExtensionAvailable("GL_ARB_shader_objects")
+ && gl.isExtensionAvailable("GL_ARB_fragment_shader") && gl.isExtensionAvailable("GL_ARB_vertex_shader")
+ && gl.isExtensionAvailable("GL_ARB_shading_language_100");
+
+ _geometryShader4Supported = gl.isExtensionAvailable("GL_ARB_geometry_shader4") && _glslSupported;
+
+ _geometryInstancingSupported = gl.isExtensionAvailable("GL_EXT_draw_instanced") || gl.isExtensionAvailable("GL_VERSION_3_0");
+
+ _tessellationShadersSupported = gl.isExtensionAvailable("GL_ARB_tessellation_shader") && _glslSupported;
+
+ if (_glslSupported) {
+ gl.glGetIntegerv(GL2.GL_MAX_VERTEX_ATTRIBS_ARB, buf);
+ _maxGLSLVertexAttribs = buf.get(0);
+ }
+
+ // Pbuffer
+ _pbufferSupported = gl.isExtensionAvailable("GL_ARB_pixel_buffer_object");
+
+ // FBO
+ _fboSupported = gl.isExtensionAvailable("GL_EXT_framebuffer_object");
+ if (_fboSupported) {
+ if (gl.isExtensionAvailable("GL_ARB_draw_buffers")) {
+ gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, buf);
+ _maxFBOColorAttachments = buf.get(0);
+ } else {
+ _maxFBOColorAttachments = 1;
+ }
+
+ // Max multisample samples.
+ if (gl.isExtensionAvailable("GL_EXT_framebuffer_multisample")
+ && gl.isExtensionAvailable("GL_EXT_framebuffer_blit")) {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, buf);
+ _maxFBOSamples = buf.get(0);
+ } else {
+ _maxFBOSamples = 0;
+ }
+ } else {
+ _maxFBOColorAttachments = 0;
+ }
+
+ _twoSidedStencilSupport = gl.isExtensionAvailable("GL_EXT_stencil_two_side");
+ _stencilWrapSupport = gl.isExtensionAvailable("GL_EXT_stencil_wrap");
+
+ // number of available auxiliary draw buffers
+ gl.glGetIntegerv(GL2.GL_AUX_BUFFERS, buf);
+ _numAuxDrawBuffers = buf.get(0);
+
+ // max texture size.
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, buf);
+ _maxTextureSize = buf.get(0);
+
+ // Check for support of multitextures.
+ _supportsMultiTexture = gl.isExtensionAvailable("GL_ARB_multitexture");
+
+ // Support for texture formats
+ _supportsFloatTextures = gl.isExtensionAvailable("GL_ARB_texture_float");
+ _supportsIntegerTextures = gl.isExtensionAvailable("GL_EXT_texture_integer");
+ _supportsOneTwoComponentTextures = gl.isExtensionAvailable("GL_ARB_texture_rg");
+
+ // Check for support of fixed function dot3 environment settings
+ _supportsEnvDot3 = gl.isExtensionAvailable("GL_ARB_texture_env_dot3");
+
+ // Check for support of fixed function dot3 environment settings
+ _supportsEnvCombine = gl.isExtensionAvailable("GL_ARB_texture_env_combine");
+
+ // Check for support of automatic mipmap generation
+ _automaticMipMaps = gl.isExtensionAvailable("GL_SGIS_generate_mipmap");
+
+ _supportsDepthTexture = gl.isExtensionAvailable("GL_ARB_depth_texture");
+ _supportsShadow = gl.isExtensionAvailable("GL_ARB_shadow");
+
+ // If we do support multitexturing, find out how many textures we
+ // can handle.
+ if (_supportsMultiTexture) {
+ gl.glGetIntegerv(GL2ES1.GL_MAX_TEXTURE_UNITS, buf);
+ _numFixedTexUnits = buf.get(0);
+ } else {
+ _numFixedTexUnits = 1;
+ }
+
+ // Go on to check number of texture units supported for vertex and
+ // fragment shaders
+ if (gl.isExtensionAvailable("GL_ARB_shader_objects") && gl.isExtensionAvailable("GL_ARB_vertex_shader")
+ && gl.isExtensionAvailable("GL_ARB_fragment_shader")) {
+ gl.glGetIntegerv(GL2ES2.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, buf);
+ _numVertexTexUnits = buf.get(0);
+ gl.glGetIntegerv(GL2ES2.GL_MAX_TEXTURE_IMAGE_UNITS, buf);
+ _numFragmentTexUnits = buf.get(0);
+ gl.glGetIntegerv(GL2.GL_MAX_TEXTURE_COORDS, buf);
+ _numFragmentTexCoordUnits = buf.get(0);
+ } else {
+ // based on nvidia dev doc:
+ // http://developer.nvidia.com/object/General_FAQ.html#t6
+ // "For GPUs that do not support GL_ARB_fragment_program and
+ // GL_NV_fragment_program, those two limits are set equal to
+ // GL_MAX_TEXTURE_UNITS."
+ _numFragmentTexCoordUnits = _numFixedTexUnits;
+ _numFragmentTexUnits = _numFixedTexUnits;
+
+ // We'll set this to 0 for now since we do not know:
+ _numVertexTexUnits = 0;
+ }
+
+ // Now determine the maximum number of supported texture units
+ _numTotalTexUnits = Math.max(_numFragmentTexCoordUnits, Math.max(_numFixedTexUnits, Math.max(
+ _numFragmentTexUnits, _numVertexTexUnits)));
+
+ // Check for S3 texture compression capability.
+ _supportsS3TCCompression = gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc");
+
+ // Check for LA texture compression capability.
+ _supportsLATCCompression = gl.isExtensionAvailable("GL_EXT_texture_compression_latc");
+
+ // Check for generic texture compression capability.
+ _supportsGenericCompression = gl.isExtensionAvailable("GL_ARB_texture_compression");
+
+ // Check for 3D texture capability.
+ _supportsTexture3D = _supportsGL1_2;
+
+ // Check for cubemap capability.
+ _supportsTextureCubeMap = gl.isExtensionAvailable("GL_ARB_texture_cube_map");
+
+ // See if we support anisotropic filtering
+ _supportsAniso = gl.isExtensionAvailable("GL_EXT_texture_filter_anisotropic");
+
+ if (_supportsAniso) {
+ final FloatBuffer max_a = BufferUtils.createFloatBuffer(1);
+ max_a.rewind();
+
+ // Grab the maximum anisotropic filter.
+ gl.glGetFloatv(GL.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, max_a);
+
+ // set max.
+ _maxAnisotropic = max_a.get(0);
+ }
+
+ // See if we support textures that are not power of 2 in size.
+ _supportsNonPowerTwo = gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two");
+
+ // See if we support textures that do not have width == height.
+ _supportsRectangular = gl.isExtensionAvailable("GL_ARB_texture_rectangle");
+
+ _supportsMirroredRepeat = gl.isExtensionAvailable("GL_ARB_texture_mirrored_repeat");
+ _supportsMirrorClamp = _supportsMirrorBorderClamp = _supportsMirrorEdgeClamp = gl
+ .isExtensionAvailable("GL_EXT_texture_mirror_clamp");
+ _supportsBorderClamp = gl.isExtensionAvailable("GL_ARB_texture_border_clamp");
+ _supportsEdgeClamp = _supportsGL1_2;
+
+ try {
+ _displayVendor = gl.glGetString(GL.GL_VENDOR);
+ } catch (final Exception e) {
+ _displayVendor = "Unable to retrieve vendor.";
+ }
+
+ try {
+ _displayRenderer = gl.glGetString(GL.GL_RENDERER);
+ } catch (final Exception e) {
+ _displayRenderer = "Unable to retrieve adapter details.";
+ }
+
+ try {
+ _displayVersion = gl.glGetString(GL.GL_VERSION);
+ } catch (final Exception e) {
+ _displayVersion = "Unable to retrieve API version.";
+ }
+
+ if (_glslSupported) {
+ try {
+ _shadingLanguageVersion = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION);
+ } catch (final Exception e) {
+ _shadingLanguageVersion = "Unable to retrieve shading language version.";
+ }
+ } else {
+ _shadingLanguageVersion = "Not supported.";
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglPbufferTextureRenderer.java b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglPbufferTextureRenderer.java
new file mode 100644
index 0000000..63eb6ee
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglPbufferTextureRenderer.java
@@ -0,0 +1,368 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.renderer.jogl;
+
+import java.nio.IntBuffer;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLPbuffer;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.framework.DisplaySettings;
+import com.ardor3d.framework.Scene;
+import com.ardor3d.image.Texture;
+import com.ardor3d.image.Texture.Type;
+import com.ardor3d.renderer.AbstractPbufferTextureRenderer;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.TextureRendererFactory;
+import com.ardor3d.renderer.state.RenderState;
+import com.ardor3d.renderer.state.record.TextureRecord;
+import com.ardor3d.renderer.state.record.TextureStateRecord;
+import com.ardor3d.scene.state.jogl.JoglTextureStateUtil;
+import com.ardor3d.scene.state.jogl.util.JoglTextureUtil;
+import com.ardor3d.scenegraph.Spatial;
+import com.ardor3d.util.Ardor3dException;
+import com.ardor3d.util.TextureKey;
+import com.ardor3d.util.geom.BufferUtils;
+
+/**
+ * <p>
+ * This class is used by Ardor3D's JOGL implementation to render textures. Users should <b>not </b> create this class
+ * directly.
+ * </p>
+ *
+ * @see TextureRendererFactory
+ */
+public class JoglPbufferTextureRenderer extends AbstractPbufferTextureRenderer {
+ private static final Logger logger = Logger.getLogger(JoglPbufferTextureRenderer.class.getName());
+
+ /* Pbuffer instance */
+ private GLPbuffer _pbuffer;
+
+ private GLContext _context;
+
+ // HACK: needed to get the parent context in here somehow...
+ public static GLContext _parentContext;
+
+ public JoglPbufferTextureRenderer(final DisplaySettings settings, final Renderer parentRenderer,
+ final ContextCapabilities caps) {
+ super(settings, parentRenderer, caps);
+ setMultipleTargets(false);
+ }
+
+ /**
+ * <code>setupTexture</code> initializes a new Texture object for use with TextureRenderer. Generates a valid gl
+ * texture id for this texture and inits the data type for the texture.
+ */
+ public void setupTexture(final Texture tex) {
+ if (tex.getType() != Type.TwoDimensional) {
+ throw new IllegalArgumentException("Unsupported type: " + tex.getType());
+ }
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final TextureStateRecord record = (TextureStateRecord) context.getStateRecord(RenderState.StateType.Texture);
+
+ // check if we are already setup... if so, throw error.
+ if (tex.getTextureKey() == null) {
+ tex.setTextureKey(TextureKey.getRTTKey(tex.getMinificationFilter()));
+ } else if (tex.getTextureIdForContext(context.getGlContextRep()) != 0) {
+ throw new Ardor3dException("Texture is already setup and has id.");
+ }
+
+ // Create the texture
+ final IntBuffer ibuf = BufferUtils.createIntBuffer(1);
+ gl.glGenTextures(1, ibuf);
+ final int textureId = ibuf.get(0);
+ tex.setTextureIdForContext(context.getGlContextRep(), textureId);
+
+ JoglTextureStateUtil.doTextureBind(tex, 0, true);
+
+ // Initialize our texture with some default data.
+ final int internalFormat = JoglTextureUtil.getGLInternalFormat(tex.getTextureStoreFormat());
+ final int dataFormat = JoglTextureUtil.getGLPixelFormatFromStoreFormat(tex.getTextureStoreFormat());
+ final int pixelDataType = JoglTextureUtil.getGLPixelDataType(tex.getRenderedTexturePixelDataType());
+
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, internalFormat, _width, _height, 0, dataFormat, pixelDataType, null);
+
+ // Setup filtering and wrap
+ final TextureRecord texRecord = record.getTextureRecord(textureId, tex.getType());
+ JoglTextureStateUtil.applyFilter(tex, texRecord, 0, record, context.getCapabilities());
+ JoglTextureStateUtil.applyWrap(tex, texRecord, 0, record, context.getCapabilities());
+
+ logger.fine("setup pbuffer tex" + textureId + ": " + _width + "," + _height);
+ }
+
+ public void render(final Spatial spat, final Texture tex, final int clear) {
+ render(null, spat, null, tex, clear);
+ }
+
+ public void render(final List<? extends Spatial> spat, final Texture tex, final int clear) {
+ render(spat, null, null, tex, clear);
+ }
+
+ public void render(final Scene scene, final Texture tex, final int clear) {
+ render(null, null, scene, tex, clear);
+ }
+
+ private void render(final List<? extends Spatial> toDrawA, final Spatial toDrawB, final Scene toDrawC,
+ final Texture tex, final int clear) {
+ try {
+ if (_pbuffer == null) {
+ initPbuffer();
+ }
+
+ if (_useDirectRender && !tex.getTextureStoreFormat().isDepthFormat()) {
+ // setup and render directly to a 2d texture.
+ _pbuffer.releaseTexture();
+ activate();
+ switchCameraIn(clear);
+
+ if (toDrawA != null) {
+ doDraw(toDrawA);
+ } else {
+ doDraw(toDrawB);
+ }
+
+ deactivate();
+ switchCameraOut();
+ JoglTextureStateUtil.doTextureBind(tex, 0, true);
+ _pbuffer.bindTexture();
+ } else {
+ // render and copy to a texture
+ activate();
+ switchCameraIn(clear);
+
+ if (toDrawA != null) {
+ doDraw(toDrawA);
+ } else if (toDrawB != null) {
+ doDraw(toDrawB);
+ } else {
+ doDraw(toDrawC);
+ }
+
+ switchCameraOut();
+
+ copyToTexture(tex, 0, 0, _width, _height, 0, 0);
+
+ deactivate();
+ }
+
+ } catch (final Exception e) {
+ logger.logp(Level.SEVERE, this.getClass().toString(), "render(Spatial, Texture)", "Exception", e);
+ }
+ }
+
+ public void render(final Spatial spat, final List<Texture> texs, final int clear) {
+ render(null, spat, null, texs, clear);
+ }
+
+ public void render(final List<? extends Spatial> spat, final List<Texture> texs, final int clear) {
+ render(spat, null, null, texs, clear);
+ }
+
+ public void render(final Scene scene, final List<Texture> texs, final int clear) {
+ render(null, null, scene, texs, clear);
+ }
+
+ private void render(final List<? extends Spatial> toDrawA, final Spatial toDrawB, final Scene toDrawC,
+ final List<Texture> texs, final int clear) {
+ try {
+ if (_pbuffer == null) {
+ initPbuffer();
+ }
+
+ if (texs.size() == 1 && _useDirectRender && !texs.get(0).getTextureStoreFormat().isDepthFormat()) {
+ // setup and render directly to a 2d texture.
+ JoglTextureStateUtil.doTextureBind(texs.get(0), 0, true);
+ activate();
+ switchCameraIn(clear);
+ _pbuffer.releaseTexture();
+
+ if (toDrawA != null) {
+ doDraw(toDrawA);
+ } else if (toDrawB != null) {
+ doDraw(toDrawB);
+ } else {
+ doDraw(toDrawC);
+ }
+
+ switchCameraOut();
+
+ deactivate();
+ _pbuffer.bindTexture();
+ } else {
+ // render and copy to a texture
+ activate();
+ switchCameraIn(clear);
+
+ if (toDrawA != null) {
+ doDraw(toDrawA);
+ } else {
+ doDraw(toDrawB);
+ }
+
+ switchCameraOut();
+
+ for (int i = 0; i < texs.size(); i++) {
+ copyToTexture(texs.get(i), 0, 0, _width, _height, 0, 0);
+ }
+
+ deactivate();
+ }
+
+ } catch (final Exception e) {
+ logger.logp(Level.SEVERE, this.getClass().toString(), "render(Spatial, Texture)", "Exception", e);
+ }
+ }
+
+ public void copyToTexture(final Texture tex, final int x, final int y, final int width, final int height,
+ final int xoffset, final int yoffset) {
+ final GL gl = GLU.getCurrentGL();
+
+ JoglTextureStateUtil.doTextureBind(tex, 0, true);
+
+ gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, xoffset, yoffset, x, y, width, height);
+ }
+
+ @Override
+ protected void clearBuffers(final int clear) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.glDisable(GL.GL_SCISSOR_TEST);
+ _parentRenderer.clearBuffers(clear);
+ }
+
+ private void initPbuffer() {
+
+ try {
+ if (_pbuffer != null) {
+ _context.destroy();
+ _pbuffer.destroy();
+ giveBackContext();
+ ContextManager.removeContext(_pbuffer);
+ }
+
+ // Make our GLPbuffer...
+ final GLDrawableFactory fac = GLDrawableFactory.getFactory(GLProfile.getMaxFixedFunc(true));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true));
+ caps.setHardwareAccelerated(true);
+ caps.setDoubleBuffered(true);
+ caps.setAlphaBits(_settings.getAlphaBits());
+ caps.setDepthBits(_settings.getDepthBits());
+ caps.setNumSamples(_settings.getSamples());
+ caps.setSampleBuffers(_settings.getSamples() != 0);
+ caps.setStencilBits(_settings.getStencilBits());
+ caps.setDoubleBuffered(false);
+ _pbuffer = fac.createGLPbuffer(null, caps, null, _width, _height, _parentContext);
+ _context = _pbuffer.getContext();
+
+ _context.makeCurrent();
+
+ final JoglContextCapabilities contextCaps = new JoglContextCapabilities(_pbuffer.getGL());
+ ContextManager.addContext(_context,
+ new RenderContext(_context, contextCaps, ContextManager.getCurrentContext()));
+
+ } catch (final Exception e) {
+ logger.logp(Level.SEVERE, this.getClass().toString(), "initPbuffer()", "Exception", e);
+
+ if (_useDirectRender) {
+ logger.warning("Your card claims to support Render to Texture but fails to enact it. Updating your driver might solve this problem.");
+ logger.warning("Attempting to fall back to Copy Texture.");
+ _useDirectRender = false;
+ initPbuffer();
+ return;
+ }
+
+ logger.log(Level.WARNING, "Failed to create Pbuffer.", e);
+ return;
+ }
+
+ try {
+ activate();
+
+ _width = _pbuffer.getWidth();
+ _height = _pbuffer.getHeight();
+
+ deactivate();
+ } catch (final Exception e) {
+ logger.log(Level.WARNING, "Failed to initialize created Pbuffer.", e);
+ return;
+ }
+ }
+
+ private void activate() {
+ if (_active == 0) {
+ _oldContext = ContextManager.getCurrentContext();
+ _context.makeCurrent();
+
+ ContextManager.switchContext(_context);
+
+ ContextManager.getCurrentContext().clearEnforcedStates();
+ ContextManager.getCurrentContext().enforceStates(_enforcedStates);
+
+ if (_bgColorDirty) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.glClearColor(_backgroundColor.getRed(), _backgroundColor.getGreen(), _backgroundColor.getBlue(),
+ _backgroundColor.getAlpha());
+ _bgColorDirty = false;
+ }
+ }
+ _active++;
+ }
+
+ private void deactivate() {
+ if (_active == 1) {
+ giveBackContext();
+ }
+ _active--;
+ }
+
+ private void giveBackContext() {
+ _parentContext.makeCurrent();
+ ContextManager.switchContext(_oldContext.getContextKey());
+ }
+
+ public void cleanup() {
+ ContextManager.removeContext(_pbuffer);
+ _pbuffer.destroy();
+ }
+
+ public void setMultipleTargets(final boolean force) {
+ if (force) {
+ logger.fine("Copy Texture Pbuffer used!");
+ _useDirectRender = false;
+ if (_pbuffer != null) {
+ giveBackContext();
+ ContextManager.removeContext(_pbuffer);
+ }
+ } else {
+ // XXX: Is this WGL specific query right?
+ if (GLU.getCurrentGL().isExtensionAvailable("WGL_ARB_render_texture")) {
+ logger.fine("Render to Texture Pbuffer supported!");
+ _useDirectRender = true;
+ } else {
+ logger.fine("Copy Texture Pbuffer supported!");
+ }
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglRenderer.java b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglRenderer.java
new file mode 100644
index 0000000..7812aa6
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglRenderer.java
@@ -0,0 +1,1757 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.renderer.jogl;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.image.ImageDataFormat;
+import com.ardor3d.image.Texture;
+import com.ardor3d.image.Texture1D;
+import com.ardor3d.image.Texture2D;
+import com.ardor3d.image.Texture3D;
+import com.ardor3d.image.TextureCubeMap;
+import com.ardor3d.image.TextureCubeMap.Face;
+import com.ardor3d.math.Matrix4;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.math.type.ReadOnlyRectangle2;
+import com.ardor3d.math.type.ReadOnlyTransform;
+import com.ardor3d.math.type.ReadOnlyVector3;
+import com.ardor3d.renderer.AbstractRenderer;
+import com.ardor3d.renderer.Camera;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.DrawBufferTarget;
+import com.ardor3d.renderer.IndexMode;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.queue.RenderBucketType;
+import com.ardor3d.renderer.state.BlendState;
+import com.ardor3d.renderer.state.ClipState;
+import com.ardor3d.renderer.state.ColorMaskState;
+import com.ardor3d.renderer.state.CullState;
+import com.ardor3d.renderer.state.FogState;
+import com.ardor3d.renderer.state.FragmentProgramState;
+import com.ardor3d.renderer.state.GLSLShaderObjectsState;
+import com.ardor3d.renderer.state.LightState;
+import com.ardor3d.renderer.state.MaterialState;
+import com.ardor3d.renderer.state.OffsetState;
+import com.ardor3d.renderer.state.RenderState;
+import com.ardor3d.renderer.state.ShadingState;
+import com.ardor3d.renderer.state.StencilState;
+import com.ardor3d.renderer.state.TextureState;
+import com.ardor3d.renderer.state.VertexProgramState;
+import com.ardor3d.renderer.state.WireframeState;
+import com.ardor3d.renderer.state.ZBufferState;
+import com.ardor3d.renderer.state.record.LineRecord;
+import com.ardor3d.renderer.state.record.RendererRecord;
+import com.ardor3d.scene.state.jogl.JoglBlendStateUtil;
+import com.ardor3d.scene.state.jogl.JoglClipStateUtil;
+import com.ardor3d.scene.state.jogl.JoglColorMaskStateUtil;
+import com.ardor3d.scene.state.jogl.JoglCullStateUtil;
+import com.ardor3d.scene.state.jogl.JoglFogStateUtil;
+import com.ardor3d.scene.state.jogl.JoglFragmentProgramStateUtil;
+import com.ardor3d.scene.state.jogl.JoglLightStateUtil;
+import com.ardor3d.scene.state.jogl.JoglMaterialStateUtil;
+import com.ardor3d.scene.state.jogl.JoglOffsetStateUtil;
+import com.ardor3d.scene.state.jogl.JoglShaderObjectsStateUtil;
+import com.ardor3d.scene.state.jogl.JoglShadingStateUtil;
+import com.ardor3d.scene.state.jogl.JoglStencilStateUtil;
+import com.ardor3d.scene.state.jogl.JoglTextureStateUtil;
+import com.ardor3d.scene.state.jogl.JoglVertexProgramStateUtil;
+import com.ardor3d.scene.state.jogl.JoglWireframeStateUtil;
+import com.ardor3d.scene.state.jogl.JoglZBufferStateUtil;
+import com.ardor3d.scene.state.jogl.util.JoglRendererUtil;
+import com.ardor3d.scene.state.jogl.util.JoglTextureUtil;
+import com.ardor3d.scenegraph.AbstractBufferData;
+import com.ardor3d.scenegraph.FloatBufferData;
+import com.ardor3d.scenegraph.IndexBufferData;
+import com.ardor3d.scenegraph.Mesh;
+import com.ardor3d.scenegraph.Renderable;
+import com.ardor3d.scenegraph.Spatial;
+import com.ardor3d.scenegraph.AbstractBufferData.VBOAccessMode;
+import com.ardor3d.scenegraph.hint.NormalsMode;
+import com.ardor3d.util.Ardor3dException;
+import com.ardor3d.util.Constants;
+import com.ardor3d.util.geom.BufferUtils;
+import com.ardor3d.util.stat.StatCollector;
+import com.ardor3d.util.stat.StatType;
+
+/**
+ * <code>JoglRenderer</code> provides an implementation of the <code>Renderer</code> interface using the JOGL API.
+ *
+ * @see com.ardor3d.renderer.Renderer
+ */
+public class JoglRenderer extends AbstractRenderer {
+ private static final Logger logger = Logger.getLogger(JoglRenderer.class.getName());
+
+ private final FloatBuffer _transformBuffer = BufferUtils.createFloatBuffer(16);
+ private final Matrix4 _transformMatrix = new Matrix4();
+
+ /**
+ * Constructor instantiates a new <code>JoglRenderer</code> object.
+ */
+ public JoglRenderer() {
+ logger.fine("JoglRenderer created.");
+ }
+
+ public void setBackgroundColor(final ReadOnlyColorRGBA c) {
+ final GL gl = GLU.getCurrentGL();
+
+ _backgroundColor.set(c);
+ gl.glClearColor(_backgroundColor.getRed(), _backgroundColor.getGreen(), _backgroundColor.getBlue(),
+ _backgroundColor.getAlpha());
+ }
+
+ @Override
+ public void renderBuckets() {
+ renderBuckets(true, true);
+ }
+
+ @Override
+ public void renderBuckets(final boolean doSort, final boolean doClear) {
+ _processingQueue = true;
+ if (doSort && doClear) {
+ _queue.renderBuckets(this);
+ } else {
+ if (doSort) {
+ _queue.sortBuckets();
+ }
+ _queue.renderOnly(this);
+ if (doClear) {
+ _queue.clearBuckets();
+ }
+ }
+ _processingQueue = false;
+ }
+
+ /**
+ * clear the render queue
+ */
+ public void clearQueue() {
+ _queue.clearBuckets();
+ }
+
+ public void clearBuffers(final int buffers) {
+ clearBuffers(buffers, false);
+ }
+
+ public void clearBuffers(final int buffers, final boolean strict) {
+ final GL gl = GLU.getCurrentGL();
+
+ int clear = 0;
+
+ if ((buffers & Renderer.BUFFER_COLOR) != 0) {
+ clear |= GL.GL_COLOR_BUFFER_BIT;
+ }
+
+ if ((buffers & Renderer.BUFFER_DEPTH) != 0) {
+ clear |= GL.GL_DEPTH_BUFFER_BIT;
+
+ // make sure no funny business is going on in the z before clearing.
+ if (defaultStateList.containsKey(RenderState.StateType.ZBuffer)) {
+ defaultStateList.get(RenderState.StateType.ZBuffer).setNeedsRefresh(true);
+ doApplyState(defaultStateList.get(RenderState.StateType.ZBuffer));
+ }
+ }
+
+ if ((buffers & Renderer.BUFFER_STENCIL) != 0) {
+ clear |= GL.GL_STENCIL_BUFFER_BIT;
+
+ gl.glClearStencil(_stencilClearValue);
+ gl.glStencilMask(~0);
+ gl.glClear(GL.GL_STENCIL_BUFFER_BIT);
+ }
+
+ if ((buffers & Renderer.BUFFER_ACCUMULATION) != 0) {
+ clear |= GL2.GL_ACCUM_BUFFER_BIT;
+ }
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord record = context.getRendererRecord();
+
+ if (strict) {
+ // grab our camera to get width and height info.
+ final Camera cam = Camera.getCurrentCamera();
+
+ gl.glEnable(GL.GL_SCISSOR_TEST);
+ gl.glScissor(0, 0, cam.getWidth(), cam.getHeight());
+ record.setClippingTestEnabled(true);
+ }
+
+ gl.glClear(clear);
+
+ if (strict) {
+ // put us back.
+ JoglRendererUtil.applyScissors(record);
+ }
+ }
+
+ public void flushFrame(final boolean doSwap) {
+ final GL gl = GLU.getCurrentGL();
+
+ renderBuckets();
+
+ gl.glFlush();
+ if (doSwap) {
+
+ doApplyState(defaultStateList.get(RenderState.StateType.ColorMask));
+
+ if (Constants.stats) {
+ StatCollector.startStat(StatType.STAT_DISPLAYSWAP_TIMER);
+ }
+
+ checkCardError();
+ GLContext.getCurrent().getGLDrawable().swapBuffers();
+ if (Constants.stats) {
+ StatCollector.endStat(StatType.STAT_DISPLAYSWAP_TIMER);
+ }
+ }
+
+ if (Constants.stats) {
+ StatCollector.addStat(StatType.STAT_FRAMES, 1);
+ }
+ }
+
+ public void setOrtho() {
+ final GL gl = GLU.getCurrentGL();
+
+ if (_inOrthoMode) {
+ throw new Ardor3dException("Already in Orthographic mode.");
+ }
+ // set up ortho mode
+ final RendererRecord matRecord = ContextManager.getCurrentContext().getRendererRecord();
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_PROJECTION);
+ gl.getGL2().glPushMatrix();
+ gl.getGL2().glLoadIdentity();
+ final Camera camera = Camera.getCurrentCamera();
+ final double viewportWidth = camera.getWidth() * (camera.getViewPortRight() - camera.getViewPortLeft());
+ final double viewportHeight = camera.getHeight() * (camera.getViewPortTop() - camera.getViewPortBottom());
+ gl.getGL2().glOrtho(0, viewportWidth, 0, viewportHeight, -1, 1);
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_MODELVIEW);
+ gl.getGL2().glPushMatrix();
+ gl.getGL2().glLoadIdentity();
+ _inOrthoMode = true;
+ }
+
+ public void unsetOrtho() {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!_inOrthoMode) {
+ throw new Ardor3dException("Not in Orthographic mode.");
+ }
+ // remove ortho mode, and go back to original
+ // state
+ final RendererRecord matRecord = ContextManager.getCurrentContext().getRendererRecord();
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_PROJECTION);
+ gl.getGL2().glPopMatrix();
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_MODELVIEW);
+ gl.getGL2().glPopMatrix();
+ _inOrthoMode = false;
+ }
+
+ public void grabScreenContents(final ByteBuffer store, final ImageDataFormat format, final int x, final int y,
+ final int w, final int h) {
+ final GL gl = GLU.getCurrentGL();
+
+ final int pixFormat = JoglTextureUtil.getGLPixelFormat(format);
+ gl.glReadPixels(x, y, w, h, pixFormat, GL.GL_UNSIGNED_BYTE, store);
+ }
+
+ public void draw(final Spatial s) {
+ if (s != null) {
+ s.onDraw(this);
+ }
+ }
+
+ public boolean checkAndAdd(final Spatial s) {
+ final RenderBucketType rqMode = s.getSceneHints().getRenderBucketType();
+ if (rqMode != RenderBucketType.Skip) {
+ getQueue().addToQueue(s, rqMode);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * re-initializes the GL context for rendering of another piece of geometry.
+ */
+ protected void postdrawGeometry(final Mesh g) {
+ // Nothing to do here yet
+ }
+
+ public void flushGraphics() {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.glFlush();
+ }
+
+ public void finishGraphics() {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.glFinish();
+ }
+
+ public void applyNormalsMode(final NormalsMode normalsMode, final ReadOnlyTransform worldTransform) {
+ final GL gl = GLU.getCurrentGL();
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord rendRecord = context.getRendererRecord();
+ if (normalsMode != NormalsMode.Off) {
+ final ContextCapabilities caps = context.getCapabilities();
+ switch (normalsMode) {
+ case NormalizeIfScaled:
+ if (worldTransform.isRotationMatrix()) {
+ final ReadOnlyVector3 scale = worldTransform.getScale();
+ if (!(scale.getX() == 1.0 && scale.getY() == 1.0 && scale.getZ() == 1.0)) {
+ if (scale.getX() == scale.getY() && scale.getY() == scale.getZ()
+ && caps.isOpenGL1_2Supported()
+ && rendRecord.getNormalMode() != GL2ES1.GL_RESCALE_NORMAL) {
+ if (rendRecord.getNormalMode() == GLLightingFunc.GL_NORMALIZE) {
+ gl.glDisable(GLLightingFunc.GL_NORMALIZE);
+ }
+ gl.glEnable(GL2ES1.GL_RESCALE_NORMAL);
+ rendRecord.setNormalMode(GL2ES1.GL_RESCALE_NORMAL);
+ } else if (rendRecord.getNormalMode() != GLLightingFunc.GL_NORMALIZE) {
+ if (rendRecord.getNormalMode() == GL2ES1.GL_RESCALE_NORMAL) {
+ gl.glDisable(GL2ES1.GL_RESCALE_NORMAL);
+ }
+ gl.glEnable(GLLightingFunc.GL_NORMALIZE);
+ rendRecord.setNormalMode(GLLightingFunc.GL_NORMALIZE);
+ }
+ } else {
+ if (rendRecord.getNormalMode() == GL2ES1.GL_RESCALE_NORMAL) {
+ gl.glDisable(GL2ES1.GL_RESCALE_NORMAL);
+ } else if (rendRecord.getNormalMode() == GLLightingFunc.GL_NORMALIZE) {
+ gl.glDisable(GLLightingFunc.GL_NORMALIZE);
+ }
+ rendRecord.setNormalMode(GL.GL_ZERO);
+ }
+ } else {
+ if (!worldTransform.getMatrix().isIdentity()) {
+ // *might* be scaled...
+ if (rendRecord.getNormalMode() != GLLightingFunc.GL_NORMALIZE) {
+ if (rendRecord.getNormalMode() == GL2ES1.GL_RESCALE_NORMAL) {
+ gl.glDisable(GL2ES1.GL_RESCALE_NORMAL);
+ }
+ gl.glEnable(GLLightingFunc.GL_NORMALIZE);
+ rendRecord.setNormalMode(GLLightingFunc.GL_NORMALIZE);
+ }
+ } else {
+ // not scaled
+ if (rendRecord.getNormalMode() == GL2ES1.GL_RESCALE_NORMAL) {
+ gl.glDisable(GL2ES1.GL_RESCALE_NORMAL);
+ } else if (rendRecord.getNormalMode() == GLLightingFunc.GL_NORMALIZE) {
+ gl.glDisable(GLLightingFunc.GL_NORMALIZE);
+ }
+ rendRecord.setNormalMode(GL.GL_ZERO);
+ }
+ }
+ break;
+ case AlwaysNormalize:
+ if (rendRecord.getNormalMode() != GLLightingFunc.GL_NORMALIZE) {
+ if (rendRecord.getNormalMode() == GL2ES1.GL_RESCALE_NORMAL) {
+ gl.glDisable(GL2ES1.GL_RESCALE_NORMAL);
+ }
+ gl.glEnable(GLLightingFunc.GL_NORMALIZE);
+ rendRecord.setNormalMode(GLLightingFunc.GL_NORMALIZE);
+ }
+ break;
+ case UseProvided:
+ default:
+ if (rendRecord.getNormalMode() == GL2ES1.GL_RESCALE_NORMAL) {
+ gl.glDisable(GL2ES1.GL_RESCALE_NORMAL);
+ } else if (rendRecord.getNormalMode() == GLLightingFunc.GL_NORMALIZE) {
+ gl.glDisable(GLLightingFunc.GL_NORMALIZE);
+ }
+ rendRecord.setNormalMode(GL.GL_ZERO);
+ break;
+ }
+ } else {
+ if (rendRecord.getNormalMode() == GL2ES1.GL_RESCALE_NORMAL) {
+ gl.glDisable(GL2ES1.GL_RESCALE_NORMAL);
+ } else if (rendRecord.getNormalMode() == GLLightingFunc.GL_NORMALIZE) {
+ gl.glDisable(GLLightingFunc.GL_NORMALIZE);
+ }
+ rendRecord.setNormalMode(GL.GL_ZERO);
+ }
+ }
+
+ public void applyDefaultColor(final ReadOnlyColorRGBA defaultColor) {
+ final GL gl = GLU.getCurrentGL();
+ if (defaultColor != null) {
+ gl.getGL2().glColor4f(defaultColor.getRed(), defaultColor.getGreen(), defaultColor.getBlue(), defaultColor
+ .getAlpha());
+ } else {
+ gl.getGL2().glColor4f(1, 1, 1, 1);
+ }
+ }
+
+ public void deleteVBOs(final Collection<Integer> ids) {
+ final GL gl = GLU.getCurrentGL();
+ final IntBuffer idBuffer = BufferUtils.createIntBuffer(ids.size());
+ idBuffer.clear();
+ for (final Integer i : ids) {
+ if (i != null && i != 0) {
+ idBuffer.put(i);
+ }
+ }
+ idBuffer.flip();
+ if (idBuffer.remaining() > 0) {
+ gl.glDeleteBuffers(idBuffer.remaining(), idBuffer);
+ }
+ }
+
+ public void deleteDisplayLists(final Collection<Integer> ids) {
+ final GL gl = GLU.getCurrentGL();
+ for (final Integer i : ids) {
+ if (i != null && i != 0) {
+ gl.getGL2().glDeleteLists(i, 1);
+ }
+ }
+ }
+
+ public void deleteVBOs(final AbstractBufferData<?> buffer) {
+ if (buffer == null) {
+ return;
+ }
+
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+
+ final int id = buffer.getVBOID(context.getGlContextRep());
+ if (id == 0) {
+ // Not on card... return.
+ return;
+ }
+
+ buffer.removeVBOID(context.getGlContextRep());
+
+ final IntBuffer idBuff = BufferUtils.createIntBuffer(1);
+ idBuff.put(id);
+ idBuff.flip();
+ gl.glDeleteBuffers(1, idBuff);
+ }
+
+ public void updateTexture1DSubImage(final Texture1D destination, final int dstOffsetX, final int dstWidth,
+ final ByteBuffer source, final int srcOffsetX) {
+ updateTexSubImage(destination, dstOffsetX, 0, 0, dstWidth, 0, 0, source, srcOffsetX, 0, 0, 0, 0, null);
+ }
+
+ public void updateTexture2DSubImage(final Texture2D destination, final int dstOffsetX, final int dstOffsetY,
+ final int dstWidth, final int dstHeight, final ByteBuffer source, final int srcOffsetX,
+ final int srcOffsetY, final int srcTotalWidth) {
+ updateTexSubImage(destination, dstOffsetX, dstOffsetY, 0, dstWidth, dstHeight, 0, source, srcOffsetX,
+ srcOffsetY, 0, srcTotalWidth, 0, null);
+ }
+
+ public void updateTexture3DSubImage(final Texture3D destination, final int dstOffsetX, final int dstOffsetY,
+ final int dstOffsetZ, final int dstWidth, final int dstHeight, final int dstDepth, final ByteBuffer source,
+ final int srcOffsetX, final int srcOffsetY, final int srcOffsetZ, final int srcTotalWidth,
+ final int srcTotalHeight) {
+ updateTexSubImage(destination, dstOffsetX, dstOffsetY, dstOffsetZ, dstWidth, dstHeight, dstDepth, source,
+ srcOffsetX, srcOffsetY, srcOffsetZ, srcTotalWidth, srcTotalHeight, null);
+ }
+
+ public void updateTextureCubeMapSubImage(final TextureCubeMap destination, final TextureCubeMap.Face dstFace,
+ final int dstOffsetX, final int dstOffsetY, final int dstWidth, final int dstHeight,
+ final ByteBuffer source, final int srcOffsetX, final int srcOffsetY, final int srcTotalWidth) {
+ updateTexSubImage(destination, dstOffsetX, dstOffsetY, 0, dstWidth, dstHeight, 0, source, srcOffsetX,
+ srcOffsetY, 0, srcTotalWidth, 0, dstFace);
+ }
+
+ private void updateTexSubImage(final Texture destination, final int dstOffsetX, final int dstOffsetY,
+ final int dstOffsetZ, final int dstWidth, final int dstHeight, final int dstDepth, final ByteBuffer source,
+ final int srcOffsetX, final int srcOffsetY, final int srcOffsetZ, final int srcTotalWidth,
+ final int srcTotalHeight, final Face dstFace) {
+
+ final GL gl = GLU.getCurrentGL();
+
+ // Ignore textures that do not have an id set
+ if (destination.getTextureIdForContext(ContextManager.getCurrentContext().getGlContextRep()) == 0) {
+ logger.warning("Attempting to update a texture that is not currently on the card.");
+ return;
+ }
+
+ // Determine the original texture configuration, so that this method can
+ // restore the texture configuration to its original state.
+ final int origAlignment[] = new int[1];
+ gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, origAlignment, 0);
+ final int origRowLength = 0;
+ final int origImageHeight = 0;
+ final int origSkipPixels = 0;
+ final int origSkipRows = 0;
+ final int origSkipImages = 0;
+
+ final int alignment = 1;
+
+ int rowLength;
+ if (srcTotalWidth == dstWidth) {
+ // When the row length is zero, then the width parameter is used.
+ // We use zero in these cases in the hope that we can avoid two
+ // unnecessary calls to glPixelStorei.
+ rowLength = 0;
+ } else {
+ // The number of pixels in a row is different than the number of
+ // pixels in the region to be uploaded to the texture.
+ rowLength = srcTotalWidth;
+ }
+
+ int imageHeight;
+ if (srcTotalHeight == dstHeight) {
+ // When the image height is zero, then the height parameter is used.
+ // We use zero in these cases in the hope that we can avoid two
+ // unnecessary calls to glPixelStorei.
+ imageHeight = 0;
+ } else {
+ // The number of pixels in a row is different than the number of
+ // pixels in the region to be uploaded to the texture.
+ imageHeight = srcTotalHeight;
+ }
+
+ // Grab pixel format
+ final int pixelFormat;
+ if (destination.getImage() != null) {
+ pixelFormat = JoglTextureUtil.getGLPixelFormat(destination.getImage().getDataFormat());
+ } else {
+ pixelFormat = JoglTextureUtil.getGLPixelFormatFromStoreFormat(destination.getTextureStoreFormat());
+ }
+
+ // bind...
+ JoglTextureStateUtil.doTextureBind(destination, 0, false);
+
+ // Update the texture configuration (when necessary).
+
+ if (origAlignment[0] != alignment) {
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, alignment);
+ }
+ if (origRowLength != rowLength) {
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, rowLength);
+ }
+ if (origSkipPixels != srcOffsetX) {
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, srcOffsetX);
+ }
+ // NOTE: The below will be skipped for texture types that don't support them because we are passing in 0's.
+ if (origSkipRows != srcOffsetY) {
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, srcOffsetY);
+ }
+ if (origImageHeight != imageHeight) {
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_IMAGE_HEIGHT, imageHeight);
+ }
+ if (origSkipImages != srcOffsetZ) {
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_IMAGES, srcOffsetZ);
+ }
+
+ // Upload the image region into the texture.
+ try {
+ switch (destination.getType()) {
+ case TwoDimensional:
+ gl.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, dstOffsetX, dstOffsetY, dstWidth, dstHeight, pixelFormat,
+ GL.GL_UNSIGNED_BYTE, source);
+ break;
+ case OneDimensional:
+ gl.getGL2GL3().glTexSubImage1D(GL2GL3.GL_TEXTURE_1D, 0, dstOffsetX, dstWidth, pixelFormat, GL.GL_UNSIGNED_BYTE,
+ source);
+ break;
+ case ThreeDimensional:
+ gl.getGL2GL3().glTexSubImage3D(GL2ES2.GL_TEXTURE_3D, 0, dstOffsetX, dstOffsetY, dstOffsetZ, dstWidth, dstHeight,
+ dstDepth, pixelFormat, GL.GL_UNSIGNED_BYTE, source);
+ break;
+ case CubeMap:
+ gl.glTexSubImage2D(JoglTextureStateUtil.getGLCubeMapFace(dstFace), 0, dstOffsetX, dstOffsetY,
+ dstWidth, dstHeight, pixelFormat, GL.GL_UNSIGNED_BYTE, source);
+ break;
+ default:
+ throw new Ardor3dException("Unsupported type for updateTextureSubImage: " + destination.getType());
+ }
+ } finally {
+ // Restore the texture configuration (when necessary)...
+ // Restore alignment.
+ if (origAlignment[0] != alignment) {
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, origAlignment[0]);
+ }
+ // Restore row length.
+ if (origRowLength != rowLength) {
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, origRowLength);
+ }
+ // Restore skip pixels.
+ if (origSkipPixels != srcOffsetX) {
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, origSkipPixels);
+ }
+ // Restore skip rows.
+ if (origSkipRows != srcOffsetY) {
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, origSkipRows);
+ }
+ // Restore image height.
+ if (origImageHeight != imageHeight) {
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_IMAGE_HEIGHT, origImageHeight);
+ }
+ // Restore skip images.
+ if (origSkipImages != srcOffsetZ) {
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_IMAGES, origSkipImages);
+ }
+ }
+ }
+
+ public void checkCardError() throws Ardor3dException {
+ final GL gl = GLU.getCurrentGL();
+ final GLU glu = new GLU();
+
+ try {
+ final int errorCode = gl.glGetError();
+ if (errorCode != GL.GL_NO_ERROR) {
+ throw new GLException(glu.gluErrorString(errorCode));
+ }
+ } catch (final GLException exception) {
+ throw new Ardor3dException("Error in opengl: " + exception.getMessage(), exception);
+ }
+ }
+
+ public void draw(final Renderable renderable) {
+ if (renderLogic != null) {
+ renderLogic.apply(renderable);
+ }
+ renderable.render(this);
+ if (renderLogic != null) {
+ renderLogic.restore(renderable);
+ }
+ }
+
+ public boolean doTransforms(final ReadOnlyTransform transform) {
+ final GL gl = GLU.getCurrentGL();
+
+ // set world matrix
+ if (!transform.isIdentity()) {
+ synchronized (_transformMatrix) {
+ transform.getGLApplyMatrix(_transformBuffer);
+
+ final RendererRecord matRecord = ContextManager.getCurrentContext().getRendererRecord();
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_MODELVIEW);
+ gl.getGL2().glPushMatrix();
+ gl.getGL2().glMultMatrixf(_transformBuffer);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void undoTransforms(final ReadOnlyTransform transform) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RendererRecord matRecord = ContextManager.getCurrentContext().getRendererRecord();
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_MODELVIEW);
+ gl.getGL2().glPopMatrix();
+ }
+
+ public void setupVertexData(final FloatBufferData vertexBufferData) {
+ final GL gl = GLU.getCurrentGL();
+
+ final FloatBuffer vertexBuffer = vertexBufferData != null ? vertexBufferData.getBuffer() : null;
+
+ if (vertexBuffer == null) {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ } else {
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ vertexBuffer.rewind();
+ gl.getGL2().glVertexPointer(vertexBufferData.getValuesPerTuple(), GL.GL_FLOAT, 0, vertexBuffer);
+ }
+ }
+
+ public void setupNormalData(final FloatBufferData normalBufferData) {
+ final GL gl = GLU.getCurrentGL();
+
+ final FloatBuffer normalBuffer = normalBufferData != null ? normalBufferData.getBuffer() : null;
+
+ if (normalBuffer == null) {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ } else {
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ normalBuffer.rewind();
+ gl.getGL2().glNormalPointer(GL.GL_FLOAT, 0, normalBuffer);
+ }
+ }
+
+ public void setupColorData(final FloatBufferData colorBufferData) {
+ final GL gl = GLU.getCurrentGL();
+
+ final FloatBuffer colorBuffer = colorBufferData != null ? colorBufferData.getBuffer() : null;
+
+ if (colorBuffer == null) {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ } else {
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ colorBuffer.rewind();
+ gl.getGL2().glColorPointer(colorBufferData.getValuesPerTuple(), GL.GL_FLOAT, 0, colorBuffer);
+ }
+ }
+
+ public void setupFogData(final FloatBufferData fogBufferData) {
+ final GL gl = GLU.getCurrentGL();
+
+ final FloatBuffer fogBuffer = fogBufferData != null ? fogBufferData.getBuffer() : null;
+
+ if (fogBuffer == null) {
+ gl.getGL2GL3().glDisableClientState(GL2.GL_FOG_COORDINATE_ARRAY);
+ } else {
+ gl.getGL2GL3().glEnableClientState(GL2.GL_FOG_COORDINATE_ARRAY);
+ fogBuffer.rewind();
+ gl.getGL2().glFogCoordPointer(GL.GL_FLOAT, 0, fogBuffer);
+ }
+ }
+
+ public void setupTextureData(final List<FloatBufferData> textureCoords) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+ final RendererRecord rendRecord = context.getRendererRecord();
+
+ final TextureState ts = (TextureState) context.getCurrentState(RenderState.StateType.Texture);
+ int enabledTextures = rendRecord.getEnabledTextures();
+ final boolean valid = rendRecord.isTexturesValid();
+ boolean isOn, wasOn;
+ if (ts != null) {
+ final int max = caps.isMultitextureSupported() ? Math.min(caps.getNumberOfFragmentTexCoordUnits(),
+ TextureState.MAX_TEXTURES) : 1;
+ for (int i = 0; i < max; i++) {
+ wasOn = (enabledTextures & (2 << i)) != 0;
+ isOn = textureCoords != null && i < textureCoords.size() && textureCoords.get(i) != null
+ && textureCoords.get(i).getBuffer() != null;
+
+ if (!isOn) {
+ if (valid && !wasOn) {
+ continue;
+ } else {
+ checkAndSetTextureArrayUnit(i, gl, rendRecord, caps);
+
+ // disable bit in tracking int
+ enabledTextures &= ~(2 << i);
+
+ // disable state
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+
+ continue;
+ }
+ } else {
+ checkAndSetTextureArrayUnit(i, gl, rendRecord, caps);
+
+ if (!valid || !wasOn) {
+ // enable state
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+
+ // enable bit in tracking int
+ enabledTextures |= (2 << i);
+ }
+
+ final FloatBufferData textureBufferData = textureCoords.get(i);
+ final FloatBuffer textureBuffer = textureBufferData.getBuffer();
+
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+ textureBuffer.rewind();
+ gl.getGL2().glTexCoordPointer(textureBufferData.getValuesPerTuple(), GL.GL_FLOAT, 0, textureBuffer);
+ }
+ }
+ }
+
+ rendRecord.setEnabledTextures(enabledTextures);
+ rendRecord.setTexturesValid(true);
+ }
+
+ public void drawElements(final IndexBufferData<?> indices, final int[] indexLengths, final IndexMode[] indexModes,
+ final int primcount) {
+ if (indices == null || indices.getBuffer() == null) {
+ logger.severe("Missing indices for drawElements call without VBO");
+ return;
+ }
+
+ final GL gl = GLU.getCurrentGL();
+
+ final int type = getGLDataType(indices);
+ if (indexLengths == null) {
+ final int glIndexMode = getGLIndexMode(indexModes[0]);
+
+ indices.position(0);
+
+ if (primcount < 0) {
+ gl.glDrawElements(glIndexMode, indices.getBufferLimit(), type, indices.getBuffer());
+ } else {
+ gl.getGL2GL3().glDrawElementsInstanced(glIndexMode, indices.getBufferLimit(), type, indices.getBuffer(),
+ primcount);
+ }
+
+ if (Constants.stats) {
+ addStats(indexModes[0], indices.getBufferLimit());
+ }
+ } else {
+ int offset = 0;
+ int indexModeCounter = 0;
+ for (int i = 0; i < indexLengths.length; i++) {
+ final int count = indexLengths[i];
+
+ final int glIndexMode = getGLIndexMode(indexModes[indexModeCounter]);
+
+ indices.getBuffer().position(offset);
+ indices.getBuffer().limit(offset + count);
+
+ if (primcount < 0) {
+ gl.glDrawElements(glIndexMode, count, type, indices.getBuffer());
+ } else {
+ gl.getGL2GL3().glDrawElementsInstanced(glIndexMode, count, type, indices.getBuffer(), primcount);
+ }
+
+ if (Constants.stats) {
+ addStats(indexModes[indexModeCounter], count);
+ }
+
+ offset += count;
+
+ if (indexModeCounter < indexModes.length - 1) {
+ indexModeCounter++;
+ }
+ }
+ }
+ }
+
+ public static int setupVBO(final AbstractBufferData<? extends Buffer> data, final RenderContext context) {
+ if (data == null) {
+ return 0;
+ }
+
+ final GL gl = GLU.getCurrentGL();
+
+ final RendererRecord rendRecord = context.getRendererRecord();
+ int vboID = data.getVBOID(context.getGlContextRep());
+ if (vboID != 0) {
+ updateVBO(data, rendRecord, vboID, 0);
+ return vboID;
+ }
+
+ final Buffer dataBuffer = data.getBuffer();
+ if (dataBuffer != null) {
+ // XXX: should we be rewinding? Maybe make that the programmer's responsibility.
+ dataBuffer.rewind();
+ vboID = makeVBOId();
+ data.setVBOID(context.getGlContextRep(), vboID);
+
+ rendRecord.invalidateVBO();
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, dataBuffer.limit() * data.getByteCount(), dataBuffer,
+ getGLVBOAccessMode(data.getVboAccessMode()));
+ } else {
+ throw new Ardor3dException("Attempting to create a vbo id for an AbstractBufferData with no Buffer value.");
+ }
+ return vboID;
+ }
+
+ private static void updateVBO(final AbstractBufferData<? extends Buffer> data, final RendererRecord rendRecord,
+ final int vboID, final int offsetBytes) {
+ if (data.isNeedsRefresh()) {
+ final GL gl = GLU.getCurrentGL();
+ final Buffer dataBuffer = data.getBuffer();
+ dataBuffer.rewind();
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, offsetBytes, dataBuffer.limit() * data.getByteCount(),
+ dataBuffer);
+ data.setNeedsRefresh(false);
+ }
+ }
+
+ private int setupIndicesVBO(final IndexBufferData<?> data, final RenderContext context,
+ final RendererRecord rendRecord) {
+ if (data == null) {
+ return 0;
+ }
+
+ final GL gl = GLU.getCurrentGL();
+
+ int vboID = data.getVBOID(context.getGlContextRep());
+ if (vboID != 0) {
+ if (data.isNeedsRefresh()) {
+ final Buffer dataBuffer = data.getBuffer();
+ dataBuffer.rewind();
+ JoglRendererUtil.setBoundElementVBO(rendRecord, vboID);
+ gl.glBufferSubData(GL.GL_ELEMENT_ARRAY_BUFFER, 0, dataBuffer.limit() * data.getByteCount(),
+ dataBuffer);
+ data.setNeedsRefresh(false);
+ }
+
+ return vboID;
+ }
+
+ final Buffer dataBuffer = data.getBuffer();
+ if (dataBuffer != null) {
+ // XXX: should we be rewinding? Maybe make that the programmer's responsibility.
+ dataBuffer.rewind();
+ vboID = makeVBOId();
+ data.setVBOID(context.getGlContextRep(), vboID);
+
+ rendRecord.invalidateVBO();
+ JoglRendererUtil.setBoundElementVBO(rendRecord, vboID);
+ gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, dataBuffer.limit() * data.getByteCount(), dataBuffer,
+ getGLVBOAccessMode(data.getVboAccessMode()));
+ } else {
+ throw new Ardor3dException("Attempting to create a vbo id for a IndexBufferData with no Buffer value.");
+ }
+ return vboID;
+ }
+
+ public void setupVertexDataVBO(final FloatBufferData data) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord rendRecord = context.getRendererRecord();
+
+ final int vboID = setupVBO(data, context);
+
+ if (vboID != 0) {
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+ gl.getGL2().glVertexPointer(data.getValuesPerTuple(), GL.GL_FLOAT, 0, 0);
+ } else {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ }
+ }
+
+ public void setupNormalDataVBO(final FloatBufferData data) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord rendRecord = context.getRendererRecord();
+
+ final int vboID = setupVBO(data, context);
+
+ if (vboID != 0) {
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+ gl.getGL2().glNormalPointer(GL.GL_FLOAT, 0, 0);
+ } else {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ }
+ }
+
+ public void setupColorDataVBO(final FloatBufferData data) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord rendRecord = context.getRendererRecord();
+
+ final int vboID = setupVBO(data, context);
+
+ if (vboID != 0) {
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+ gl.getGL2().glColorPointer(data.getValuesPerTuple(), GL.GL_FLOAT, 0, 0);
+ } else {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ }
+ }
+
+ public void setupFogDataVBO(final FloatBufferData data) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+
+ if (!caps.isFogCoordinatesSupported()) {
+ return;
+ }
+
+ final RendererRecord rendRecord = context.getRendererRecord();
+ final int vboID = setupVBO(data, context);
+
+ if (vboID != 0) {
+ gl.getGL2GL3().glEnableClientState(GL2.GL_FOG_COORDINATE_ARRAY);
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+ gl.getGL2().glFogCoordPointer(GL.GL_FLOAT, 0, 0);
+ } else {
+ gl.getGL2GL3().glDisableClientState(GL2.GL_FOG_COORDINATE_ARRAY);
+ }
+ }
+
+ public void setupTextureDataVBO(final List<FloatBufferData> textureCoords) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord rendRecord = context.getRendererRecord();
+ final ContextCapabilities caps = context.getCapabilities();
+
+ final TextureState ts = (TextureState) context.getCurrentState(RenderState.StateType.Texture);
+ int enabledTextures = rendRecord.getEnabledTextures();
+ final boolean valid = rendRecord.isTexturesValid();
+ boolean exists, wasOn;
+ if (ts != null) {
+ final int max = caps.isMultitextureSupported() ? Math.min(caps.getNumberOfFragmentTexCoordUnits(),
+ TextureState.MAX_TEXTURES) : 1;
+ for (int i = 0; i < max; i++) {
+ wasOn = (enabledTextures & (2 << i)) != 0;
+ exists = textureCoords != null && i < textureCoords.size();
+
+ if (!exists) {
+ if (valid && !wasOn) {
+ continue;
+ } else {
+ checkAndSetTextureArrayUnit(i, gl, rendRecord, caps);
+
+ // disable bit in tracking int
+ enabledTextures &= ~(2 << i);
+
+ // disable state
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+
+ continue;
+ }
+ } else {
+ checkAndSetTextureArrayUnit(i, gl, rendRecord, caps);
+
+ // grab a vboID and make sure it exists and is up to date.
+ final FloatBufferData data = textureCoords.get(i);
+ final int vboID = setupVBO(data, context);
+
+ // Found good vbo
+ if (vboID != 0) {
+ if (!valid || !wasOn) {
+ // enable bit in tracking int
+ enabledTextures |= (2 << i);
+
+ // enable state
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+ }
+
+ // set our active vbo
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+
+ // send data
+ gl.getGL2().glTexCoordPointer(data.getValuesPerTuple(), GL.GL_FLOAT, 0, 0);
+ }
+ // Not a good vbo, disable it.
+ else {
+ if (!valid || wasOn) {
+ // disable bit in tracking int
+ enabledTextures &= ~(2 << i);
+
+ // disable state
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+ }
+ }
+ }
+
+ rendRecord.setEnabledTextures(enabledTextures);
+ rendRecord.setTexturesValid(true);
+ }
+
+ public void setupInterleavedDataVBO(final FloatBufferData interleaved, final FloatBufferData vertexCoords,
+ final FloatBufferData normalCoords, final FloatBufferData colorCoords,
+ final List<FloatBufferData> textureCoords) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord rendRecord = context.getRendererRecord();
+ final ContextCapabilities caps = context.getCapabilities();
+
+ final int lengthBytes = getTotalInterleavedSize(context, vertexCoords, normalCoords, colorCoords, textureCoords);
+ int currLengthBytes = 0;
+ if (interleaved.getBufferLimit() > 0) {
+ interleaved.getBuffer().rewind();
+ currLengthBytes = Math.round(interleaved.getBuffer().get());
+ }
+
+ if (lengthBytes != currLengthBytes || interleaved.getVBOID(context.getGlContextRep()) == 0
+ || interleaved.isNeedsRefresh()) {
+ initializeInterleavedVBO(context, interleaved, vertexCoords, normalCoords, colorCoords, textureCoords,
+ lengthBytes);
+ }
+
+ final int vboID = interleaved.getVBOID(context.getGlContextRep());
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+
+ int offsetBytes = 0;
+
+ if (normalCoords != null) {
+ updateVBO(normalCoords, rendRecord, vboID, offsetBytes);
+ gl.getGL2().glNormalPointer(GL.GL_FLOAT, 0, offsetBytes);
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ offsetBytes += normalCoords.getBufferLimit() * 4;
+ } else {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ }
+
+ if (colorCoords != null) {
+ updateVBO(colorCoords, rendRecord, vboID, offsetBytes);
+ gl.getGL2().glColorPointer(colorCoords.getValuesPerTuple(), GL.GL_FLOAT, 0, offsetBytes);
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ offsetBytes += colorCoords.getBufferLimit() * 4;
+ } else {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ }
+
+ if (textureCoords != null) {
+ final TextureState ts = (TextureState) context.getCurrentState(RenderState.StateType.Texture);
+ int enabledTextures = rendRecord.getEnabledTextures();
+ final boolean valid = rendRecord.isTexturesValid();
+ boolean exists, wasOn;
+ if (ts != null) {
+ final int max = caps.isMultitextureSupported() ? Math.min(caps.getNumberOfFragmentTexCoordUnits(),
+ TextureState.MAX_TEXTURES) : 1;
+ for (int i = 0; i < max; i++) {
+ wasOn = (enabledTextures & (2 << i)) != 0;
+ exists = textureCoords != null && i < textureCoords.size() && textureCoords.get(i) != null
+ && i <= ts.getMaxTextureIndexUsed();
+
+ if (!exists) {
+ if (valid && !wasOn) {
+ continue;
+ } else {
+ checkAndSetTextureArrayUnit(i, gl, rendRecord, caps);
+
+ // disable bit in tracking int
+ enabledTextures &= ~(2 << i);
+
+ // disable state
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+
+ continue;
+ }
+
+ } else {
+ checkAndSetTextureArrayUnit(i, gl, rendRecord, caps);
+
+ // grab a vboID and make sure it exists and is up to date.
+ final FloatBufferData textureBufferData = textureCoords.get(i);
+ updateVBO(textureBufferData, rendRecord, vboID, offsetBytes);
+
+ if (!valid || !wasOn) {
+ // enable bit in tracking int
+ enabledTextures |= (2 << i);
+
+ // enable state
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+ }
+
+ // send data
+ gl.getGL2().glTexCoordPointer(textureBufferData.getValuesPerTuple(), GL.GL_FLOAT, 0, offsetBytes);
+ offsetBytes += textureBufferData.getBufferLimit() * 4;
+ }
+ }
+ }
+
+ rendRecord.setEnabledTextures(enabledTextures);
+ rendRecord.setTexturesValid(true);
+ }
+
+ if (vertexCoords != null) {
+ updateVBO(vertexCoords, rendRecord, vboID, offsetBytes);
+ gl.getGL2().glVertexPointer(vertexCoords.getValuesPerTuple(), GL.GL_FLOAT, 0, offsetBytes);
+ gl.getGL2GL3().glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ } else {
+ gl.getGL2GL3().glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ }
+ }
+
+ private void initializeInterleavedVBO(final RenderContext context, final FloatBufferData interleaved,
+ final FloatBufferData vertexCoords, final FloatBufferData normalCoords, final FloatBufferData colorCoords,
+ final List<FloatBufferData> textureCoords, final int bufferSize) {
+
+ // keep around buffer size
+ if (interleaved.getBufferCapacity() != 1) {
+ final FloatBuffer buffer = BufferUtils.createFloatBufferOnHeap(1);
+ interleaved.setBuffer(buffer);
+ }
+ interleaved.getBuffer().rewind();
+ interleaved.getBuffer().put(bufferSize);
+
+ final GL gl = GLU.getCurrentGL();
+
+ final RendererRecord rendRecord = context.getRendererRecord();
+ final ContextCapabilities caps = context.getCapabilities();
+
+ final int vboID = makeVBOId();
+ interleaved.setVBOID(context.getGlContextRep(), vboID);
+
+ rendRecord.invalidateVBO();
+ JoglRendererUtil.setBoundVBO(rendRecord, vboID);
+ gl
+ .glBufferData(GL.GL_ARRAY_BUFFER, bufferSize, null, getGLVBOAccessMode(interleaved
+ .getVboAccessMode()));
+
+ int offset = 0;
+ if (normalCoords != null) {
+ normalCoords.getBuffer().rewind();
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, offset, normalCoords.getBufferLimit() * 4, normalCoords
+ .getBuffer());
+ offset += normalCoords.getBufferLimit() * 4;
+ }
+ if (colorCoords != null) {
+ colorCoords.getBuffer().rewind();
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, offset, colorCoords.getBufferLimit() * 4, colorCoords
+ .getBuffer());
+ offset += colorCoords.getBufferLimit() * 4;
+ }
+ if (textureCoords != null) {
+ final TextureState ts = (TextureState) context.getCurrentState(RenderState.StateType.Texture);
+ if (ts != null) {
+ for (int i = 0; i <= ts.getMaxTextureIndexUsed() && i < caps.getNumberOfFragmentTexCoordUnits(); i++) {
+ if (textureCoords == null || i >= textureCoords.size()) {
+ continue;
+ }
+
+ final FloatBufferData textureBufferData = textureCoords.get(i);
+ final FloatBuffer textureBuffer = textureBufferData != null ? textureBufferData.getBuffer() : null;
+ if (textureBuffer != null) {
+ textureBuffer.rewind();
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, offset, textureBufferData.getBufferLimit() * 4,
+ textureBuffer);
+ offset += textureBufferData.getBufferLimit() * 4;
+ }
+ }
+ }
+ }
+ if (vertexCoords != null) {
+ vertexCoords.getBuffer().rewind();
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, offset, vertexCoords.getBufferLimit() * 4, vertexCoords
+ .getBuffer());
+ }
+
+ interleaved.setNeedsRefresh(false);
+ }
+
+ public void drawElementsVBO(final IndexBufferData<?> indices, final int[] indexLengths,
+ final IndexMode[] indexModes, final int primcount) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord rendRecord = context.getRendererRecord();
+
+ final int vboID = setupIndicesVBO(indices, context, rendRecord);
+
+ JoglRendererUtil.setBoundElementVBO(rendRecord, vboID);
+
+ if (indexLengths == null) {
+ final int glIndexMode = getGLIndexMode(indexModes[0]);
+
+ final int type = getGLDataType(indices);
+
+ if (primcount < 0) {
+ gl.glDrawElements(glIndexMode, indices.getBufferLimit(), type, 0);
+ } else {
+ gl.getGL2GL3().glDrawElementsInstanced(glIndexMode, indices.getBufferLimit(), type, indices.getBuffer(),
+ primcount);
+ }
+
+ if (Constants.stats) {
+ addStats(indexModes[0], indices.getBufferLimit());
+ }
+ } else {
+ int offset = 0;
+ int indexModeCounter = 0;
+ for (int i = 0; i < indexLengths.length; i++) {
+ final int count = indexLengths[i];
+
+ final int glIndexMode = getGLIndexMode(indexModes[indexModeCounter]);
+
+ final int type = getGLDataType(indices);
+ final int byteSize = indices.getByteCount();
+ // offset in this call is done in bytes.
+ gl.glDrawElements(glIndexMode, count, type, offset * byteSize);
+
+ if (primcount < 0) {
+ gl.glDrawElements(glIndexMode, count, type, offset * byteSize);
+ } else {
+ final int previousPos = indices.getBuffer().position();
+ indices.getBuffer().position(offset * byteSize);
+ gl.getGL2GL3().glDrawElementsInstanced(glIndexMode, count, type, indices.getBuffer(), primcount);
+ indices.getBuffer().position(previousPos);
+ }
+
+ if (Constants.stats) {
+ addStats(indexModes[indexModeCounter], count);
+ }
+
+ offset += count;
+
+ if (indexModeCounter < indexModes.length - 1) {
+ indexModeCounter++;
+ }
+ }
+ }
+ }
+
+ public void drawArrays(final FloatBufferData vertexBuffer, final int[] indexLengths, final IndexMode[] indexModes,
+ final int primcount) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (indexLengths == null) {
+ final int glIndexMode = getGLIndexMode(indexModes[0]);
+
+ if (primcount < 0) {
+ gl.glDrawArrays(glIndexMode, 0, vertexBuffer.getTupleCount());
+ } else {
+ gl.getGL2GL3().glDrawArraysInstanced(glIndexMode, 0, vertexBuffer.getTupleCount(), primcount);
+ }
+
+ if (Constants.stats) {
+ addStats(indexModes[0], vertexBuffer.getTupleCount());
+ }
+ } else {
+ int offset = 0;
+ int indexModeCounter = 0;
+ for (int i = 0; i < indexLengths.length; i++) {
+ final int count = indexLengths[i];
+
+ final int glIndexMode = getGLIndexMode(indexModes[indexModeCounter]);
+
+ if (primcount < 0) {
+ gl.glDrawArrays(glIndexMode, offset, count);
+ } else {
+ gl.getGL2GL3().glDrawArraysInstanced(glIndexMode, offset, count, primcount);
+ }
+
+ if (Constants.stats) {
+ addStats(indexModes[indexModeCounter], count);
+ }
+
+ offset += count;
+
+ if (indexModeCounter < indexModes.length - 1) {
+ indexModeCounter++;
+ }
+ }
+ }
+ }
+
+ private static int makeVBOId() {
+ final GL gl = GLU.getCurrentGL();
+
+ final IntBuffer idBuff = BufferUtils.createIntBuffer(1);
+ gl.glGenBuffers(1, idBuff);
+ return idBuff.get(0);
+ }
+
+ public void unbindVBO() {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord rendRecord = context.getRendererRecord();
+ JoglRendererUtil.setBoundVBO(rendRecord, 0);
+ JoglRendererUtil.setBoundElementVBO(rendRecord, 0);
+ }
+
+ private static int getGLVBOAccessMode(final VBOAccessMode vboAccessMode) {
+ int glMode = GL.GL_STATIC_DRAW;
+ switch (vboAccessMode) {
+ case StaticDraw:
+ glMode = GL.GL_STATIC_DRAW;
+ break;
+ case StaticRead:
+ glMode = GL2GL3.GL_STATIC_READ;
+ break;
+ case StaticCopy:
+ glMode = GL2GL3.GL_STATIC_COPY;
+ break;
+ case DynamicDraw:
+ glMode = GL.GL_DYNAMIC_DRAW;
+ break;
+ case DynamicRead:
+ glMode = GL2GL3.GL_DYNAMIC_READ;
+ break;
+ case DynamicCopy:
+ glMode = GL2GL3.GL_DYNAMIC_COPY;
+ break;
+ case StreamDraw:
+ glMode = GL2ES2.GL_STREAM_DRAW;
+ break;
+ case StreamRead:
+ glMode = GL2GL3.GL_STREAM_READ;
+ break;
+ case StreamCopy:
+ glMode = GL2GL3.GL_STREAM_COPY;
+ break;
+ }
+ return glMode;
+ }
+
+ private int getGLIndexMode(final IndexMode indexMode) {
+ int glMode = GL.GL_TRIANGLES;
+ switch (indexMode) {
+ case Triangles:
+ glMode = GL.GL_TRIANGLES;
+ break;
+ case TriangleStrip:
+ glMode = GL.GL_TRIANGLE_STRIP;
+ break;
+ case TriangleFan:
+ glMode = GL.GL_TRIANGLE_FAN;
+ break;
+ case Quads:
+ glMode = GL2.GL_QUADS;
+ break;
+ case QuadStrip:
+ glMode = GL2.GL_QUAD_STRIP;
+ break;
+ case Lines:
+ glMode = GL.GL_LINES;
+ break;
+ case LineStrip:
+ glMode = GL.GL_LINE_STRIP;
+ break;
+ case LineLoop:
+ glMode = GL.GL_LINE_LOOP;
+ break;
+ case Points:
+ glMode = GL.GL_POINTS;
+ break;
+ }
+ return glMode;
+ }
+
+ private int getGLDataType(final IndexBufferData<?> indices) {
+ if (indices.getBuffer() instanceof ByteBuffer) {
+ return GL.GL_UNSIGNED_BYTE;
+ } else if (indices.getBuffer() instanceof ShortBuffer) {
+ return GL.GL_UNSIGNED_SHORT;
+ } else if (indices.getBuffer() instanceof IntBuffer) {
+ return GL.GL_UNSIGNED_INT;
+ }
+
+ throw new IllegalArgumentException("Unknown buffer type: " + indices.getBuffer());
+ }
+
+ public void setModelViewMatrix(final FloatBuffer matrix) {
+ final RendererRecord matRecord = ContextManager.getCurrentContext().getRendererRecord();
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_MODELVIEW);
+
+ loadMatrix(matrix);
+ }
+
+ public void setProjectionMatrix(final FloatBuffer matrix) {
+ final RendererRecord matRecord = ContextManager.getCurrentContext().getRendererRecord();
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_PROJECTION);
+
+ loadMatrix(matrix);
+ }
+
+ private void loadMatrix(final FloatBuffer matrix) {
+ GLU.getCurrentGL().getGL2().glLoadMatrixf(matrix);
+ }
+
+ public FloatBuffer getModelViewMatrix(final FloatBuffer store) {
+ return getMatrix(GLMatrixFunc.GL_MODELVIEW_MATRIX, store);
+ }
+
+ public FloatBuffer getProjectionMatrix(final FloatBuffer store) {
+ return getMatrix(GLMatrixFunc.GL_PROJECTION_MATRIX, store);
+ }
+
+ private FloatBuffer getMatrix(final int matrixType, final FloatBuffer store) {
+ FloatBuffer result = store;
+ if (result.remaining() < 16) {
+ result = BufferUtils.createFloatBuffer(16);
+ }
+ GLU.getCurrentGL().glGetFloatv(matrixType, store);
+ return result;
+ }
+
+ public void setViewport(final int x, final int y, final int width, final int height) {
+ GLU.getCurrentGL().glViewport(x, y, width, height);
+ }
+
+ public void setDepthRange(final double depthRangeNear, final double depthRangeFar) {
+ GLU.getCurrentGL().glDepthRange(depthRangeNear, depthRangeFar);
+ }
+
+ public void setDrawBuffer(final DrawBufferTarget target) {
+ final RendererRecord record = ContextManager.getCurrentContext().getRendererRecord();
+ if (record.getDrawBufferTarget() != target) {
+ int buffer = GL.GL_BACK;
+ switch (target) {
+ case None:
+ case Back:
+ break;
+ case Front:
+ buffer = GL.GL_FRONT;
+ break;
+ case BackLeft:
+ buffer = GL2GL3.GL_BACK_LEFT;
+ break;
+ case BackRight:
+ buffer = GL2GL3.GL_BACK_RIGHT;
+ break;
+ case FrontLeft:
+ buffer = GL2GL3.GL_FRONT_LEFT;
+ break;
+ case FrontRight:
+ buffer = GL2GL3.GL_FRONT_RIGHT;
+ break;
+ case FrontAndBack:
+ buffer = GL.GL_FRONT_AND_BACK;
+ break;
+ case Left:
+ buffer = GL2GL3.GL_LEFT;
+ break;
+ case Right:
+ buffer = GL2GL3.GL_RIGHT;
+ break;
+ case Aux0:
+ buffer = GL2.GL_AUX0;
+ break;
+ case Aux1:
+ buffer = GL2.GL_AUX1;
+ break;
+ case Aux2:
+ buffer = GL2.GL_AUX2;
+ break;
+ case Aux3:
+ buffer = GL2.GL_AUX3;
+ break;
+ }
+
+ GLU.getCurrentGL().getGL2GL3().glDrawBuffer(buffer);
+ record.setDrawBufferTarget(target);
+ }
+ }
+
+ public void setupLineParameters(final float lineWidth, final int stippleFactor, final short stipplePattern,
+ final boolean antialiased) {
+ final GL gl = GLU.getCurrentGL();
+
+ final LineRecord lineRecord = ContextManager.getCurrentContext().getLineRecord();
+
+ if (!lineRecord.isValid() || lineRecord.width != lineWidth) {
+ gl.glLineWidth(lineWidth);
+ lineRecord.width = lineWidth;
+ }
+
+ if (stipplePattern != (short) 0xFFFF) {
+ if (!lineRecord.isValid() || !lineRecord.stippled) {
+ gl.glEnable(GL2.GL_LINE_STIPPLE);
+ lineRecord.stippled = true;
+ }
+
+ if (!lineRecord.isValid() || stippleFactor != lineRecord.stippleFactor
+ || stipplePattern != lineRecord.stipplePattern) {
+ gl.getGL2().glLineStipple(stippleFactor, stipplePattern);
+ lineRecord.stippleFactor = stippleFactor;
+ lineRecord.stipplePattern = stipplePattern;
+ }
+ } else if (!lineRecord.isValid() || lineRecord.stippled) {
+ gl.glDisable(GL2.GL_LINE_STIPPLE);
+ lineRecord.stippled = false;
+ }
+
+ if (antialiased) {
+ if (!lineRecord.isValid() || !lineRecord.smoothed) {
+ gl.glEnable(GL.GL_LINE_SMOOTH);
+ lineRecord.smoothed = true;
+ }
+ if (!lineRecord.isValid() || lineRecord.smoothHint != GL.GL_NICEST) {
+ gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_NICEST);
+ lineRecord.smoothHint = GL.GL_NICEST;
+ }
+ } else if (!lineRecord.isValid() || lineRecord.smoothed) {
+ gl.glDisable(GL.GL_LINE_SMOOTH);
+ lineRecord.smoothed = false;
+ }
+
+ if (!lineRecord.isValid()) {
+ lineRecord.validate();
+ }
+ }
+
+ @Override
+ public void setupPointParameters(final float pointSize, final boolean antialiased, final boolean isSprite,
+ final boolean useDistanceAttenuation, final FloatBuffer attenuationCoefficients, final float minPointSize,
+ final float maxPointSize) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final GL gl = GLU.getCurrentGL();
+
+ // TODO: make this into a pointrecord call
+ gl.getGL2GL3().glPointSize(pointSize);
+ if (antialiased) {
+ gl.glEnable(GL2ES1.GL_POINT_SMOOTH);
+ gl.glHint(GL2ES1.GL_POINT_SMOOTH_HINT, GL.GL_NICEST);
+ }
+
+ if (isSprite && context.getCapabilities().isPointSpritesSupported()) {
+ gl.glEnable(GL2ES1.GL_POINT_SPRITE);
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_POINT_SPRITE, GL2ES1.GL_COORD_REPLACE, GL.GL_TRUE);
+ }
+
+ if (useDistanceAttenuation && context.getCapabilities().isPointParametersSupported()) {
+ gl.getGL2GL3().glPointParameterfv(GL2ES1.GL_POINT_DISTANCE_ATTENUATION, attenuationCoefficients);
+ gl.getGL2GL3().glPointParameterf(GL2ES1.GL_POINT_SIZE_MIN, minPointSize);
+ gl.getGL2GL3().glPointParameterf(GL2ES1.GL_POINT_SIZE_MAX, maxPointSize);
+ }
+ }
+
+ @Override
+ protected void doApplyState(final RenderState state) {
+ switch (state.getType()) {
+ case Texture:
+ JoglTextureStateUtil.apply(this, (TextureState) state);
+ return;
+ case Light:
+ JoglLightStateUtil.apply(this, (LightState) state);
+ return;
+ case Blend:
+ JoglBlendStateUtil.apply(this, (BlendState) state);
+ return;
+ case Clip:
+ JoglClipStateUtil.apply(this, (ClipState) state);
+ return;
+ case ColorMask:
+ JoglColorMaskStateUtil.apply(this, (ColorMaskState) state);
+ return;
+ case Cull:
+ JoglCullStateUtil.apply(this, (CullState) state);
+ return;
+ case Fog:
+ JoglFogStateUtil.apply(this, (FogState) state);
+ return;
+ case FragmentProgram:
+ JoglFragmentProgramStateUtil.apply(this, (FragmentProgramState) state);
+ return;
+ case GLSLShader:
+ JoglShaderObjectsStateUtil.apply(this, (GLSLShaderObjectsState) state);
+ return;
+ case Material:
+ JoglMaterialStateUtil.apply(this, (MaterialState) state);
+ return;
+ case Offset:
+ JoglOffsetStateUtil.apply(this, (OffsetState) state);
+ return;
+ case Shading:
+ JoglShadingStateUtil.apply(this, (ShadingState) state);
+ return;
+ case Stencil:
+ JoglStencilStateUtil.apply(this, (StencilState) state);
+ return;
+ case VertexProgram:
+ JoglVertexProgramStateUtil.apply(this, (VertexProgramState) state);
+ return;
+ case Wireframe:
+ JoglWireframeStateUtil.apply(this, (WireframeState) state);
+ return;
+ case ZBuffer:
+ JoglZBufferStateUtil.apply(this, (ZBufferState) state);
+ return;
+ }
+ throw new IllegalArgumentException("Unknown state: " + state);
+ }
+
+ public void deleteTexture(final Texture texture) {
+ JoglTextureStateUtil.deleteTexture(texture);
+ }
+
+ public void loadTexture(final Texture texture, final int unit) {
+ JoglTextureStateUtil.load(texture, unit);
+ }
+
+ public void deleteTextureIds(final Collection<Integer> ids) {
+ JoglTextureStateUtil.deleteTextureIds(ids);
+ }
+
+ /**
+ * Start a new display list. All further renderer commands that can be stored in a display list are part of this new
+ * list until {@link #endDisplayList()} is called.
+ *
+ * @return id of new display list
+ */
+ public int startDisplayList() {
+ final GL gl = GLU.getCurrentGL();
+
+ final int id = gl.getGL2().glGenLists(1);
+
+ gl.getGL2().glNewList(id, GL2.GL_COMPILE);
+
+ return id;
+ }
+
+ /**
+ * Ends a display list. Will likely cause an OpenGL exception is a display list is not currently being generated.
+ */
+ public void endDisplayList() {
+ GLU.getCurrentGL().getGL2().glEndList();
+ }
+
+ /**
+ * Draw the given display list.
+ */
+ public void renderDisplayList(final int displayListID) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2().glCallList(displayListID);
+ }
+
+ public void clearClips() {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord record = context.getRendererRecord();
+ record.getScissorClips().clear();
+
+ JoglRendererUtil.applyScissors(record);
+ }
+
+ public void popClip() {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord record = context.getRendererRecord();
+ record.getScissorClips().pop();
+
+ JoglRendererUtil.applyScissors(record);
+ }
+
+ public void pushClip(final ReadOnlyRectangle2 rectangle) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord record = context.getRendererRecord();
+ record.getScissorClips().push(rectangle);
+
+ JoglRendererUtil.applyScissors(record);
+ }
+
+ public void pushEmptyClip() {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord record = context.getRendererRecord();
+ record.getScissorClips().push(null);
+
+ JoglRendererUtil.applyScissors(record);
+ }
+
+ public void setClipTestEnabled(final boolean enabled) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord record = context.getRendererRecord();
+
+ JoglRendererUtil.setClippingEnabled(record, enabled);
+ }
+
+ public void checkAndSetTextureArrayUnit(final int unit, final GL gl, final RendererRecord record,
+ final ContextCapabilities caps) {
+ if (record.getCurrentTextureArraysUnit() != unit && caps.isMultitextureSupported()) {
+ gl.getGL2().glClientActiveTexture(GL.GL_TEXTURE0 + unit);
+ record.setCurrentTextureArraysUnit(unit);
+ }
+ }
+} \ No newline at end of file
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRenderer.java b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRenderer.java
new file mode 100644
index 0000000..99719df
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRenderer.java
@@ -0,0 +1,571 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.renderer.jogl;
+
+import java.nio.IntBuffer;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.framework.Scene;
+import com.ardor3d.image.Texture;
+import com.ardor3d.image.Texture.Type;
+import com.ardor3d.image.TextureCubeMap;
+import com.ardor3d.image.TextureCubeMap.Face;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.AbstractFBOTextureRenderer;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.TextureRendererFactory;
+import com.ardor3d.renderer.state.RenderState;
+import com.ardor3d.renderer.state.record.RendererRecord;
+import com.ardor3d.renderer.state.record.TextureRecord;
+import com.ardor3d.renderer.state.record.TextureStateRecord;
+import com.ardor3d.scene.state.jogl.JoglTextureStateUtil;
+import com.ardor3d.scene.state.jogl.util.JoglTextureUtil;
+import com.ardor3d.scenegraph.Spatial;
+import com.ardor3d.util.Ardor3dException;
+import com.ardor3d.util.TextureKey;
+import com.ardor3d.util.geom.BufferUtils;
+
+/**
+ * <p>
+ * This class is used by Ardor3D's JOGL implementation to render textures. Users should <b>not</b> create this class
+ * directly.
+ * </p>
+ *
+ * @see TextureRendererFactory
+ */
+public class JoglTextureRenderer extends AbstractFBOTextureRenderer {
+ private static final Logger logger = Logger.getLogger(JoglTextureRenderer.class.getName());
+
+ public JoglTextureRenderer(final int width, final int height, final int depthBits, final int samples,
+ final Renderer parentRenderer, final ContextCapabilities caps) {
+ super(width, height, depthBits, samples, parentRenderer, caps);
+
+ if (caps.getMaxFBOColorAttachments() > 1) {
+ _attachBuffer = BufferUtils.createIntBuffer(caps.getMaxFBOColorAttachments());
+ for (int i = 0; i < caps.getMaxFBOColorAttachments(); i++) {
+ _attachBuffer.put(GL.GL_COLOR_ATTACHMENT0 + i);
+ }
+ }
+ }
+
+ /**
+ * <code>setupTexture</code> initializes a new Texture object for use with TextureRenderer. Generates a valid OpenGL
+ * texture id for this texture and initializes the data type for the texture.
+ */
+ public void setupTexture(final Texture tex) {
+ if (tex.getType() != Type.TwoDimensional && tex.getType() != Type.CubeMap) {
+ throw new IllegalArgumentException("Texture type not supported: " + tex.getType());
+ }
+
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final TextureStateRecord record = (TextureStateRecord) context.getStateRecord(RenderState.StateType.Texture);
+
+ // check if we are already setup... if so, throw error.
+ if (tex.getTextureKey() == null) {
+ tex.setTextureKey(TextureKey.getRTTKey(tex.getMinificationFilter()));
+ } else if (tex.getTextureIdForContext(context.getGlContextRep()) != 0) {
+ throw new Ardor3dException("Texture is already setup and has id.");
+ }
+
+ // Create the texture
+ final IntBuffer ibuf = BufferUtils.createIntBuffer(1);
+ gl.glGenTextures(ibuf.limit(), ibuf); // TODO Check <size>
+ final int textureId = ibuf.get(0);
+ tex.setTextureIdForContext(context.getGlContextRep(), textureId);
+
+ JoglTextureStateUtil.doTextureBind(tex, 0, true);
+
+ // Initialize our texture with some default data.
+ final int internalFormat = JoglTextureUtil.getGLInternalFormat(tex.getTextureStoreFormat());
+ final int dataFormat = JoglTextureUtil.getGLPixelFormatFromStoreFormat(tex.getTextureStoreFormat());
+ final int pixelDataType = JoglTextureUtil.getGLPixelDataType(tex.getRenderedTexturePixelDataType());
+
+ if (tex.getType() == Type.TwoDimensional) {
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, internalFormat, _width, _height, 0, dataFormat, pixelDataType,
+ null);
+ } else {
+ for (final Face face : Face.values()) {
+ gl.glTexImage2D(JoglTextureStateUtil.getGLCubeMapFace(face), 0, internalFormat, _width, _height, 0,
+ dataFormat, pixelDataType, null);
+ }
+ }
+
+ // Initialize mipmapping for this texture, if requested
+ if (tex.getMinificationFilter().usesMipMapLevels()) {
+ gl.glGenerateMipmap(JoglTextureStateUtil.getGLType(tex.getType()));
+ }
+
+ // Setup filtering and wrap
+ final TextureRecord texRecord = record.getTextureRecord(textureId, tex.getType());
+ JoglTextureStateUtil.applyFilter(tex, texRecord, 0, record, context.getCapabilities());
+ JoglTextureStateUtil.applyWrap(tex, texRecord, 0, record, context.getCapabilities());
+
+ logger.fine("setup fbo tex with id " + textureId + ": " + _width + "," + _height);
+ }
+
+ public void render(final Spatial spat, final List<Texture> texs, final int clear) {
+ render(null, spat, null, texs, clear);
+ }
+
+ public void render(final List<? extends Spatial> spat, final List<Texture> texs, final int clear) {
+ render(spat, null, null, texs, clear);
+ }
+
+ @Override
+ public void render(final Scene scene, final List<Texture> texs, final int clear) {
+ render(null, null, scene, texs, clear);
+ }
+
+ private void render(final List<? extends Spatial> toDrawA, final Spatial toDrawB, final Scene toDrawC,
+ final List<Texture> texs, final int clear) {
+ final GL gl = GLU.getCurrentGL();
+
+ final int maxDrawBuffers = ContextManager.getCurrentContext().getCapabilities().getMaxFBOColorAttachments();
+
+ // if we only support 1 draw buffer at a time anyway, we'll have to render to each texture individually...
+ if (maxDrawBuffers == 1 || texs.size() == 1) {
+ try {
+ ContextManager.getCurrentContext().pushFBOTextureRenderer(this);
+
+ for (int i = 0; i < texs.size(); i++) {
+ final Texture tex = texs.get(i);
+
+ setupForSingleTexDraw(tex);
+
+ if (_samples > 0 && _supportsMultisample) {
+ setMSFBO();
+ }
+
+ switchCameraIn(clear);
+ if (toDrawA != null) {
+ doDraw(toDrawA);
+ } else {
+ doDraw(toDrawB);
+ }
+ switchCameraOut();
+
+ if (_samples > 0 && _supportsMultisample) {
+ blitMSFBO();
+ }
+
+ takedownForSingleTexDraw(tex);
+ }
+ } finally {
+ ContextManager.getCurrentContext().popFBOTextureRenderer();
+ }
+ return;
+ }
+ try {
+ ContextManager.getCurrentContext().pushFBOTextureRenderer(this);
+
+ // Otherwise, we can streamline this by rendering to multiple textures at once.
+ // first determine how many groups we need
+ final LinkedList<Texture> depths = new LinkedList<Texture>();
+ final LinkedList<Texture> colors = new LinkedList<Texture>();
+ for (int i = 0; i < texs.size(); i++) {
+ final Texture tex = texs.get(i);
+ if (tex.getTextureStoreFormat().isDepthFormat()) {
+ depths.add(tex);
+ } else {
+ colors.add(tex);
+ }
+ }
+ // we can only render to 1 depth texture at a time, so # groups is at minimum == numDepth
+ final int groups = Math.max(depths.size(), (int) Math.ceil(colors.size() / (float) maxDrawBuffers));
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ for (int i = 0; i < groups; i++) {
+ // First handle colors
+ int colorsAdded = 0;
+ while (colorsAdded < maxDrawBuffers && !colors.isEmpty()) {
+ final Texture tex = colors.removeFirst();
+ if (tex.getType() == Type.TwoDimensional) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0 + colorsAdded,
+ GL.GL_TEXTURE_2D, tex.getTextureIdForContext(context.getGlContextRep()), 0);
+ } else if (tex.getType() == Type.CubeMap) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0 + colorsAdded,
+ JoglTextureStateUtil.getGLCubeMapFace(((TextureCubeMap) tex).getCurrentRTTFace()),
+ tex.getTextureIdForContext(context.getGlContextRep()), 0);
+ } else {
+ throw new IllegalArgumentException("Invalid texture type: " + tex.getType());
+ }
+ colorsAdded++;
+ }
+
+ // Now take care of depth.
+ if (!depths.isEmpty()) {
+ final Texture tex = depths.removeFirst();
+ // Set up our depth texture
+ if (tex.getType() == Type.TwoDimensional) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
+ GL.GL_TEXTURE_2D, tex.getTextureIdForContext(context.getGlContextRep()), 0);
+ } else if (tex.getType() == Type.CubeMap) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
+ JoglTextureStateUtil.getGLCubeMapFace(((TextureCubeMap) tex).getCurrentRTTFace()),
+ tex.getTextureIdForContext(context.getGlContextRep()), 0);
+ } else {
+ throw new IllegalArgumentException("Invalid texture type: " + tex.getType());
+ }
+ _usingDepthRB = false;
+ } else if (!_usingDepthRB) {
+ // setup our default depth render buffer if not already set
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
+ GL.GL_RENDERBUFFER, _depthRBID);
+ _usingDepthRB = true;
+ }
+
+ setDrawBuffers(colorsAdded);
+ setReadBuffer(colorsAdded != 0 ? GL.GL_COLOR_ATTACHMENT0 : GL.GL_NONE);
+
+ // Check FBO complete
+ checkFBOComplete(_fboID);
+
+ switchCameraIn(clear);
+
+ if (toDrawA != null) {
+ doDraw(toDrawA);
+ } else {
+ doDraw(toDrawB);
+ }
+
+ switchCameraOut();
+ }
+
+ // automatically generate mipmaps for our textures.
+ for (int x = 0, max = texs.size(); x < max; x++) {
+ final Texture tex = texs.get(x);
+ if (tex.getMinificationFilter().usesMipMapLevels()) {
+ JoglTextureStateUtil.doTextureBind(tex, 0, true);
+ gl.glGenerateMipmap(JoglTextureStateUtil.getGLType(tex.getType()));
+ }
+ }
+ } finally {
+ ContextManager.getCurrentContext().popFBOTextureRenderer();
+ }
+ }
+
+ @Override
+ protected void setupForSingleTexDraw(final Texture tex) {
+ final GL gl = GLU.getCurrentGL();
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final int textureId = tex.getTextureIdForContext(context.getGlContextRep());
+
+ if (tex.getTextureStoreFormat().isDepthFormat()) {
+ // No color buffer
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_RENDERBUFFER,
+ 0);
+
+ // Setup depth texture into FBO
+ if (tex.getType() == Type.TwoDimensional) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_TEXTURE_2D,
+ textureId, 0);
+ } else if (tex.getType() == Type.CubeMap) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
+ JoglTextureStateUtil.getGLCubeMapFace(((TextureCubeMap) tex).getCurrentRTTFace()), textureId, 0);
+ } else {
+ throw new IllegalArgumentException("Can not render to texture of type: " + tex.getType());
+ }
+
+ setDrawBuffer(GL.GL_NONE);
+ setReadBuffer(GL.GL_NONE);
+ } else {
+ // Set color texture into FBO
+ if (tex.getType() == Type.TwoDimensional) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D,
+ textureId, 0);
+ } else if (tex.getType() == Type.CubeMap) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0,
+ JoglTextureStateUtil.getGLCubeMapFace(((TextureCubeMap) tex).getCurrentRTTFace()), textureId, 0);
+ } else {
+ throw new IllegalArgumentException("Can not render to texture of type: " + tex.getType());
+ }
+
+ // setup depth RB
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER,
+ _depthRBID);
+
+ setDrawBuffer(GL.GL_COLOR_ATTACHMENT0);
+ setReadBuffer(GL.GL_COLOR_ATTACHMENT0);
+ }
+
+ // Check FBO complete
+ checkFBOComplete(_fboID);
+ }
+
+ private void setReadBuffer(final int attachVal) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glReadBuffer(attachVal);
+ }
+
+ private void setDrawBuffer(final int attachVal) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glDrawBuffer(attachVal);
+ }
+
+ private void setDrawBuffers(final int maxEntry) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (maxEntry <= 1) {
+ setDrawBuffer(maxEntry != 0 ? GL.GL_COLOR_ATTACHMENT0 : GL.GL_NONE);
+ } else {
+ // We should only get to this point if we support ARBDrawBuffers.
+ _attachBuffer.clear();
+ _attachBuffer.limit(maxEntry);
+ gl.getGL2GL3().glDrawBuffers(_attachBuffer.limit(), _attachBuffer); // TODO Check <size>
+ }
+ }
+
+ @Override
+ protected void takedownForSingleTexDraw(final Texture tex) {
+ final GL gl = GLU.getCurrentGL();
+
+ // automatically generate mipmaps for our texture.
+ if (tex.getMinificationFilter().usesMipMapLevels()) {
+ JoglTextureStateUtil.doTextureBind(tex, 0, true);
+ gl.glGenerateMipmap(JoglTextureStateUtil.getGLType(tex.getType()));
+ }
+ }
+
+ @Override
+ protected void setMSFBO() {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, _msfboID);
+ }
+
+ @Override
+ protected void blitMSFBO() {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, _msfboID);
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, _fboID);
+ gl.getGL2GL3().glBlitFramebuffer(0, 0, _width, _height, 0, 0, _width, _height, GL.GL_COLOR_BUFFER_BIT
+ | GL.GL_DEPTH_BUFFER_BIT, GL.GL_NEAREST);
+
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
+ }
+
+ /**
+ * Check the currently bound FBO status for completeness. The passed in fboID is for informational purposes only.
+ *
+ * @param fboID
+ * an id to use for log messages, particularly if there are any issues.
+ */
+ public static void checkFBOComplete(final int fboID) {
+ final GL gl = GLU.getCurrentGL();
+
+ final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ switch (status) {
+ case GL.GL_FRAMEBUFFER_COMPLETE:
+ break;
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ throw new IllegalStateException("FrameBuffer: " + fboID
+ + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT exception");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ throw new IllegalStateException("FrameBuffer: " + fboID
+ + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT exception");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ throw new IllegalStateException("FrameBuffer: " + fboID
+ + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT exception");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ throw new IllegalStateException("FrameBuffer: " + fboID
+ + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT exception");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
+ throw new IllegalStateException("FrameBuffer: " + fboID
+ + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT exception");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ throw new IllegalStateException("FrameBuffer: " + fboID
+ + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT exception");
+ case GL.GL_FRAMEBUFFER_UNSUPPORTED:
+ throw new IllegalStateException("FrameBuffer: " + fboID
+ + ", has caused a GL_FRAMEBUFFER_UNSUPPORTED_EXT exception");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ throw new IllegalStateException("FrameBuffer: " + fboID
+ + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT exception.");
+ default:
+ throw new RuntimeException("Unexpected reply from glCheckFramebufferStatusEXT: " + status);
+ }
+ }
+
+ public void copyToTexture(final Texture tex, final int x, final int y, final int width, final int height,
+ final int xoffset, final int yoffset) {
+ final GL gl = GLU.getCurrentGL();
+
+ JoglTextureStateUtil.doTextureBind(tex, 0, true);
+
+ if (tex.getType() == Type.TwoDimensional) {
+ gl.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, xoffset, yoffset, x, y, width, height);
+ } else if (tex.getType() == Type.CubeMap) {
+ gl.glCopyTexSubImage2D(JoglTextureStateUtil.getGLCubeMapFace(((TextureCubeMap) tex).getCurrentRTTFace()),
+ 0, xoffset, yoffset, x, y, width, height);
+ } else {
+ throw new IllegalArgumentException("Invalid texture type: " + tex.getType());
+ }
+ }
+
+ @Override
+ protected void clearBuffers(final int clear) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.glDisable(GL.GL_SCISSOR_TEST);
+ _parentRenderer.clearBuffers(clear);
+ }
+
+ @Override
+ protected void activate() {
+ final GL gl = GLU.getCurrentGL();
+
+ // Lazy init
+ if (_fboID == 0) {
+ final IntBuffer buffer = BufferUtils.createIntBuffer(1);
+
+ // Create our texture binding FBO
+ gl.glGenFramebuffers(1, buffer); // generate id
+ _fboID = buffer.get(0);
+
+ // Create a depth renderbuffer to use for RTT use
+ gl.glGenRenderbuffers(1, buffer); // generate id
+ _depthRBID = buffer.get(0);
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, _depthRBID);
+ int format = GL2ES2.GL_DEPTH_COMPONENT;
+ if (_supportsDepthTexture && _depthBits > 0) {
+ switch (_depthBits) {
+ case 16:
+ format = GL.GL_DEPTH_COMPONENT16;
+ break;
+ case 24:
+ format = GL.GL_DEPTH_COMPONENT24;
+ break;
+ case 32:
+ format = GL.GL_DEPTH_COMPONENT32;
+ break;
+ default:
+ // stick with the "undefined" GL_DEPTH_COMPONENT
+ }
+ }
+ gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, _width, _height);
+
+ // unbind...
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0);
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
+
+ // If we support it, rustle up a multisample framebuffer + renderbuffers
+ if (_samples != 0 && _supportsMultisample) {
+ // create ms framebuffer object
+ gl.glGenFramebuffers(1, buffer);
+ _msfboID = buffer.get(0);
+
+ // create ms renderbuffers
+ gl.glGenRenderbuffers(1, buffer); // generate id
+ _mscolorRBID = buffer.get(0);
+ gl.glGenRenderbuffers(1, buffer); // generate id
+ _msdepthRBID = buffer.get(0);
+
+ // set up renderbuffer properties
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, _mscolorRBID);
+ gl.getGL2GL3().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, _samples, GL.GL_RGBA, _width, _height);
+
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, _msdepthRBID);
+ gl.getGL2GL3().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, _samples, format, _width, _height);
+
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0);
+
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, _msfboID);
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0,
+ GL.GL_RENDERBUFFER, _mscolorRBID);
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
+ GL.GL_RENDERBUFFER, _msdepthRBID);
+
+ // check for errors
+ checkFBOComplete(_msfboID);
+
+ // release
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
+ }
+
+ }
+
+ if (_active == 0) {
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final RendererRecord record = context.getRendererRecord();
+
+ // needed as FBOs do not share this flag it seems
+ record.setClippingTestValid(false);
+
+ // push a delimiter onto the clip stack
+ _neededClip = _parentRenderer.isClipTestEnabled();
+ if (_neededClip) {
+ _parentRenderer.pushEmptyClip();
+ }
+
+ gl.glClearColor(_backgroundColor.getRed(), _backgroundColor.getGreen(), _backgroundColor.getBlue(),
+ _backgroundColor.getAlpha());
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, _fboID);
+ ContextManager.getCurrentContext().pushEnforcedStates();
+ ContextManager.getCurrentContext().clearEnforcedStates();
+ ContextManager.getCurrentContext().enforceStates(_enforcedStates);
+ }
+ _active++;
+ }
+
+ @Override
+ protected void deactivate() {
+ final GL gl = GLU.getCurrentGL();
+
+ if (_active == 1) {
+ final ReadOnlyColorRGBA bgColor = _parentRenderer.getBackgroundColor();
+ gl.glClearColor(bgColor.getRed(), bgColor.getGreen(), bgColor.getBlue(), bgColor.getAlpha());
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
+ ContextManager.getCurrentContext().popEnforcedStates();
+
+ if (_neededClip) {
+ _parentRenderer.popClip();
+ }
+ }
+ _active--;
+ }
+
+ public void cleanup() {
+ final GL gl = GLU.getCurrentGL();
+
+ if (_fboID != 0) {
+ final IntBuffer id = BufferUtils.createIntBuffer(1);
+ id.put(_fboID);
+ id.rewind();
+ gl.glDeleteFramebuffers(id.limit(), id);
+ }
+
+ if (_depthRBID != 0) {
+ final IntBuffer id = BufferUtils.createIntBuffer(1);
+ id.put(_depthRBID);
+ id.rewind();
+ gl.glDeleteRenderbuffers(id.limit(), id);
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRendererProvider.java b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRendererProvider.java
new file mode 100644
index 0000000..b2d433c
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRendererProvider.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.renderer.jogl;
+
+import java.util.logging.Logger;
+
+import com.ardor3d.framework.DisplaySettings;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.TextureRenderer;
+import com.ardor3d.renderer.TextureRendererProvider;
+
+public class JoglTextureRendererProvider implements TextureRendererProvider {
+
+ private static final Logger logger = Logger.getLogger(JoglTextureRendererProvider.class.getName());
+
+ public TextureRenderer createTextureRenderer(final int width, final int height, final Renderer renderer,
+ final ContextCapabilities caps) {
+ return createTextureRenderer(width, height, 0, 0, renderer, caps);
+ }
+
+ public TextureRenderer createTextureRenderer(final int width, final int height, final int depthBits,
+ final int samples, final Renderer renderer, final ContextCapabilities caps) {
+ return createTextureRenderer(new DisplaySettings(width, height, depthBits, samples), false, renderer, caps);
+ }
+
+ public TextureRenderer createTextureRenderer(final DisplaySettings settings, final boolean forcePbuffer,
+ final Renderer renderer, final ContextCapabilities caps) {
+ if (!forcePbuffer && caps.isFBOSupported()) {
+ return new JoglTextureRenderer(settings.getWidth(), settings.getHeight(), settings.getDepthBits(), settings
+ .getSamples(), renderer, caps);
+ } else if (caps.isPbufferSupported()) {
+ return new JoglPbufferTextureRenderer(settings, renderer, caps);
+ } else {
+ logger.severe("No texture renderer support (FBO or Pbuffer).");
+ return null;
+ }
+
+ }
+
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglBlendStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglBlendStateUtil.java
new file mode 100644
index 0000000..39f0221
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglBlendStateUtil.java
@@ -0,0 +1,424 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.BlendState;
+import com.ardor3d.renderer.state.BlendState.BlendEquation;
+import com.ardor3d.renderer.state.BlendState.DestinationFunction;
+import com.ardor3d.renderer.state.BlendState.SourceFunction;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.BlendStateRecord;
+
+public abstract class JoglBlendStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final BlendState state) {
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final BlendStateRecord record = (BlendStateRecord) context.getStateRecord(StateType.Blend);
+ final ContextCapabilities caps = context.getCapabilities();
+ context.setCurrentState(StateType.Blend, state);
+
+ final GL gl = GLU.getCurrentGL();
+
+ if (state.isEnabled()) {
+ applyBlendEquations(gl, state.isBlendEnabled(), state, record, caps);
+ applyBlendColor(gl, state.isBlendEnabled(), state, record, caps);
+ applyBlendFunctions(gl, state.isBlendEnabled(), state, record, caps);
+
+ applyTest(gl, state.isTestEnabled(), state, record);
+
+ if (caps.isMultisampleSupported()) {
+ applyAlphaCoverage(gl, state.isSampleAlphaToCoverageEnabled(), state.isSampleAlphaToOneEnabled(),
+ record, caps);
+ applySampleCoverage(gl, state.isSampleCoverageEnabled(), state, record, caps);
+ }
+ } else {
+ // disable blend
+ applyBlendEquations(gl, false, state, record, caps);
+
+ // disable alpha test
+ applyTest(gl, false, state, record);
+
+ // disable sample coverage
+ if (caps.isMultisampleSupported()) {
+ applyAlphaCoverage(gl, false, false, record, caps);
+ applySampleCoverage(gl, false, state, record, caps);
+ }
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void applyBlendEquations(final GL gl, final boolean enabled, final BlendState state,
+ final BlendStateRecord record, final ContextCapabilities caps) {
+ if (record.isValid()) {
+ if (enabled) {
+ if (!record.blendEnabled) {
+ gl.glEnable(GL.GL_BLEND);
+ record.blendEnabled = true;
+ }
+ final int blendEqRGB = getGLEquationValue(state.getBlendEquationRGB(), caps);
+ if (caps.isSeparateBlendEquationsSupported()) {
+ final int blendEqAlpha = getGLEquationValue(state.getBlendEquationAlpha(), caps);
+ if (record.blendEqRGB != blendEqRGB || record.blendEqAlpha != blendEqAlpha) {
+ gl.glBlendEquationSeparate(blendEqRGB, blendEqAlpha);
+ record.blendEqRGB = blendEqRGB;
+ record.blendEqAlpha = blendEqAlpha;
+ }
+ } else if (caps.isBlendEquationSupported()) {
+ if (record.blendEqRGB != blendEqRGB) {
+ gl.glBlendEquation(blendEqRGB);
+ record.blendEqRGB = blendEqRGB;
+ }
+ }
+ } else if (record.blendEnabled) {
+ gl.glDisable(GL.GL_BLEND);
+ record.blendEnabled = false;
+ }
+
+ } else {
+ if (enabled) {
+ gl.glEnable(GL.GL_BLEND);
+ record.blendEnabled = true;
+ final int blendEqRGB = getGLEquationValue(state.getBlendEquationRGB(), caps);
+ if (caps.isSeparateBlendEquationsSupported()) {
+ final int blendEqAlpha = getGLEquationValue(state.getBlendEquationAlpha(), caps);
+ gl.glBlendEquationSeparate(blendEqRGB, blendEqAlpha);
+ record.blendEqRGB = blendEqRGB;
+ record.blendEqAlpha = blendEqAlpha;
+ } else if (caps.isBlendEquationSupported()) {
+ gl.glBlendEquation(blendEqRGB);
+ record.blendEqRGB = blendEqRGB;
+ }
+ } else {
+ gl.glDisable(GL.GL_BLEND);
+ record.blendEnabled = false;
+ }
+ }
+ }
+
+ private static void applyBlendColor(final GL gl, final boolean enabled, final BlendState state,
+ final BlendStateRecord record, final ContextCapabilities caps) {
+ if (enabled) {
+ final boolean applyConstant = state.getDestinationFunctionRGB().usesConstantColor()
+ || state.getSourceFunctionRGB().usesConstantColor()
+ || (caps.isConstantBlendColorSupported() && (state.getDestinationFunctionAlpha()
+ .usesConstantColor() || state.getSourceFunctionAlpha().usesConstantColor()));
+ if (applyConstant && caps.isConstantBlendColorSupported()) {
+ final ReadOnlyColorRGBA constant = state.getConstantColor();
+ if (!record.isValid() || (caps.isConstantBlendColorSupported() && !record.blendColor.equals(constant))) {
+ gl.getGL2GL3().glBlendColor(constant.getRed(), constant.getGreen(), constant.getBlue(), constant.getAlpha());
+ record.blendColor.set(constant);
+ }
+ }
+ }
+ }
+
+ private static void applyBlendFunctions(final GL gl, final boolean enabled, final BlendState state,
+ final BlendStateRecord record, final ContextCapabilities caps) {
+ if (record.isValid()) {
+ if (enabled) {
+ final int glSrcRGB = getGLSrcValue(state.getSourceFunctionRGB(), caps);
+ final int glDstRGB = getGLDstValue(state.getDestinationFunctionRGB(), caps);
+ if (caps.isSeparateBlendFunctionsSupported()) {
+ final int glSrcAlpha = getGLSrcValue(state.getSourceFunctionAlpha(), caps);
+ final int glDstAlpha = getGLDstValue(state.getDestinationFunctionAlpha(), caps);
+ if (record.srcFactorRGB != glSrcRGB || record.dstFactorRGB != glDstRGB
+ || record.srcFactorAlpha != glSrcAlpha || record.dstFactorAlpha != glDstAlpha) {
+ gl.glBlendFuncSeparate(glSrcRGB, glDstRGB, glSrcAlpha, glDstAlpha);
+ record.srcFactorRGB = glSrcRGB;
+ record.dstFactorRGB = glDstRGB;
+ record.srcFactorAlpha = glSrcAlpha;
+ record.dstFactorAlpha = glDstAlpha;
+ }
+ } else if (record.srcFactorRGB != glSrcRGB || record.dstFactorRGB != glDstRGB) {
+ gl.glBlendFunc(glSrcRGB, glDstRGB);
+ record.srcFactorRGB = glSrcRGB;
+ record.dstFactorRGB = glDstRGB;
+ }
+ }
+ } else {
+ if (enabled) {
+ final int glSrcRGB = getGLSrcValue(state.getSourceFunctionRGB(), caps);
+ final int glDstRGB = getGLDstValue(state.getDestinationFunctionRGB(), caps);
+ if (caps.isSeparateBlendFunctionsSupported()) {
+ final int glSrcAlpha = getGLSrcValue(state.getSourceFunctionAlpha(), caps);
+ final int glDstAlpha = getGLDstValue(state.getDestinationFunctionAlpha(), caps);
+ gl.glBlendFuncSeparate(glSrcRGB, glDstRGB, glSrcAlpha, glDstAlpha);
+ record.srcFactorRGB = glSrcRGB;
+ record.dstFactorRGB = glDstRGB;
+ record.srcFactorAlpha = glSrcAlpha;
+ record.dstFactorAlpha = glDstAlpha;
+ } else {
+ gl.glBlendFunc(glSrcRGB, glDstRGB);
+ record.srcFactorRGB = glSrcRGB;
+ record.dstFactorRGB = glDstRGB;
+ }
+ }
+ }
+ }
+
+ protected static void applyAlphaCoverage(final GL gl, final boolean sampleAlphaToCoverageEnabled,
+ final boolean sampleAlphaToOneEnabled, final BlendStateRecord record, final ContextCapabilities caps) {
+ if (record.isValid()) {
+ if (sampleAlphaToCoverageEnabled != record.sampleAlphaToCoverageEnabled) {
+ if (sampleAlphaToCoverageEnabled) {
+ gl.glEnable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE);
+ } else {
+ gl.glDisable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE);
+ }
+ record.sampleAlphaToCoverageEnabled = sampleAlphaToCoverageEnabled;
+ }
+ if (sampleAlphaToOneEnabled != record.sampleAlphaToOneEnabled) {
+ if (sampleAlphaToOneEnabled) {
+ gl.glEnable(GL.GL_SAMPLE_ALPHA_TO_ONE);
+ } else {
+ gl.glDisable(GL.GL_SAMPLE_ALPHA_TO_ONE);
+ }
+ record.sampleAlphaToOneEnabled = sampleAlphaToOneEnabled;
+ }
+ } else {
+ if (sampleAlphaToCoverageEnabled) {
+ gl.glEnable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE);
+ } else {
+ gl.glDisable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE);
+ }
+ record.sampleAlphaToCoverageEnabled = sampleAlphaToCoverageEnabled;
+ if (sampleAlphaToOneEnabled) {
+ gl.glEnable(GL.GL_SAMPLE_ALPHA_TO_ONE);
+ } else {
+ gl.glDisable(GL.GL_SAMPLE_ALPHA_TO_ONE);
+ }
+ record.sampleAlphaToOneEnabled = sampleAlphaToOneEnabled;
+ }
+ }
+
+ protected static void applySampleCoverage(final GL gl, final boolean enabled, final BlendState state,
+ final BlendStateRecord record, final ContextCapabilities caps) {
+
+ final boolean coverageInverted = state.isSampleCoverageInverted();
+ final float coverageValue = state.getSampleCoverage();
+
+ if (record.isValid()) {
+ if (enabled) {
+ if (!record.sampleCoverageEnabled) {
+ gl.glEnable(GL.GL_SAMPLE_COVERAGE);
+ record.sampleCoverageEnabled = true;
+ }
+ if (record.sampleCoverageInverted != coverageInverted || record.sampleCoverage != coverageValue) {
+ gl.glSampleCoverage(coverageValue, coverageInverted);
+ record.sampleCoverageInverted = coverageInverted;
+ record.sampleCoverage = coverageValue;
+ }
+ } else {
+ if (record.sampleCoverageEnabled) {
+ gl.glDisable(GL.GL_SAMPLE_COVERAGE);
+ record.sampleCoverageEnabled = false;
+ }
+ }
+ } else {
+ if (enabled) {
+ gl.glEnable(GL.GL_SAMPLE_COVERAGE);
+ record.sampleCoverageEnabled = true;
+ gl.glSampleCoverage(coverageValue, coverageInverted);
+ record.sampleCoverageInverted = coverageInverted;
+ record.sampleCoverage = coverageValue;
+ } else {
+ gl.glDisable(GL.GL_SAMPLE_COVERAGE);
+ record.sampleCoverageEnabled = false;
+ }
+ }
+ }
+
+ private static int getGLSrcValue(final SourceFunction function, final ContextCapabilities caps) {
+ switch (function) {
+ case Zero:
+ return GL.GL_ZERO;
+ case DestinationColor:
+ return GL.GL_DST_COLOR;
+ case OneMinusDestinationColor:
+ return GL.GL_ONE_MINUS_DST_COLOR;
+ case SourceAlpha:
+ return GL.GL_SRC_ALPHA;
+ case OneMinusSourceAlpha:
+ return GL.GL_ONE_MINUS_SRC_ALPHA;
+ case DestinationAlpha:
+ return GL.GL_DST_ALPHA;
+ case OneMinusDestinationAlpha:
+ return GL.GL_ONE_MINUS_DST_ALPHA;
+ case SourceAlphaSaturate:
+ return GL.GL_SRC_ALPHA_SATURATE;
+ case ConstantColor:
+ if (caps.isConstantBlendColorSupported()) {
+ return GL2ES2.GL_CONSTANT_COLOR;
+ }
+ // FALLS THROUGH
+ case OneMinusConstantColor:
+ if (caps.isConstantBlendColorSupported()) {
+ return GL2ES2.GL_ONE_MINUS_CONSTANT_COLOR;
+ }
+ // FALLS THROUGH
+ case ConstantAlpha:
+ if (caps.isConstantBlendColorSupported()) {
+ return GL2ES2.GL_CONSTANT_ALPHA;
+ }
+ // FALLS THROUGH
+ case OneMinusConstantAlpha:
+ if (caps.isConstantBlendColorSupported()) {
+ return GL2ES2.GL_ONE_MINUS_CONSTANT_ALPHA;
+ }
+ // FALLS THROUGH
+ case One:
+ return GL.GL_ONE;
+ }
+ throw new IllegalArgumentException("Invalid source function type: " + function);
+ }
+
+ private static int getGLDstValue(final DestinationFunction function, final ContextCapabilities caps) {
+ switch (function) {
+ case Zero:
+ return GL.GL_ZERO;
+ case SourceColor:
+ return GL.GL_SRC_COLOR;
+ case OneMinusSourceColor:
+ return GL.GL_ONE_MINUS_SRC_COLOR;
+ case SourceAlpha:
+ return GL.GL_SRC_ALPHA;
+ case OneMinusSourceAlpha:
+ return GL.GL_ONE_MINUS_SRC_ALPHA;
+ case DestinationAlpha:
+ return GL.GL_DST_ALPHA;
+ case OneMinusDestinationAlpha:
+ return GL.GL_ONE_MINUS_DST_ALPHA;
+ case ConstantColor:
+ if (caps.isConstantBlendColorSupported()) {
+ return GL2ES2.GL_CONSTANT_COLOR;
+ }
+ // FALLS THROUGH
+ case OneMinusConstantColor:
+ if (caps.isConstantBlendColorSupported()) {
+ return GL2ES2.GL_ONE_MINUS_CONSTANT_COLOR;
+ }
+ // FALLS THROUGH
+ case ConstantAlpha:
+ if (caps.isConstantBlendColorSupported()) {
+ return GL2ES2.GL_CONSTANT_ALPHA;
+ }
+ // FALLS THROUGH
+ case OneMinusConstantAlpha:
+ if (caps.isConstantBlendColorSupported()) {
+ return GL2ES2.GL_ONE_MINUS_CONSTANT_ALPHA;
+ }
+ // FALLS THROUGH
+ case One:
+ return GL.GL_ONE;
+ }
+ throw new IllegalArgumentException("Invalid destination function type: " + function);
+ }
+
+ private static int getGLEquationValue(final BlendEquation eq, final ContextCapabilities caps) {
+ switch (eq) {
+ case Min:
+ if (caps.isMinMaxBlendEquationsSupported()) {
+ return GL2GL3.GL_MIN;
+ }
+ // FALLS THROUGH
+ case Max:
+ if (caps.isMinMaxBlendEquationsSupported()) {
+ return GL2GL3.GL_MAX;
+ } else {
+ return GL.GL_FUNC_ADD;
+ }
+ case Subtract:
+ if (caps.isSubtractBlendEquationsSupported()) {
+ return GL.GL_FUNC_SUBTRACT;
+ }
+ // FALLS THROUGH
+ case ReverseSubtract:
+ if (caps.isSubtractBlendEquationsSupported()) {
+ return GL.GL_FUNC_REVERSE_SUBTRACT;
+ }
+ // FALLS THROUGH
+ case Add:
+ return GL.GL_FUNC_ADD;
+ }
+ throw new IllegalArgumentException("Invalid blend equation: " + eq);
+ }
+
+ private static void applyTest(final GL gl, final boolean enabled, final BlendState state,
+ final BlendStateRecord record) {
+ if (record.isValid()) {
+ if (enabled) {
+ if (!record.testEnabled) {
+ gl.glEnable(GL2ES1.GL_ALPHA_TEST);
+ record.testEnabled = true;
+ }
+ final int glFunc = getGLFuncValue(state.getTestFunction());
+ if (record.alphaFunc != glFunc || record.alphaRef != state.getReference()) {
+ gl.getGL2().glAlphaFunc(glFunc, state.getReference());
+ record.alphaFunc = glFunc;
+ record.alphaRef = state.getReference();
+ }
+ } else if (record.testEnabled) {
+ gl.glDisable(GL2ES1.GL_ALPHA_TEST);
+ record.testEnabled = false;
+ }
+
+ } else {
+ if (enabled) {
+ gl.glEnable(GL2ES1.GL_ALPHA_TEST);
+ record.testEnabled = true;
+ final int glFunc = getGLFuncValue(state.getTestFunction());
+ gl.getGL2().glAlphaFunc(glFunc, state.getReference());
+ record.alphaFunc = glFunc;
+ record.alphaRef = state.getReference();
+ } else {
+ gl.glDisable(GL2ES1.GL_ALPHA_TEST);
+ record.testEnabled = false;
+ }
+ }
+ }
+
+ private static int getGLFuncValue(final BlendState.TestFunction function) {
+ switch (function) {
+ case Never:
+ return GL.GL_NEVER;
+ case LessThan:
+ return GL.GL_LESS;
+ case EqualTo:
+ return GL.GL_EQUAL;
+ case LessThanOrEqualTo:
+ return GL.GL_LEQUAL;
+ case GreaterThan:
+ return GL.GL_GREATER;
+ case NotEqualTo:
+ return GL.GL_NOTEQUAL;
+ case GreaterThanOrEqualTo:
+ return GL.GL_GEQUAL;
+ case Always:
+ return GL.GL_ALWAYS;
+ }
+ throw new IllegalArgumentException("Invalid test function type: " + function);
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglClipStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglClipStateUtil.java
new file mode 100644
index 0000000..df673aa
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglClipStateUtil.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.ClipState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.ClipStateRecord;
+
+public abstract class JoglClipStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final ClipState state) {
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ClipStateRecord record = (ClipStateRecord) context.getStateRecord(StateType.Clip);
+ context.setCurrentState(StateType.Clip, state);
+
+ final ContextCapabilities caps = context.getCapabilities();
+ final int max = Math.min(ClipState.MAX_CLIP_PLANES, caps.getMaxUserClipPlanes());
+
+ if (state.isEnabled()) {
+ for (int i = 0; i < max; i++) {
+ enableClipPlane(i, state.getPlaneEnabled(i), state, record);
+ }
+ } else {
+ for (int i = 0; i < max; i++) {
+ enableClipPlane(i, false, state, record);
+ }
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void enableClipPlane(final int planeIndex, final boolean enable, final ClipState state,
+ final ClipStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (enable) {
+ if (!record.isValid() || !record.planeEnabled[planeIndex]) {
+ gl.glEnable(GL2ES1.GL_CLIP_PLANE0 + planeIndex);
+ record.planeEnabled[planeIndex] = true;
+ }
+
+ record.buf.rewind();
+ record.buf.put(state.getPlaneEquations(planeIndex));
+ record.buf.flip();
+ gl.getGL2().glClipPlane(GL2ES1.GL_CLIP_PLANE0 + planeIndex, record.buf);
+
+ } else {
+ if (!record.isValid() || record.planeEnabled[planeIndex]) {
+ gl.glDisable(GL2ES1.GL_CLIP_PLANE0 + planeIndex);
+ record.planeEnabled[planeIndex] = false;
+ }
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglColorMaskStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglColorMaskStateUtil.java
new file mode 100644
index 0000000..a0316e0
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglColorMaskStateUtil.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.ColorMaskState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.ColorMaskStateRecord;
+
+public abstract class JoglColorMaskStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final ColorMaskState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ColorMaskStateRecord record = (ColorMaskStateRecord) context.getStateRecord(StateType.ColorMask);
+ context.setCurrentState(StateType.ColorMask, state);
+
+ if (state.isEnabled()) {
+ if (!record.isValid() || !record.is(state.getRed(), state.getGreen(), state.getBlue(), state.getAlpha())) {
+ gl.glColorMask(state.getRed(), state.getGreen(), state.getBlue(), state.getAlpha());
+ record.set(state.getRed(), state.getGreen(), state.getBlue(), state.getAlpha());
+ }
+ } else if (!record.isValid() || !record.is(true, true, true, true)) {
+ gl.glColorMask(true, true, true, true);
+ record.set(true, true, true, true);
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglCullStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglCullStateUtil.java
new file mode 100644
index 0000000..d93eb33
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglCullStateUtil.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.CullState;
+import com.ardor3d.renderer.state.CullState.Face;
+import com.ardor3d.renderer.state.CullState.PolygonWind;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.CullStateRecord;
+
+public abstract class JoglCullStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final CullState state) {
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final CullStateRecord record = (CullStateRecord) context.getStateRecord(StateType.Cull);
+ context.setCurrentState(StateType.Cull, state);
+
+ if (state.isEnabled()) {
+ final Face useCullMode = state.getCullFace();
+
+ switch (useCullMode) {
+ case Front:
+ setCull(GL.GL_FRONT, state, record);
+ setCullEnabled(true, state, record);
+ break;
+ case Back:
+ setCull(GL.GL_BACK, state, record);
+ setCullEnabled(true, state, record);
+ break;
+ case FrontAndBack:
+ setCull(GL.GL_FRONT_AND_BACK, state, record);
+ setCullEnabled(true, state, record);
+ break;
+ case None:
+ setCullEnabled(false, state, record);
+ break;
+ }
+ setGLPolygonWind(state.getPolygonWind(), state, record);
+ } else {
+ setCullEnabled(false, state, record);
+ setGLPolygonWind(PolygonWind.CounterClockWise, state, record);
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void setCullEnabled(final boolean enable, final CullState state, final CullStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || record.enabled != enable) {
+ if (enable) {
+ gl.glEnable(GL.GL_CULL_FACE);
+ } else {
+ gl.glDisable(GL.GL_CULL_FACE);
+ }
+ record.enabled = enable;
+ }
+ }
+
+ private static void setCull(final int face, final CullState state, final CullStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || record.face != face) {
+ gl.glCullFace(face);
+ record.face = face;
+ }
+ }
+
+ private static void setGLPolygonWind(final PolygonWind windOrder, final CullState state,
+ final CullStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || record.windOrder != windOrder) {
+ switch (windOrder) {
+ case CounterClockWise:
+ gl.glFrontFace(GL.GL_CCW);
+ break;
+ case ClockWise:
+ gl.glFrontFace(GL.GL_CW);
+ break;
+ }
+ record.windOrder = windOrder;
+ }
+ }
+
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFogStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFogStateUtil.java
new file mode 100644
index 0000000..19b1b0f
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFogStateUtil.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.FogState;
+import com.ardor3d.renderer.state.FogState.CoordinateSource;
+import com.ardor3d.renderer.state.FogState.DensityFunction;
+import com.ardor3d.renderer.state.FogState.Quality;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.FogStateRecord;
+
+public abstract class JoglFogStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final FogState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+ final FogStateRecord record = (FogStateRecord) context.getStateRecord(StateType.Fog);
+ context.setCurrentState(StateType.Fog, state);
+
+ if (state.isEnabled()) {
+ enableFog(true, record);
+
+ if (record.isValid()) {
+ if (record.fogStart != state.getStart()) {
+ gl.getGL2ES1().glFogf(GL2ES1.GL_FOG_START, state.getStart());
+ record.fogStart = state.getStart();
+ }
+ if (record.fogEnd != state.getEnd()) {
+ gl.getGL2ES1().glFogf(GL2ES1.GL_FOG_END, state.getEnd());
+ record.fogEnd = state.getEnd();
+ }
+ if (record.density != state.getDensity()) {
+ gl.getGL2ES1().glFogf(GL2ES1.GL_FOG_DENSITY, state.getDensity());
+ record.density = state.getDensity();
+ }
+ } else {
+ gl.getGL2ES1().glFogf(GL2ES1.GL_FOG_START, state.getStart());
+ record.fogStart = state.getStart();
+ gl.getGL2ES1().glFogf(GL2ES1.GL_FOG_END, state.getEnd());
+ record.fogEnd = state.getEnd();
+ gl.getGL2ES1().glFogf(GL2ES1.GL_FOG_DENSITY, state.getDensity());
+ record.density = state.getDensity();
+ }
+
+ final ReadOnlyColorRGBA fogColor = state.getColor();
+ applyFogColor(fogColor, record);
+ applyFogMode(state.getDensityFunction(), record);
+ applyFogHint(state.getQuality(), record);
+ applyFogSource(state.getSource(), record, caps);
+ } else {
+ enableFog(false, record);
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void enableFog(final boolean enable, final FogStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (record.isValid()) {
+ if (enable && !record.enabled) {
+ gl.glEnable(GL2ES1.GL_FOG);
+ record.enabled = true;
+ } else if (!enable && record.enabled) {
+ gl.glDisable(GL2ES1.GL_FOG);
+ record.enabled = false;
+ }
+ } else {
+ if (enable) {
+ gl.glEnable(GL2ES1.GL_FOG);
+ } else {
+ gl.glDisable(GL2ES1.GL_FOG);
+ }
+ record.enabled = enable;
+ }
+ }
+
+ private static void applyFogColor(final ReadOnlyColorRGBA color, final FogStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || !color.equals(record.fogColor)) {
+ record.fogColor.set(color);
+ record.colorBuff.clear();
+ record.colorBuff.put(record.fogColor.getRed()).put(record.fogColor.getGreen()).put(
+ record.fogColor.getBlue()).put(record.fogColor.getAlpha());
+ record.colorBuff.flip();
+ gl.getGL2ES1().glFogfv(GL2ES1.GL_FOG_COLOR, record.colorBuff);
+ }
+ }
+
+ private static void applyFogSource(final CoordinateSource source, final FogStateRecord record,
+ final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (caps.isFogCoordinatesSupported()) {
+ if (!record.isValid() || !source.equals(record.source)) {
+ if (source == CoordinateSource.Depth) {
+ gl.getGL2().glFogi(GL2.GL_FOG_COORDINATE_SOURCE, GL2.GL_FRAGMENT_DEPTH);
+ } else {
+ gl.getGL2().glFogi(GL2.GL_FOG_COORDINATE_SOURCE, GL2.GL_FOG_COORDINATE);
+ }
+ }
+ }
+ }
+
+ private static void applyFogMode(final DensityFunction densityFunction, final FogStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ int glMode = 0;
+ switch (densityFunction) {
+ case Exponential:
+ glMode = GL2ES1.GL_EXP;
+ break;
+ case Linear:
+ glMode = GL.GL_LINEAR;
+ break;
+ case ExponentialSquared:
+ glMode = GL2ES1.GL_EXP2;
+ break;
+ }
+
+ if (!record.isValid() || record.fogMode != glMode) {
+ gl.getGL2().glFogi(GL2ES1.GL_FOG_MODE, glMode);
+ record.fogMode = glMode;
+ }
+ }
+
+ private static void applyFogHint(final Quality quality, final FogStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ int glHint = 0;
+ switch (quality) {
+ case PerVertex:
+ glHint = GL.GL_FASTEST;
+ break;
+ case PerPixel:
+ glHint = GL.GL_NICEST;
+ break;
+ }
+
+ if (!record.isValid() || record.fogHint != glHint) {
+ gl.glHint(GL2ES1.GL_FOG_HINT, glHint);
+ record.fogHint = glHint;
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFragmentProgramStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFragmentProgramStateUtil.java
new file mode 100644
index 0000000..5b8d068
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFragmentProgramStateUtil.java
@@ -0,0 +1,125 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.FragmentProgramState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.FragmentProgramStateRecord;
+import com.ardor3d.util.geom.BufferUtils;
+
+public final class JoglFragmentProgramStateUtil {
+ private static final Logger logger = Logger.getLogger(JoglFragmentProgramStateUtil.class.getName());
+
+ /**
+ * Queries OpenGL for errors in the fragment program. Errors are logged as SEVERE, noting both the line number and
+ * message.
+ */
+ private static void checkProgramError() {
+ final GL gl = GLU.getCurrentGL();
+
+ if (gl.glGetError() == GL.GL_INVALID_OPERATION) {
+ // retrieve the error position
+ final IntBuffer errorloc = BufferUtils.createIntBuffer(16);
+ gl.glGetIntegerv(GL2.GL_PROGRAM_ERROR_POSITION_ARB, errorloc); // TODO Check for integer
+
+ logger.severe("Error " + gl.glGetString(GL2.GL_PROGRAM_ERROR_STRING_ARB) + " in fragment program on line "
+ + errorloc.get(0));
+ }
+ }
+
+ private static int create(final ByteBuffer program) {
+ final GL gl = GLU.getCurrentGL();
+
+ final IntBuffer buf = BufferUtils.createIntBuffer(1);
+
+ gl.getGL2().glGenProgramsARB(buf.limit(), buf); // TODO Check <size>
+ gl.getGL2().glBindProgramARB(GL2.GL_FRAGMENT_PROGRAM_ARB, buf.get(0));
+
+ final byte array[] = new byte[program.limit()];
+ program.rewind();
+ program.get(array);
+ gl.getGL2().glProgramStringARB(GL2.GL_FRAGMENT_PROGRAM_ARB, GL2.GL_PROGRAM_FORMAT_ASCII_ARB, array.length, new String(
+ array)); // TODO Check cost of using non-buffer
+
+ checkProgramError();
+
+ return buf.get(0);
+ }
+
+ public static void apply(final JoglRenderer renderer, final FragmentProgramState state) {
+ final GL gl = GLU.getCurrentGL();
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+
+ if (caps.isFragmentProgramSupported()) {
+ final FragmentProgramStateRecord record = (FragmentProgramStateRecord) context
+ .getStateRecord(StateType.FragmentProgram);
+ context.setCurrentState(StateType.FragmentProgram, state);
+
+ if (!record.isValid() || record.getReference() != state) {
+ record.setReference(state);
+ if (state.isEnabled()) {
+ // Fragment program not yet loaded
+ if (state._getProgramID() == -1) {
+ if (state.getProgramAsBuffer() != null) {
+ final int id = create(state.getProgramAsBuffer());
+ state._setProgramID(id);
+ } else {
+ return;
+ }
+ }
+
+ gl.glEnable(GL2.GL_FRAGMENT_PROGRAM_ARB);
+ gl.getGL2().glBindProgramARB(GL2.GL_FRAGMENT_PROGRAM_ARB, state._getProgramID());
+
+ // load environmental parameters...
+ // TODO: Reevaluate how this is done.
+ /*
+ * for (int i = 0; i < envparameters.length; i++) if (envparameters[i] != null)
+ * gl.glProgramEnvParameter4fARB( GL.GL_FRAGMENT_PROGRAM_ARB, i, envparameters[i][0],
+ * envparameters[i][1], envparameters[i][2], envparameters[i][3]);
+ */
+
+ // load local parameters...
+ if (state.isUsingParameters()) {
+ // no parameters are used
+ for (int i = 0; i < state._getParameters().length; i++) {
+ if (state._getParameters()[i] != null) {
+ gl.getGL2().glProgramLocalParameter4fARB(GL2.GL_FRAGMENT_PROGRAM_ARB, i,
+ state._getParameters()[i][0], state._getParameters()[i][1], state
+ ._getParameters()[i][2], state._getParameters()[i][3]);
+ }
+ }
+ }
+
+ } else {
+ gl.glDisable(GL2.GL_FRAGMENT_PROGRAM_ARB);
+ }
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglLightStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglLightStateUtil.java
new file mode 100644
index 0000000..3050d67
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglLightStateUtil.java
@@ -0,0 +1,412 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.light.DirectionalLight;
+import com.ardor3d.light.Light;
+import com.ardor3d.light.PointLight;
+import com.ardor3d.light.SpotLight;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.math.type.ReadOnlyMatrix4;
+import com.ardor3d.math.type.ReadOnlyVector3;
+import com.ardor3d.renderer.Camera;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.LightState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.LightRecord;
+import com.ardor3d.renderer.state.record.LightStateRecord;
+
+public abstract class JoglLightStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final LightState state) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+ final LightStateRecord record = (LightStateRecord) context.getStateRecord(StateType.Light);
+ context.setCurrentState(StateType.Light, state);
+
+ if (state.isEnabled() && LightState.LIGHTS_ENABLED) {
+ setLightEnabled(true, record);
+ setTwoSided(state.getTwoSidedLighting(), record);
+ setLocalViewer(state.getLocalViewer(), record);
+ if (caps.isOpenGL1_2Supported()) {
+ setSpecularControl(state.getSeparateSpecular(), record);
+ }
+
+ for (int i = 0, max = state.getNumberOfChildren(); i < max; i++) {
+ final Light light = state.get(i);
+ LightRecord lr = record.getLightRecord(i);
+ // TODO: use the reference to get the lightrecord - rherlitz
+
+ if (lr == null) {
+ lr = new LightRecord();
+ record.setLightRecord(lr, i);
+ }
+
+ if (light == null) {
+ setSingleLightEnabled(false, i, record, lr);
+ } else {
+ if (light.isEnabled()) {
+ setLight(i, light, record, state, lr);
+ } else {
+ setSingleLightEnabled(false, i, record, lr);
+ }
+ }
+ }
+
+ // disable lights at and above the max count in this state
+ for (int i = state.getNumberOfChildren(); i < LightState.MAX_LIGHTS_ALLOWED; i++) {
+ LightRecord lr = record.getLightRecord(i);
+
+ if (lr == null) {
+ lr = new LightRecord();
+ record.setLightRecord(lr, i);
+ }
+ setSingleLightEnabled(false, i, record, lr);
+ }
+
+ if ((state.getLightMask() & LightState.MASK_GLOBALAMBIENT) == 0) {
+ setModelAmbient(record, state.getGlobalAmbient());
+ } else {
+ setModelAmbient(record, ColorRGBA.BLACK_NO_ALPHA);
+ }
+ } else {
+ setLightEnabled(false, record);
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void setLight(final int index, final Light light, final LightStateRecord record,
+ final LightState state, final LightRecord lr) {
+ setSingleLightEnabled(true, index, record, lr);
+
+ if ((state.getLightMask() & LightState.MASK_AMBIENT) == 0
+ && (light.getLightMask() & LightState.MASK_AMBIENT) == 0) {
+ setAmbient(index, record, light.getAmbient(), lr);
+ } else {
+ setAmbient(index, record, ColorRGBA.BLACK_NO_ALPHA, lr);
+ }
+
+ if ((state.getLightMask() & LightState.MASK_DIFFUSE) == 0
+ && (light.getLightMask() & LightState.MASK_DIFFUSE) == 0) {
+
+ setDiffuse(index, record, light.getDiffuse(), lr);
+ } else {
+ setDiffuse(index, record, ColorRGBA.BLACK_NO_ALPHA, lr);
+ }
+
+ if ((state.getLightMask() & LightState.MASK_SPECULAR) == 0
+ && (light.getLightMask() & LightState.MASK_SPECULAR) == 0) {
+
+ setSpecular(index, record, light.getSpecular(), lr);
+ } else {
+ setSpecular(index, record, ColorRGBA.BLACK_NO_ALPHA, lr);
+ }
+
+ if (light.isAttenuate()) {
+ setAttenuate(true, index, light, record, lr);
+
+ } else {
+ setAttenuate(false, index, light, record, lr);
+
+ }
+
+ switch (light.getType()) {
+ case Directional: {
+ final DirectionalLight dirLight = (DirectionalLight) light;
+
+ final ReadOnlyVector3 direction = dirLight.getDirection();
+ setPosition(index, record, -direction.getXf(), -direction.getYf(), -direction.getZf(), 0, lr);
+ break;
+ }
+ case Point:
+ case Spot: {
+ final PointLight pointLight = (PointLight) light;
+ final ReadOnlyVector3 location = pointLight.getLocation();
+ setPosition(index, record, location.getXf(), location.getYf(), location.getZf(), 1, lr);
+ break;
+ }
+ }
+
+ if (light.getType() == Light.Type.Spot) {
+ final SpotLight spot = (SpotLight) light;
+ final ReadOnlyVector3 direction = spot.getDirection();
+ setSpotCutoff(index, record, spot.getAngle(), lr);
+ setSpotDirection(index, record, direction.getXf(), direction.getYf(), direction.getZf(), 0);
+ setSpotExponent(index, record, spot.getExponent(), lr);
+ } else {
+ // set the cutoff to 180, which causes the other spot params to be
+ // ignored.
+ setSpotCutoff(index, record, 180, lr);
+ }
+ }
+
+ private static void setSingleLightEnabled(final boolean enable, final int index, final LightStateRecord record,
+ final LightRecord lr) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || lr.isEnabled() != enable) {
+ if (enable) {
+ gl.glEnable(GLLightingFunc.GL_LIGHT0 + index);
+ } else {
+ gl.glDisable(GLLightingFunc.GL_LIGHT0 + index);
+ }
+
+ lr.setEnabled(enable);
+ }
+ }
+
+ private static void setLightEnabled(final boolean enable, final LightStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || record.isEnabled() != enable) {
+ if (enable) {
+ gl.glEnable(GLLightingFunc.GL_LIGHTING);
+ } else {
+ gl.glDisable(GLLightingFunc.GL_LIGHTING);
+ }
+ record.setEnabled(enable);
+ }
+ }
+
+ private static void setTwoSided(final boolean twoSided, final LightStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || record.isTwoSidedOn() != twoSided) {
+ if (twoSided) {
+ gl.getGL2().glLightModeli(GL2ES1.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE);
+ } else {
+ gl.getGL2().glLightModeli(GL2ES1.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_FALSE);
+ }
+ record.setTwoSidedOn(twoSided);
+ }
+ }
+
+ private static void setLocalViewer(final boolean localViewer, final LightStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || record.isLocalViewer() != localViewer) {
+ if (localViewer) {
+ gl.getGL2().glLightModeli(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE);
+ } else {
+ gl.getGL2().glLightModeli(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_FALSE);
+ }
+ record.setLocalViewer(localViewer);
+ }
+ }
+
+ private static void setSpecularControl(final boolean separateSpecularOn, final LightStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || record.isSeparateSpecular() != separateSpecularOn) {
+ if (separateSpecularOn) {
+ gl.getGL2().glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL, GL2.GL_SEPARATE_SPECULAR_COLOR);
+ } else {
+ gl.getGL2().glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL, GL2.GL_SINGLE_COLOR);
+ }
+ record.setSeparateSpecular(separateSpecularOn);
+ }
+ }
+
+ private static void setModelAmbient(final LightStateRecord record, final ReadOnlyColorRGBA globalAmbient) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || !record.globalAmbient.equals(globalAmbient)) {
+ record.lightBuffer.clear();
+ record.lightBuffer.put(globalAmbient.getRed());
+ record.lightBuffer.put(globalAmbient.getGreen());
+ record.lightBuffer.put(globalAmbient.getBlue());
+ record.lightBuffer.put(globalAmbient.getAlpha());
+ record.lightBuffer.flip();
+ gl.getGL2().glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT, record.lightBuffer); // TODO Check for float
+ record.globalAmbient.set(globalAmbient);
+ }
+ }
+
+ private static void setAmbient(final int index, final LightStateRecord record, final ReadOnlyColorRGBA ambient,
+ final LightRecord lr) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || !lr.ambient.equals(ambient)) {
+ record.lightBuffer.clear();
+ record.lightBuffer.put(ambient.getRed());
+ record.lightBuffer.put(ambient.getGreen());
+ record.lightBuffer.put(ambient.getBlue());
+ record.lightBuffer.put(ambient.getAlpha());
+ record.lightBuffer.flip();
+ gl.getGL2().glLightfv(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_AMBIENT, record.lightBuffer); // TODO Check for float
+ lr.ambient.set(ambient);
+ }
+ }
+
+ private static void setDiffuse(final int index, final LightStateRecord record, final ReadOnlyColorRGBA diffuse,
+ final LightRecord lr) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || !lr.diffuse.equals(diffuse)) {
+ record.lightBuffer.clear();
+ record.lightBuffer.put(diffuse.getRed());
+ record.lightBuffer.put(diffuse.getGreen());
+ record.lightBuffer.put(diffuse.getBlue());
+ record.lightBuffer.put(diffuse.getAlpha());
+ record.lightBuffer.flip();
+ gl.getGL2().glLightfv(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_DIFFUSE, record.lightBuffer); // TODO Check for float
+ lr.diffuse.set(diffuse);
+ }
+ }
+
+ private static void setSpecular(final int index, final LightStateRecord record, final ReadOnlyColorRGBA specular,
+ final LightRecord lr) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || !lr.specular.equals(specular)) {
+ record.lightBuffer.clear();
+ record.lightBuffer.put(specular.getRed());
+ record.lightBuffer.put(specular.getGreen());
+ record.lightBuffer.put(specular.getBlue());
+ record.lightBuffer.put(specular.getAlpha());
+ record.lightBuffer.flip();
+ gl.getGL2().glLightfv(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_SPECULAR, record.lightBuffer); // TODO Check for float
+ lr.specular.set(specular);
+ }
+ }
+
+ private static void setPosition(final int index, final LightStateRecord record, final float positionX,
+ final float positionY, final float positionZ, final float positionW, final LightRecord lr) {
+ final GL gl = GLU.getCurrentGL();
+
+ // From OpenGL Docs:
+ // The light position is transformed by the contents of the current top
+ // of the ModelView matrix stack when you specify the light position
+ // with a call to glLightfv(GL_LIGHT_POSITION,...). If you later change
+ // the ModelView matrix, such as when the view changes for the next
+ // frame, the light position isn't automatically retransformed by the
+ // new contents of the ModelView matrix. If you want to update the
+ // light's position, you must again specify the light position with a
+ // call to glLightfv(GL_LIGHT_POSITION,...).
+
+ // XXX: This is a hack until we get a better lighting model up
+ final ReadOnlyMatrix4 modelViewMatrix = Camera.getCurrentCamera().getModelViewMatrix();
+
+ if (!record.isValid() || lr.position.getXf() != positionX || lr.position.getYf() != positionY
+ || lr.position.getZf() != positionZ || lr.position.getWf() != positionW
+ || !lr.modelViewMatrix.equals(modelViewMatrix)) {
+
+ record.lightBuffer.clear();
+ record.lightBuffer.put(positionX);
+ record.lightBuffer.put(positionY);
+ record.lightBuffer.put(positionZ);
+ record.lightBuffer.put(positionW);
+ record.lightBuffer.flip();
+ gl.getGL2().glLightfv(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_POSITION, record.lightBuffer);
+
+ lr.position.set(positionX, positionY, positionZ, positionW);
+ if (!Camera.getCurrentCamera().isFrameDirty()) {
+ lr.modelViewMatrix.set(modelViewMatrix);
+ }
+ }
+ }
+
+ private static void setSpotDirection(final int index, final LightStateRecord record, final float directionX,
+ final float directionY, final float directionZ, final float value) {
+ final GL gl = GLU.getCurrentGL();
+
+ // From OpenGL Docs:
+ // The light position is transformed by the contents of the current top
+ // of the ModelView matrix stack when you specify the light position
+ // with a call to glLightfv(GL_LIGHT_POSITION,...). If you later change
+ // the ModelView matrix, such as when the view changes for the next
+ // frame, the light position isn't automatically retransformed by the
+ // new contents of the ModelView matrix. If you want to update the
+ // light's position, you must again specify the light position with a
+ // call to glLightfv(GL_LIGHT_POSITION,...).
+ record.lightBuffer.clear();
+ record.lightBuffer.put(directionX);
+ record.lightBuffer.put(directionY);
+ record.lightBuffer.put(directionZ);
+ record.lightBuffer.put(value);
+ record.lightBuffer.flip();
+ gl.getGL2().glLightfv(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_SPOT_DIRECTION, record.lightBuffer); // TODO Check for float
+ }
+
+ private static void setConstant(final int index, final float constant, final LightRecord lr, final boolean force) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (force || constant != lr.getConstant()) {
+ gl.getGL2().glLightf(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_CONSTANT_ATTENUATION, constant);
+ lr.setConstant(constant);
+ }
+ }
+
+ private static void setLinear(final int index, final float linear, final LightRecord lr, final boolean force) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (force || linear != lr.getLinear()) {
+ gl.getGL2().glLightf(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_LINEAR_ATTENUATION, linear);
+ lr.setLinear(linear);
+ }
+ }
+
+ private static void setQuadratic(final int index, final float quad, final LightRecord lr, final boolean force) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (force || quad != lr.getQuadratic()) {
+ gl.getGL2().glLightf(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_QUADRATIC_ATTENUATION, quad);
+ lr.setQuadratic(quad);
+ }
+ }
+
+ private static void setAttenuate(final boolean attenuate, final int index, final Light light,
+ final LightStateRecord record, final LightRecord lr) {
+ if (attenuate) {
+ setConstant(index, light.getConstant(), lr, !record.isValid());
+ setLinear(index, light.getLinear(), lr, !record.isValid());
+ setQuadratic(index, light.getQuadratic(), lr, !record.isValid());
+ } else {
+ setConstant(index, 1, lr, !record.isValid());
+ setLinear(index, 0, lr, !record.isValid());
+ setQuadratic(index, 0, lr, !record.isValid());
+ }
+ lr.setAttenuate(attenuate);
+ }
+
+ private static void setSpotExponent(final int index, final LightStateRecord record, final float exponent,
+ final LightRecord lr) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || lr.getSpotExponent() != exponent) {
+ gl.getGL2().glLightf(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_SPOT_EXPONENT, exponent);
+ lr.setSpotExponent(exponent);
+ }
+ }
+
+ private static void setSpotCutoff(final int index, final LightStateRecord record, final float cutoff,
+ final LightRecord lr) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || lr.getSpotCutoff() != cutoff) {
+ gl.getGL2().glLightf(GLLightingFunc.GL_LIGHT0 + index, GLLightingFunc.GL_SPOT_CUTOFF, cutoff);
+ lr.setSpotCutoff(cutoff);
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglMaterialStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglMaterialStateUtil.java
new file mode 100644
index 0000000..4a20143
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglMaterialStateUtil.java
@@ -0,0 +1,214 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.MaterialState;
+import com.ardor3d.renderer.state.MaterialState.ColorMaterial;
+import com.ardor3d.renderer.state.MaterialState.MaterialFace;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.MaterialStateRecord;
+
+public abstract class JoglMaterialStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final MaterialState state) {
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final MaterialStateRecord record = (MaterialStateRecord) context.getStateRecord(StateType.Material);
+ context.setCurrentState(StateType.Material, state);
+
+ if (state.isEnabled()) {
+ // setup colormaterial, if changed.
+ applyColorMaterial(state.getColorMaterial(), state.getColorMaterialFace(), record);
+
+ // apply colors, if needed and not what is currently set.
+ applyColor(ColorMaterial.Ambient, state.getAmbient(), state.getBackAmbient(), record);
+ applyColor(ColorMaterial.Diffuse, state.getDiffuse(), state.getBackDiffuse(), record);
+ applyColor(ColorMaterial.Emissive, state.getEmissive(), state.getBackEmissive(), record);
+ applyColor(ColorMaterial.Specular, state.getSpecular(), state.getBackSpecular(), record);
+
+ // set our shine
+ applyShininess(state.getShininess(), state.getBackShininess(), record);
+ } else {
+ // apply defaults
+ applyColorMaterial(MaterialState.DEFAULT_COLOR_MATERIAL, MaterialState.DEFAULT_COLOR_MATERIAL_FACE, record);
+
+ applyColor(ColorMaterial.Ambient, MaterialState.DEFAULT_AMBIENT, MaterialState.DEFAULT_AMBIENT, record);
+ applyColor(ColorMaterial.Diffuse, MaterialState.DEFAULT_DIFFUSE, MaterialState.DEFAULT_DIFFUSE, record);
+ applyColor(ColorMaterial.Emissive, MaterialState.DEFAULT_EMISSIVE, MaterialState.DEFAULT_EMISSIVE, record);
+ applyColor(ColorMaterial.Specular, MaterialState.DEFAULT_SPECULAR, MaterialState.DEFAULT_SPECULAR, record);
+
+ applyShininess(MaterialState.DEFAULT_SHININESS, MaterialState.DEFAULT_SHININESS, record);
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void applyColor(final ColorMaterial glMatColor, final ReadOnlyColorRGBA frontColor,
+ final ReadOnlyColorRGBA backColor, final MaterialStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ final int glMat = getGLColorMaterial(glMatColor);
+ if (frontColor.equals(backColor)) {
+ // consolidate to one call
+ if (!isVertexProvidedColor(MaterialFace.FrontAndBack, glMatColor, record)) {
+ if (!record.isValid() || !record.isSetColor(MaterialFace.FrontAndBack, glMatColor, frontColor, record)) {
+ record.tempColorBuff.clear();
+ record.tempColorBuff.put(frontColor.getRed()).put(frontColor.getGreen()).put(frontColor.getBlue())
+ .put(frontColor.getAlpha());
+ record.tempColorBuff.flip();
+ gl.getGL2().glMaterialfv(getGLMaterialFace(MaterialFace.FrontAndBack), glMat, record.tempColorBuff);
+ record.setColor(MaterialFace.FrontAndBack, glMatColor, frontColor);
+ }
+ }
+ } else {
+ if (!isVertexProvidedColor(MaterialFace.Front, glMatColor, record)) {
+ if (!record.isValid() || !record.isSetColor(MaterialFace.Front, glMatColor, frontColor, record)) {
+ record.tempColorBuff.clear();
+ record.tempColorBuff.put(frontColor.getRed()).put(frontColor.getGreen()).put(frontColor.getBlue())
+ .put(frontColor.getAlpha());
+ record.tempColorBuff.flip();
+ gl.getGL2().glMaterialfv(getGLMaterialFace(MaterialFace.Front), glMat, record.tempColorBuff);
+ record.setColor(MaterialFace.Front, glMatColor, frontColor);
+ }
+ }
+
+ if (!isVertexProvidedColor(MaterialFace.Back, glMatColor, record)) {
+ if (!record.isValid() || !record.isSetColor(MaterialFace.Back, glMatColor, backColor, record)) {
+ record.tempColorBuff.clear();
+ record.tempColorBuff.put(backColor.getRed()).put(backColor.getGreen()).put(backColor.getBlue())
+ .put(backColor.getAlpha());
+ record.tempColorBuff.flip();
+ gl.getGL2().glMaterialfv(getGLMaterialFace(MaterialFace.Back), glMat, record.tempColorBuff);
+ record.setColor(MaterialFace.Back, glMatColor, backColor);
+ }
+ }
+ }
+ }
+
+ private static boolean isVertexProvidedColor(final MaterialFace face, final ColorMaterial glMatColor,
+ final MaterialStateRecord record) {
+ if (face != record.colorMaterialFace) {
+ return false;
+ }
+ switch (glMatColor) {
+ case Ambient:
+ return record.colorMaterial == ColorMaterial.Ambient
+ || record.colorMaterial == ColorMaterial.AmbientAndDiffuse;
+ case Diffuse:
+ return record.colorMaterial == ColorMaterial.Diffuse
+ || record.colorMaterial == ColorMaterial.AmbientAndDiffuse;
+ case Specular:
+ return record.colorMaterial == ColorMaterial.Specular;
+ case Emissive:
+ return record.colorMaterial == ColorMaterial.Emissive;
+ case AmbientAndDiffuse:
+ break;
+ case None:
+ break;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ private static void applyColorMaterial(final ColorMaterial colorMaterial, final MaterialFace face,
+ final MaterialStateRecord record) {
+ if (!record.isValid() || face != record.colorMaterialFace || colorMaterial != record.colorMaterial) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (colorMaterial == ColorMaterial.None) {
+ gl.glDisable(GLLightingFunc.GL_COLOR_MATERIAL);
+ } else {
+ final int glMat = getGLColorMaterial(colorMaterial);
+ final int glFace = getGLMaterialFace(face);
+
+ gl.getGL2().glColorMaterial(glFace, glMat);
+ gl.glEnable(GLLightingFunc.GL_COLOR_MATERIAL);
+ record.resetColorsForCM(face, colorMaterial);
+ }
+ record.colorMaterial = colorMaterial;
+ record.colorMaterialFace = face;
+ }
+ }
+
+ private static void applyShininess(final float frontShininess, final float backShininess,
+ final MaterialStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (frontShininess == backShininess) {
+ // consolidate to one call
+ if (!record.isValid() || frontShininess != record.frontShininess || record.backShininess != backShininess) {
+ gl.getGL2().glMaterialf(getGLMaterialFace(MaterialFace.FrontAndBack), GLLightingFunc.GL_SHININESS, frontShininess);
+ record.backShininess = record.frontShininess = frontShininess;
+ }
+ } else {
+ if (!record.isValid() || frontShininess != record.frontShininess) {
+ gl.getGL2().glMaterialf(getGLMaterialFace(MaterialFace.Front), GLLightingFunc.GL_SHININESS, frontShininess);
+ record.frontShininess = frontShininess;
+ }
+
+ if (!record.isValid() || backShininess != record.backShininess) {
+ gl.getGL2().glMaterialf(getGLMaterialFace(MaterialFace.Back), GLLightingFunc.GL_SHININESS, backShininess);
+ record.backShininess = backShininess;
+ }
+ }
+ }
+
+ /**
+ * Converts the color material setting of this state to a GL constant.
+ *
+ * @return the GL constant
+ */
+ private static int getGLColorMaterial(final ColorMaterial material) {
+ switch (material) {
+ case None:
+ return GL.GL_NONE;
+ case Ambient:
+ return GLLightingFunc.GL_AMBIENT;
+ case Diffuse:
+ return GLLightingFunc.GL_DIFFUSE;
+ case AmbientAndDiffuse:
+ return GLLightingFunc.GL_AMBIENT_AND_DIFFUSE;
+ case Emissive:
+ return GLLightingFunc.GL_EMISSION;
+ case Specular:
+ return GLLightingFunc.GL_SPECULAR;
+ }
+ throw new IllegalArgumentException("invalid color material setting: " + material);
+ }
+
+ /**
+ * Converts the material face setting of this state to a GL constant.
+ *
+ * @return the GL constant
+ */
+ private static int getGLMaterialFace(final MaterialFace face) {
+ switch (face) {
+ case Front:
+ return GL.GL_FRONT;
+ case Back:
+ return GL.GL_BACK;
+ case FrontAndBack:
+ return GL.GL_FRONT_AND_BACK;
+ }
+ throw new IllegalArgumentException("invalid material face setting: " + face);
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglOffsetStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglOffsetStateUtil.java
new file mode 100644
index 0000000..b2cd05a
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglOffsetStateUtil.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.OffsetState;
+import com.ardor3d.renderer.state.OffsetState.OffsetType;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.OffsetStateRecord;
+
+public abstract class JoglOffsetStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final OffsetState state) {
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final OffsetStateRecord record = (OffsetStateRecord) context.getStateRecord(StateType.Offset);
+ context.setCurrentState(StateType.Offset, state);
+
+ if (state.isEnabled()) {
+ // enable any set offset types
+ setOffsetEnabled(OffsetType.Fill, state.isTypeEnabled(OffsetType.Fill), record);
+ setOffsetEnabled(OffsetType.Line, state.isTypeEnabled(OffsetType.Line), record);
+ setOffsetEnabled(OffsetType.Point, state.isTypeEnabled(OffsetType.Point), record);
+
+ // set factor and units.
+ setOffset(state.getFactor(), state.getUnits(), record);
+ } else {
+ // disable all offset types
+ setOffsetEnabled(OffsetType.Fill, false, record);
+ setOffsetEnabled(OffsetType.Line, false, record);
+ setOffsetEnabled(OffsetType.Point, false, record);
+
+ // set factor and units to default 0, 0.
+ setOffset(0, 0, record);
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void setOffsetEnabled(final OffsetType type, final boolean typeEnabled,
+ final OffsetStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ final int glType = getGLType(type);
+ if (!record.isValid() || typeEnabled != record.enabledOffsets.contains(type)) {
+ if (typeEnabled) {
+ gl.glEnable(glType);
+ } else {
+ gl.glDisable(glType);
+ }
+ }
+ }
+
+ private static void setOffset(final float factor, final float units, final OffsetStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!record.isValid() || record.factor != factor || record.units != units) {
+ gl.glPolygonOffset(factor, units);
+ record.factor = factor;
+ record.units = units;
+ }
+ }
+
+ private static int getGLType(final OffsetType type) {
+ switch (type) {
+ case Fill:
+ return GL.GL_POLYGON_OFFSET_FILL;
+ case Line:
+ return GL2GL3.GL_POLYGON_OFFSET_LINE;
+ case Point:
+ return GL2GL3.GL_POLYGON_OFFSET_POINT;
+ }
+ throw new IllegalArgumentException("invalid type: " + type);
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShaderObjectsStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShaderObjectsStateUtil.java
new file mode 100644
index 0000000..f254b29
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShaderObjectsStateUtil.java
@@ -0,0 +1,384 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GL4;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.GLSLShaderObjectsState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.ShaderObjectsStateRecord;
+import com.ardor3d.scene.state.jogl.shader.JoglShaderUtil;
+import com.ardor3d.util.Ardor3dException;
+import com.ardor3d.util.geom.BufferUtils;
+import com.ardor3d.util.shader.ShaderVariable;
+
+public abstract class JoglShaderObjectsStateUtil {
+ private static final Logger logger = Logger.getLogger(JoglShaderObjectsStateUtil.class.getName());
+
+ protected static void sendToGL(final GLSLShaderObjectsState state, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (state.getVertexShader() == null && state.getFragmentShader() == null) {
+ logger.warning("Could not find shader resources!" + "(both inputbuffers are null)");
+ state._needSendShader = false;
+ return;
+ }
+
+ if (state._programID == -1) {
+ state._programID = gl.getGL2().glCreateProgramObjectARB();
+ }
+
+ if (state.getVertexShader() != null) {
+ if (state._vertexShaderID != -1) {
+ removeVertShader(state);
+ }
+
+ state._vertexShaderID = gl.getGL2().glCreateShaderObjectARB(GL2ES2.GL_VERTEX_SHADER);
+
+ // Create the sources
+ final byte array[] = new byte[state.getVertexShader().limit()];
+ state.getVertexShader().rewind();
+ state.getVertexShader().get(array);
+ gl.getGL2().glShaderSourceARB(state._vertexShaderID, 1, new String[] { new String(array) },
+ new int[] { array.length }, 0);
+
+ // Compile the vertex shader
+ final IntBuffer compiled = BufferUtils.createIntBuffer(1);
+ gl.getGL2().glCompileShaderARB(state._vertexShaderID);
+ gl.getGL2().glGetObjectParameterivARB(state._vertexShaderID, GL2.GL_OBJECT_COMPILE_STATUS_ARB, compiled);
+ checkProgramError(compiled, state._vertexShaderID, state._vertexShaderName);
+
+ // Attach the program
+ gl.getGL2().glAttachObjectARB(state._programID, state._vertexShaderID);
+ } else if (state._vertexShaderID != -1) {
+ removeVertShader(state);
+ state._vertexShaderID = -1;
+ }
+
+ if (state.getFragmentShader() != null) {
+ if (state._fragmentShaderID != -1) {
+ removeFragShader(state);
+ }
+
+ state._fragmentShaderID = gl.getGL2().glCreateShaderObjectARB(GL2ES2.GL_FRAGMENT_SHADER);
+
+ // Create the sources
+ final byte array[] = new byte[state.getFragmentShader().limit()];
+ state.getFragmentShader().rewind();
+ state.getFragmentShader().get(array);
+ gl.getGL2().glShaderSourceARB(state._fragmentShaderID, 1, new String[] { new String(array) },
+ new int[] { array.length }, 0);
+
+ // Compile the fragment shader
+ final IntBuffer compiled = BufferUtils.createIntBuffer(1);
+ gl.getGL2().glCompileShaderARB(state._fragmentShaderID);
+ gl.getGL2().glGetObjectParameterivARB(state._fragmentShaderID, GL2.GL_OBJECT_COMPILE_STATUS_ARB, compiled);
+ checkProgramError(compiled, state._fragmentShaderID, state._vertexShaderName);
+
+ // Attach the program
+ gl.getGL2().glAttachObjectARB(state._programID, state._fragmentShaderID);
+ } else if (state._fragmentShaderID != -1) {
+ removeFragShader(state);
+ state._fragmentShaderID = -1;
+ }
+
+ if (caps.isGeometryShader4Supported()) {
+ if (state.getGeometryShader() != null) {
+ if (state._geometryShaderID != -1) {
+ removeGeomShader(state);
+ }
+
+ state._geometryShaderID = gl.getGL2().glCreateShaderObjectARB(GL3.GL_GEOMETRY_SHADER);
+
+ // Create the sources
+ final byte array[] = new byte[state.getGeometryShader().limit()];
+ state.getGeometryShader().rewind();
+ state.getGeometryShader().get(array);
+ gl.getGL2().glShaderSourceARB(state._geometryShaderID, 1, new String[] { new String(array) },
+ new int[] { array.length }, 0);
+
+ // Compile the geometry shader
+ final IntBuffer compiled = BufferUtils.createIntBuffer(1);
+ gl.getGL2().glCompileShaderARB(state._geometryShaderID);
+ gl.getGL2().glGetObjectParameterivARB(state._geometryShaderID, GL2.GL_OBJECT_COMPILE_STATUS_ARB, compiled);
+ checkProgramError(compiled, state._geometryShaderID, state._geometryShaderName);
+
+ // Attach the program
+ gl.getGL2().glAttachObjectARB(state._programID, state._geometryShaderID);
+ } else if (state._geometryShaderID != -1) {
+ removeGeomShader(state);
+ state._geometryShaderID = -1;
+ }
+ }
+
+ if (caps.isTessellationShadersSupported()) {
+ if (state.getTessellationControlShader() != null) {
+ if (state._tessellationControlShaderID != -1) {
+ removeTessControlShader(state);
+ }
+
+ state._tessellationControlShaderID = gl.getGL2().glCreateShaderObjectARB(GL3.GL_TESS_CONTROL_SHADER);
+
+ // Create the sources
+ final byte array[] = new byte[state.getTessellationControlShader().limit()];
+ state.getTessellationControlShader().rewind();
+ state.getTessellationControlShader().get(array);
+ gl.getGL2().glShaderSourceARB(state._tessellationControlShaderID, 1, new String[] { new String(array) },
+ new int[] { array.length }, 0);
+
+ // Compile the tessellation control shader
+ final IntBuffer compiled = BufferUtils.createIntBuffer(1);
+ gl.getGL2().glCompileShaderARB(state._tessellationControlShaderID);
+ gl.getGL2().glGetObjectParameterivARB(state._tessellationControlShaderID, GL2.GL_OBJECT_COMPILE_STATUS_ARB, compiled);
+ checkProgramError(compiled, state._tessellationControlShaderID, state._tessellationControlShaderName);
+
+ // Attach the program
+ gl.getGL2().glAttachObjectARB(state._programID, state._tessellationControlShaderID);
+ } else if (state._tessellationControlShaderID != -1) {
+ removeTessControlShader(state);
+ state._tessellationControlShaderID = -1;
+ }
+ if (state.getTessellationEvaluationShader() != null) {
+ if (state._tessellationEvaluationShaderID != -1) {
+ removeTessEvalShader(state);
+ }
+
+ state._tessellationEvaluationShaderID = gl.getGL2().glCreateShaderObjectARB(GL4.GL_TESS_CONTROL_SHADER);
+
+ // Create the sources
+ final byte array[] = new byte[state.getTessellationEvaluationShader().limit()];
+ state.getTessellationEvaluationShader().rewind();
+ state.getTessellationEvaluationShader().get(array);
+ gl.getGL2().glShaderSourceARB(state._tessellationEvaluationShaderID, 1, new String[] { new String(array) },
+ new int[] { array.length }, 0);
+
+ // Compile the tessellation control shader
+ final IntBuffer compiled = BufferUtils.createIntBuffer(1);
+ gl.getGL2().glCompileShaderARB(state._tessellationEvaluationShaderID);
+ gl.getGL2().glGetObjectParameterivARB(state._tessellationEvaluationShaderID, GL2.GL_OBJECT_COMPILE_STATUS_ARB, compiled);
+ checkProgramError(compiled, state._tessellationEvaluationShaderID, state._tessellationEvaluationShaderName);
+
+ // Attach the program
+ gl.getGL2().glAttachObjectARB(state._programID, state._tessellationEvaluationShaderID);
+ } else if (state._tessellationEvaluationShaderID != -1) {
+ removeTessEvalShader(state);
+ state._tessellationEvaluationShaderID = -1;
+ }
+ }
+
+ gl.getGL2().glLinkProgramARB(state._programID);
+ checkLinkError(state._programID);
+ state.setNeedsRefresh(true);
+ state._needSendShader = false;
+ }
+
+ private static void checkLinkError(final int programId) {
+ final GL gl = GLU.getCurrentGL();
+
+ final IntBuffer compiled = BufferUtils.createIntBuffer(1);
+ gl.getGL2().glGetObjectParameterivARB(programId, GL2ES2.GL_LINK_STATUS, compiled);
+ if (compiled.get(0) == GL.GL_FALSE) {
+ gl.getGL2().glGetObjectParameterivARB(programId, GL2ES2.GL_INFO_LOG_LENGTH, compiled);
+ final int length = compiled.get(0);
+ String out = null;
+ if (length > 0) {
+ final ByteBuffer infoLog = BufferUtils.createByteBuffer(length);
+
+ gl.getGL2().glGetInfoLogARB(programId, infoLog.limit(), compiled, infoLog);
+
+ final byte[] infoBytes = new byte[length];
+ infoLog.get(infoBytes);
+ out = new String(infoBytes);
+ }
+
+ logger.severe(out);
+
+ // throw new Ardor3dException("Error linking GLSL shader: " + out);
+ }
+ }
+
+ /** Removes the fragment shader */
+ private static void removeFragShader(final GLSLShaderObjectsState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (state._fragmentShaderID != -1) {
+ gl.getGL2().glDetachObjectARB(state._programID, state._fragmentShaderID);
+ gl.getGL2().glDeleteObjectARB(state._fragmentShaderID);
+ }
+ }
+
+ /** Removes the vertex shader */
+ private static void removeVertShader(final GLSLShaderObjectsState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (state._vertexShaderID != -1) {
+ gl.getGL2().glDetachObjectARB(state._programID, state._vertexShaderID);
+ gl.getGL2().glDeleteObjectARB(state._vertexShaderID);
+ }
+ }
+
+ /** Removes the geometry shader */
+ private static void removeGeomShader(final GLSLShaderObjectsState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (state._geometryShaderID != -1) {
+ gl.getGL2().glDetachObjectARB(state._programID, state._geometryShaderID);
+ gl.getGL2().glDeleteObjectARB(state._geometryShaderID);
+ }
+ }
+
+ /** Removes the tessellation control shader */
+ private static void removeTessControlShader(final GLSLShaderObjectsState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (state._tessellationControlShaderID != -1) {
+ gl.getGL2().glDetachObjectARB(state._programID, state._tessellationControlShaderID);
+ gl.getGL2().glDeleteObjectARB(state._tessellationControlShaderID);
+ }
+ }
+
+ /** Removes the tessellation evaluation shader */
+ private static void removeTessEvalShader(final GLSLShaderObjectsState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (state._tessellationEvaluationShaderID != -1) {
+ gl.getGL2().glDetachObjectARB(state._programID, state._tessellationEvaluationShaderID);
+ gl.getGL2().glDeleteObjectARB(state._tessellationEvaluationShaderID);
+ }
+ }
+
+ /**
+ * Check for program errors. If an error is detected, program exits.
+ *
+ * @param compiled
+ * the compiler state for a given shader
+ * @param id
+ * shader's id
+ */
+ private static void checkProgramError(final IntBuffer compiled, final int id, final String shaderName) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (compiled.get(0) == GL.GL_FALSE) {
+ final IntBuffer iVal = BufferUtils.createIntBuffer(1);
+ gl.getGL2().glGetObjectParameterivARB(id, GL2.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal);
+ final int length = iVal.get(0);
+ String out = null;
+
+ if (length > 0) {
+ final ByteBuffer infoLog = BufferUtils.createByteBuffer(length);
+
+ gl.getGL2().glGetInfoLogARB(id, infoLog.limit(), iVal, infoLog);
+
+ final byte[] infoBytes = new byte[length];
+ infoLog.get(infoBytes);
+ out = new String(infoBytes);
+ }
+
+ logger.severe(out);
+
+ final String nameString = shaderName.equals("") ? "" : " [ " + shaderName + " ]";
+ throw new Ardor3dException("Error compiling GLSL shader " + nameString + ": " + out);
+ }
+ }
+
+ public static void apply(final JoglRenderer renderer, final GLSLShaderObjectsState state) {
+ final GL gl = GLU.getCurrentGL();
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+
+ if (caps.isGLSLSupported()) {
+ // Ask for the current state record
+ final ShaderObjectsStateRecord record = (ShaderObjectsStateRecord) context
+ .getStateRecord(StateType.GLSLShader);
+ context.setCurrentState(StateType.GLSLShader, state);
+
+ if (state.isEnabled()) {
+ if (state._needSendShader) {
+ sendToGL(state, caps);
+ }
+
+ if (state._shaderDataLogic != null) {
+ state._shaderDataLogic.applyData(state, state._mesh, renderer);
+ }
+ }
+
+ if (!record.isValid() || record.getReference() != state || state.needsRefresh()) {
+ record.setReference(state);
+ if (state.isEnabled() && state._programID != -1) {
+ // clear any previously existing attributes
+ clearEnabledAttributes(record, gl);
+
+ // set our current shader
+ JoglShaderUtil.useShaderProgram(state._programID, record);
+
+ final List<ShaderVariable> attribs = state.getShaderAttributes();
+ for (int i = attribs.size(); --i >= 0;) {
+ final ShaderVariable shaderVariable = attribs.get(i);
+ if (shaderVariable.needsRefresh) {
+ JoglShaderUtil.updateAttributeLocation(shaderVariable, state._programID);
+ shaderVariable.needsRefresh = false;
+ }
+ JoglShaderUtil.updateShaderAttribute(renderer, shaderVariable, state.isUseAttributeVBO());
+ }
+
+ final List<ShaderVariable> uniforms = state.getShaderUniforms();
+ for (int i = uniforms.size(); --i >= 0;) {
+ final ShaderVariable shaderVariable = uniforms.get(i);
+ if (shaderVariable.needsRefresh) {
+ JoglShaderUtil.updateUniformLocation(shaderVariable, state._programID);
+ JoglShaderUtil.updateShaderUniform(shaderVariable);
+ shaderVariable.needsRefresh = false;
+ }
+ }
+ } else {
+ JoglShaderUtil.useShaderProgram(0, record);
+
+ clearEnabledAttributes(record, gl);
+ }
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+ }
+
+ private static void clearEnabledAttributes(final ShaderObjectsStateRecord record, final GL gl) {
+ // go through and disable any enabled attributes
+ if (!record.enabledAttributes.isEmpty()) {
+ for (int i = 0, maxI = record.enabledAttributes.size(); i < maxI; i++) {
+ final ShaderVariable var = record.enabledAttributes.get(i);
+ if (var.getSize() == 1) {
+ gl.getGL2().glDisableVertexAttribArrayARB(var.variableID);
+ } else {
+ for (int j = 0, maxJ = var.getSize(); j < maxJ; j++) {
+ gl.getGL2().glDisableVertexAttribArrayARB(var.variableID + j);
+ }
+ }
+ }
+ record.enabledAttributes.clear();
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShadingStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShadingStateUtil.java
new file mode 100644
index 0000000..ba3dea0
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShadingStateUtil.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.ShadingState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.ShadingState.ShadingMode;
+import com.ardor3d.renderer.state.record.ShadingStateRecord;
+
+public abstract class JoglShadingStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final ShadingState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ShadingStateRecord record = (ShadingStateRecord) context.getStateRecord(StateType.Shading);
+ context.setCurrentState(StateType.Shading, state);
+
+ // If not enabled, we'll use smooth
+ final int toApply = state.isEnabled() ? getGLShade(state.getShadingMode()) : GLLightingFunc.GL_SMOOTH;
+ // only apply if we're different. Update record to reflect any changes.
+ if (!record.isValid() || toApply != record.lastShade) {
+ gl.getGL2().glShadeModel(toApply);
+ record.lastShade = toApply;
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static int getGLShade(final ShadingMode shadeMode) {
+ switch (shadeMode) {
+ case Smooth:
+ return GLLightingFunc.GL_SMOOTH;
+ case Flat:
+ return GLLightingFunc.GL_FLAT;
+ }
+ throw new IllegalStateException("unknown shade mode: " + shadeMode);
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglStencilStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglStencilStateUtil.java
new file mode 100644
index 0000000..fd7204f
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglStencilStateUtil.java
@@ -0,0 +1,198 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.StencilState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.StencilState.StencilFunction;
+import com.ardor3d.renderer.state.StencilState.StencilOperation;
+import com.ardor3d.renderer.state.record.StencilStateRecord;
+
+public abstract class JoglStencilStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final StencilState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+ final StencilStateRecord record = (StencilStateRecord) context.getStateRecord(StateType.Stencil);
+ context.setCurrentState(StateType.Stencil, state);
+
+ setEnabled(state.isEnabled(), caps.isTwoSidedStencilSupported() ? state.isUseTwoSided() : false, record, caps);
+ if (state.isEnabled()) {
+ if (state.isUseTwoSided() && caps.isTwoSidedStencilSupported()) {
+ gl.getGL2().glActiveStencilFaceEXT(GL.GL_BACK);
+ applyMask(state.getStencilWriteMaskBack(), record, 2);
+ applyFunc(getGLStencilFunction(state.getStencilFunctionBack()), state.getStencilReferenceBack(), state
+ .getStencilFuncMaskBack(), record, 2);
+ applyOp(getGLStencilOp(state.getStencilOpFailBack(), caps), getGLStencilOp(state
+ .getStencilOpZFailBack(), caps), getGLStencilOp(state.getStencilOpZPassBack(), caps), record, 2);
+
+ gl.getGL2().glActiveStencilFaceEXT(GL.GL_FRONT);
+ applyMask(state.getStencilWriteMaskFront(), record, 1);
+ applyFunc(getGLStencilFunction(state.getStencilFunctionFront()), state.getStencilReferenceFront(),
+ state.getStencilFuncMaskFront(), record, 1);
+ applyOp(getGLStencilOp(state.getStencilOpFailFront(), caps), getGLStencilOp(state
+ .getStencilOpZFailFront(), caps), getGLStencilOp(state.getStencilOpZPassFront(), caps), record,
+ 1);
+ } else {
+ applyMask(state.getStencilWriteMaskFront(), record, 0);
+ applyFunc(getGLStencilFunction(state.getStencilFunctionFront()), state.getStencilReferenceFront(),
+ state.getStencilFuncMaskFront(), record, 0);
+ applyOp(getGLStencilOp(state.getStencilOpFailFront(), caps), getGLStencilOp(state
+ .getStencilOpZFailFront(), caps), getGLStencilOp(state.getStencilOpZPassFront(), caps), record,
+ 0);
+ }
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static int getGLStencilFunction(final StencilFunction function) {
+ switch (function) {
+ case Always:
+ return GL.GL_ALWAYS;
+ case Never:
+ return GL.GL_NEVER;
+ case EqualTo:
+ return GL.GL_EQUAL;
+ case NotEqualTo:
+ return GL.GL_NOTEQUAL;
+ case GreaterThan:
+ return GL.GL_GREATER;
+ case GreaterThanOrEqualTo:
+ return GL.GL_GEQUAL;
+ case LessThan:
+ return GL.GL_LESS;
+ case LessThanOrEqualTo:
+ return GL.GL_LEQUAL;
+ }
+ throw new IllegalArgumentException("unknown function: " + function);
+ }
+
+ private static int getGLStencilOp(final StencilOperation operation, final ContextCapabilities caps) {
+ switch (operation) {
+ case Keep:
+ return GL.GL_KEEP;
+ case DecrementWrap:
+ if (caps.isStencilWrapSupported()) {
+ return GL.GL_DECR_WRAP;
+ }
+ // FALLS THROUGH
+ case Decrement:
+ return GL.GL_DECR;
+ case IncrementWrap:
+ if (caps.isStencilWrapSupported()) {
+ return GL.GL_INCR_WRAP;
+ }
+ // FALLS THROUGH
+ case Increment:
+ return GL.GL_INCR;
+ case Invert:
+ return GL.GL_INVERT;
+ case Replace:
+ return GL.GL_REPLACE;
+ case Zero:
+ return GL.GL_ZERO;
+ }
+ throw new IllegalArgumentException("unknown operation: " + operation);
+ }
+
+ private static void setEnabled(final boolean enable, final boolean twoSided, final StencilStateRecord record,
+ final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (record.isValid()) {
+ if (enable && !record.enabled) {
+ gl.glEnable(GL.GL_STENCIL_TEST);
+ } else if (!enable && record.enabled) {
+ gl.glDisable(GL.GL_STENCIL_TEST);
+ }
+ } else {
+ if (enable) {
+ gl.glEnable(GL.GL_STENCIL_TEST);
+ } else {
+ gl.glDisable(GL.GL_STENCIL_TEST);
+ }
+ }
+
+ setTwoSidedEnabled(enable ? twoSided : false, record, caps);
+ record.enabled = enable;
+ }
+
+ private static void setTwoSidedEnabled(final boolean enable, final StencilStateRecord record,
+ final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (caps.isTwoSidedStencilSupported()) {
+ if (record.isValid()) {
+ if (enable && !record.useTwoSided) {
+ gl.glEnable(GL2.GL_STENCIL_TEST_TWO_SIDE_EXT);
+ } else if (!enable && record.useTwoSided) {
+ gl.glDisable(GL2.GL_STENCIL_TEST_TWO_SIDE_EXT);
+ }
+ } else {
+ if (enable) {
+ gl.glEnable(GL2.GL_STENCIL_TEST_TWO_SIDE_EXT);
+ } else {
+ gl.glDisable(GL2.GL_STENCIL_TEST_TWO_SIDE_EXT);
+ }
+ }
+ }
+ record.useTwoSided = enable;
+ }
+
+ private static void applyMask(final int writeMask, final StencilStateRecord record, final int face) {
+ final GL gl = GLU.getCurrentGL();
+
+ // if (!record.isValid() || writeMask != record.writeMask[face]) {
+ gl.glStencilMask(writeMask);
+ // record.writeMask[face] = writeMask;
+ // }
+ }
+
+ private static void applyFunc(final int glfunc, final int stencilRef, final int funcMask,
+ final StencilStateRecord record, final int face) {
+ final GL gl = GLU.getCurrentGL();
+
+ // if (!record.isValid() || glfunc != record.func[face] || stencilRef != record.ref[face]
+ // || funcMask != record.funcMask[face]) {
+ gl.glStencilFunc(glfunc, stencilRef, funcMask);
+ // record.func[face] = glfunc;
+ // record.ref[face] = stencilRef;
+ // record.funcMask[face] = funcMask;
+ // }
+ }
+
+ private static void applyOp(final int fail, final int zfail, final int zpass, final StencilStateRecord record,
+ final int face) {
+ final GL gl = GLU.getCurrentGL();
+
+ // if (!record.isValid() || fail != record.fail[face] || zfail != record.zfail[face]
+ // || zpass != record.zpass[face]) {
+ gl.glStencilOp(fail, zfail, zpass);
+ // record.fail[face] = fail;
+ // record.zfail[face] = zfail;
+ // record.zpass[face] = zpass;
+ // }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglTextureStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglTextureStateUtil.java
new file mode 100644
index 0000000..e98ced2
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglTextureStateUtil.java
@@ -0,0 +1,1730 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.glu.gl2.GLUgl2;
+
+import com.ardor3d.image.Image;
+import com.ardor3d.image.Texture;
+import com.ardor3d.image.Texture1D;
+import com.ardor3d.image.Texture2D;
+import com.ardor3d.image.Texture3D;
+import com.ardor3d.image.TextureCubeMap;
+import com.ardor3d.image.Texture.ApplyMode;
+import com.ardor3d.image.Texture.CombinerFunctionAlpha;
+import com.ardor3d.image.Texture.CombinerFunctionRGB;
+import com.ardor3d.image.Texture.CombinerOperandAlpha;
+import com.ardor3d.image.Texture.CombinerOperandRGB;
+import com.ardor3d.image.Texture.CombinerSource;
+import com.ardor3d.image.Texture.Type;
+import com.ardor3d.image.Texture.WrapAxis;
+import com.ardor3d.image.Texture.WrapMode;
+import com.ardor3d.image.util.ImageUtils;
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.TextureState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.RendererRecord;
+import com.ardor3d.renderer.state.record.TextureRecord;
+import com.ardor3d.renderer.state.record.TextureStateRecord;
+import com.ardor3d.renderer.state.record.TextureUnitRecord;
+import com.ardor3d.scene.state.jogl.util.JoglRendererUtil;
+import com.ardor3d.scene.state.jogl.util.JoglTextureUtil;
+import com.ardor3d.util.Constants;
+import com.ardor3d.util.TextureKey;
+import com.ardor3d.util.TextureManager;
+import com.ardor3d.util.geom.BufferUtils;
+import com.ardor3d.util.stat.StatCollector;
+import com.ardor3d.util.stat.StatType;
+
+public class JoglTextureStateUtil {
+ private static final Logger logger = Logger.getLogger(JoglTextureStateUtil.class.getName());
+
+ public final static void load(final Texture texture, final int unit) {
+ if (texture == null) {
+ return;
+ }
+
+ final GL gl = GLU.getCurrentGL();
+ final RenderContext context = ContextManager.getCurrentContext();
+ if (context == null) {
+ logger.warning("RenderContext is null for texture: " + texture);
+ return;
+ }
+
+ final ContextCapabilities caps = context.getCapabilities();
+ final TextureStateRecord record = (TextureStateRecord) context.getStateRecord(StateType.Texture);
+
+ // Check we are in the right unit
+ if (record != null) {
+ checkAndSetUnit(unit, record, caps);
+ }
+
+ // Create the texture...
+ if (texture.getTextureKey() != null) {
+
+ // Look for a texture in the cache just like ours
+ final TextureKey texKey = texture.getTextureKey();
+ final Texture cached = TextureManager.findCachedTexture(texKey);
+
+ if (cached == null) {
+ TextureManager.addToCache(texture);
+ } else {
+ final int textureId = cached.getTextureIdForContext(context.getGlContextRep());
+ if (textureId != 0) {
+ doTextureBind(cached, unit, false);
+ return;
+ }
+ }
+ }
+
+ final IntBuffer id = BufferUtils.createIntBuffer(1);
+ id.clear();
+ gl.glGenTextures(id.limit(), id);
+ final int textureId = id.get(0);
+
+ // store the new id by our current gl context.
+ texture.setTextureIdForContext(context.getGlContextRep(), textureId);
+
+ update(texture, unit);
+ }
+
+ /**
+ * bind texture and upload image data to card
+ */
+ public static void update(final Texture texture, final int unit) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+
+ texture.getTextureKey().setClean(context.getGlContextRep());
+
+ // our texture type:
+ final Texture.Type type = texture.getType();
+
+ final GL gl = GLU.getCurrentGL();
+ final GLU glu = new GLUgl2();
+
+ // bind our texture id to this unit.
+ doTextureBind(texture, unit, false);
+
+ // pass image data to OpenGL
+ final Image image = texture.getImage();
+ final boolean hasBorder = texture.hasBorder();
+ if (image == null) {
+ logger.warning("Image data for texture is null.");
+ }
+
+ // set alignment to support images with width % 4 != 0, as images are
+ // not aligned
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
+
+ // Get texture image data. Not all textures have image data.
+ // For example, ApplyMode.Combine modes can use primary colors,
+ // texture output, and constants to modify fragments via the
+ // texture units.
+ if (image != null) {
+ final int maxSize = caps.getMaxTextureSize();
+ final int actualWidth = image.getWidth();
+ final int actualHeight = image.getHeight();
+
+ final boolean needsPowerOfTwo = !caps.isNonPowerOfTwoTextureSupported()
+ && (!MathUtils.isPowerOfTwo(image.getWidth()) || !MathUtils.isPowerOfTwo(image.getHeight()));
+ if (actualWidth > maxSize || actualHeight > maxSize || needsPowerOfTwo) {
+ if (needsPowerOfTwo) {
+ logger.warning("(card unsupported) Attempted to apply texture with size that is not power of 2: "
+ + image.getWidth() + " x " + image.getHeight());
+ }
+ if (actualWidth > maxSize || actualHeight > maxSize) {
+ logger
+ .warning("(card unsupported) Attempted to apply texture with size bigger than max texture size ["
+ + maxSize + "]: " + image.getWidth() + " x " + image.getHeight());
+ }
+
+ int w = actualWidth;
+ if (needsPowerOfTwo) {
+ w = MathUtils.nearestPowerOfTwo(actualWidth);
+ }
+ if (w > maxSize) {
+ w = maxSize;
+ }
+
+ int h = actualHeight;
+ if (needsPowerOfTwo) {
+ h = MathUtils.nearestPowerOfTwo(actualHeight);
+ }
+ if (h > maxSize) {
+ h = maxSize;
+ }
+ logger.warning("Rescaling image to " + w + " x " + h + " !!!");
+
+ // must rescale image to get "top" mipmap texture image
+ final int pixFormat = JoglTextureUtil.getGLPixelFormat(image.getDataFormat());
+ final int pixDataType = JoglTextureUtil.getGLPixelDataType(image.getDataType());
+ final int bpp = ImageUtils.getPixelByteSize(image.getDataFormat(), image.getDataType());
+ final ByteBuffer scaledImage = BufferUtils.createByteBuffer((w + 4) * h * bpp);
+ final int error = glu.gluScaleImage(pixFormat, actualWidth, actualHeight, pixDataType,
+ image.getData(0), w, h, pixDataType, scaledImage);
+ if (error != 0) {
+ final int errorCode = gl.glGetError();
+ if (errorCode != GL.GL_NO_ERROR) {
+ throw new GLException(glu.gluErrorString(errorCode));
+ }
+ }
+
+ image.setWidth(w);
+ image.setHeight(h);
+ image.setData(scaledImage);
+ }
+
+ if (!texture.getMinificationFilter().usesMipMapLevels() && !texture.getTextureStoreFormat().isCompressed()) {
+
+ // Load textures which do not need mipmap auto-generating and
+ // which aren't using compressed images.
+
+ switch (texture.getType()) {
+ case TwoDimensional:
+ // ensure the buffer is ready for reading
+ image.getData(0).rewind();
+ // send top level to card
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), image.getWidth(), image.getHeight(), hasBorder ? 1 : 0,
+ JoglTextureUtil.getGLPixelFormat(image.getDataFormat()), JoglTextureUtil
+ .getGLPixelDataType(image.getDataType()), image.getData(0));
+ break;
+ case OneDimensional:
+ // ensure the buffer is ready for reading
+ image.getData(0).rewind();
+ // send top level to card
+ gl.getGL2GL3().glTexImage1D(GL2GL3.GL_TEXTURE_1D, 0, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), image.getWidth(), hasBorder ? 1 : 0, JoglTextureUtil
+ .getGLPixelFormat(image.getDataFormat()), JoglTextureUtil.getGLPixelDataType(image
+ .getDataType()), image.getData(0));
+ break;
+ case ThreeDimensional:
+ if (caps.isTexture3DSupported()) {
+ // concat data into single buffer:
+ int dSize = 0;
+ int count = 0;
+ ByteBuffer data = null;
+ for (int x = 0; x < image.getData().size(); x++) {
+ if (image.getData(x) != null) {
+ data = image.getData(x);
+ dSize += data.limit();
+ count++;
+ }
+ }
+ // reuse buffer if we can.
+ if (count != 1) {
+ data = BufferUtils.createByteBuffer(dSize);
+ for (int x = 0; x < image.getData().size(); x++) {
+ if (image.getData(x) != null) {
+ data.put(image.getData(x));
+ }
+ }
+ // ensure the buffer is ready for reading
+ data.flip();
+ }
+ // send top level to card
+ gl.getGL2GL3().glTexImage3D(GL2.GL_TEXTURE_3D, 0, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), image.getWidth(), image.getHeight(), image.getDepth(),
+ hasBorder ? 1 : 0, JoglTextureUtil.getGLPixelFormat(image.getDataFormat()),
+ JoglTextureUtil.getGLPixelDataType(image.getDataType()), data);
+ } else {
+ logger.warning("This card does not support Texture3D.");
+ }
+ break;
+ case CubeMap:
+ // NOTE: Cubemaps MUST be square, so height is ignored
+ // on purpose.
+ if (caps.isTextureCubeMapSupported()) {
+ for (final TextureCubeMap.Face face : TextureCubeMap.Face.values()) {
+ // ensure the buffer is ready for reading
+ image.getData(face.ordinal()).rewind();
+ // send top level to card
+ gl.glTexImage2D(getGLCubeMapFace(face), 0, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), image.getWidth(), image.getWidth(), hasBorder ? 1
+ : 0, JoglTextureUtil.getGLPixelFormat(image.getDataFormat()), JoglTextureUtil
+ .getGLPixelDataType(image.getDataType()), image.getData(face.ordinal()));
+ }
+ } else {
+ logger.warning("This card does not support Cubemaps.");
+ }
+ break;
+ case Rectangle:
+ break;
+ default:
+ break;
+ }
+ } else if (texture.getMinificationFilter().usesMipMapLevels() && !image.hasMipmaps()
+ && !texture.getTextureStoreFormat().isCompressed()) {
+
+ // For textures which need mipmaps auto-generating and which
+ // aren't using compressed images, generate the mipmaps.
+ // A new mipmap builder may be needed to build mipmaps for
+ // compressed textures.
+
+ if (caps.isAutomaticMipmapsSupported()) {
+ // Flag the card to generate mipmaps
+ gl.glTexParameteri(getGLType(type), GL2ES1.GL_GENERATE_MIPMAP, GL.GL_TRUE);
+ }
+
+ switch (type) {
+ case TwoDimensional:
+ // ensure the buffer is ready for reading
+ image.getData(0).rewind();
+ if (caps.isAutomaticMipmapsSupported()) {
+ // send top level to card
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), image.getWidth(), image.getHeight(), hasBorder ? 1 : 0,
+ JoglTextureUtil.getGLPixelFormat(image.getDataFormat()), JoglTextureUtil
+ .getGLPixelDataType(image.getDataType()), image.getData(0));
+ } else {
+ // send to card
+ glu.gluBuild2DMipmaps(GL.GL_TEXTURE_2D, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), image.getWidth(), image.getHeight(), JoglTextureUtil
+ .getGLPixelFormat(image.getDataFormat()), JoglTextureUtil.getGLPixelDataType(image
+ .getDataType()), image.getData(0));
+ }
+ break;
+ case OneDimensional:
+ // ensure the buffer is ready for reading
+ image.getData(0).rewind();
+ if (caps.isAutomaticMipmapsSupported()) {
+ // send top level to card
+ gl.getGL2GL3().glTexImage1D(GL2GL3.GL_TEXTURE_1D, 0, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), image.getWidth(), hasBorder ? 1 : 0, JoglTextureUtil
+ .getGLPixelFormat(image.getDataFormat()), JoglTextureUtil.getGLPixelDataType(image
+ .getDataType()), image.getData(0));
+ } else {
+ // Note: JOGL's GLU class does not support
+ // gluBuild1DMipmaps.
+ logger
+ .warning("non-fbo 1d mipmap generation is not currently supported. Use DDS or a non-mipmap minification filter.");
+ return;
+ }
+ break;
+ case ThreeDimensional:
+ if (caps.isTexture3DSupported()) {
+ if (caps.isAutomaticMipmapsSupported()) {
+ // concat data into single buffer:
+ int dSize = 0;
+ int count = 0;
+ ByteBuffer data = null;
+ for (int x = 0; x < image.getData().size(); x++) {
+ if (image.getData(x) != null) {
+ data = image.getData(x);
+ dSize += data.limit();
+ count++;
+ }
+ }
+ // reuse buffer if we can.
+ if (count != 1) {
+ data = BufferUtils.createByteBuffer(dSize);
+ for (int x = 0; x < image.getData().size(); x++) {
+ if (image.getData(x) != null) {
+ data.put(image.getData(x));
+ }
+ }
+ // ensure the buffer is ready for reading
+ data.flip();
+ }
+ // send top level to card
+ gl.getGL2GL3().glTexImage3D(GL2ES2.GL_TEXTURE_3D, 0, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), image.getWidth(), image.getHeight(), image
+ .getDepth(), hasBorder ? 1 : 0, JoglTextureUtil.getGLPixelFormat(image
+ .getDataFormat()), JoglTextureUtil.getGLPixelDataType(image.getDataType()),
+ data);
+ } else {
+ // Note: JOGL's GLU class does not support
+ // gluBuild3DMipmaps.
+ logger
+ .warning("non-fbo 3d mipmap generation is not currently supported. Use DDS or a non-mipmap minification filter.");
+ return;
+ }
+ } else {
+ logger.warning("This card does not support Texture3D.");
+ return;
+ }
+ break;
+ case CubeMap:
+ // NOTE: Cubemaps MUST be square, so height is ignored
+ // on purpose.
+ if (caps.isTextureCubeMapSupported()) {
+ if (caps.isAutomaticMipmapsSupported()) {
+ for (final TextureCubeMap.Face face : TextureCubeMap.Face.values()) {
+ // ensure the buffer is ready for reading
+ image.getData(face.ordinal()).rewind();
+ // send top level to card
+ gl.glTexImage2D(getGLCubeMapFace(face), 0, JoglTextureUtil
+ .getGLInternalFormat(texture.getTextureStoreFormat()), image.getWidth(),
+ image.getWidth(), hasBorder ? 1 : 0, JoglTextureUtil.getGLPixelFormat(image
+ .getDataFormat()), JoglTextureUtil.getGLPixelDataType(image
+ .getDataType()), image.getData(face.ordinal()));
+ }
+ } else {
+ for (final TextureCubeMap.Face face : TextureCubeMap.Face.values()) {
+ // ensure the buffer is ready for reading
+ image.getData(face.ordinal()).rewind();
+ // send to card
+ glu.gluBuild2DMipmaps(getGLCubeMapFace(face), JoglTextureUtil
+ .getGLInternalFormat(texture.getTextureStoreFormat()), image.getWidth(),
+ image.getWidth(), JoglTextureUtil.getGLPixelFormat(image.getDataFormat()),
+ JoglTextureUtil.getGLPixelDataType(image.getDataType()), image.getData(face
+ .ordinal()));
+ }
+ }
+ } else {
+ logger.warning("This card does not support Cubemaps.");
+ return;
+ }
+ break;
+ case Rectangle:
+ break;
+ default:
+ break;
+ }
+
+ if (texture.getTextureMaxLevel() >= 0) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MAX_LEVEL, texture.getTextureMaxLevel());
+ }
+ } else {
+ // Here we handle textures that are either compressed or have predefined mipmaps.
+ // Get mipmap data sizes and amount of mipmaps to send to opengl. Then loop through all mipmaps and send
+ // them.
+ int[] mipSizes = image.getMipMapByteSizes();
+ ByteBuffer data = null;
+ if (type == Type.CubeMap) {
+ if (caps.isTextureCubeMapSupported()) {
+ for (final TextureCubeMap.Face face : TextureCubeMap.Face.values()) {
+ data = image.getData(face.ordinal());
+ int pos = 0;
+ int max = 1;
+
+ if (mipSizes == null) {
+ mipSizes = new int[] { data.capacity() };
+ } else if (texture.getMinificationFilter().usesMipMapLevels()) {
+ max = mipSizes.length;
+ }
+
+ // set max mip level
+ gl.glTexParameteri(getGLCubeMapFace(face), GL2.GL_TEXTURE_MAX_LEVEL, max - 1);
+
+ for (int m = 0; m < max; m++) {
+ final int width = Math.max(1, image.getWidth() >> m);
+ final int height = Math.max(1, image.getHeight() >> m);
+
+ data.position(pos);
+ data.limit(pos + mipSizes[m]);
+
+ if (texture.getTextureStoreFormat().isCompressed()) {
+ gl.glCompressedTexImage2D(getGLCubeMapFace(face), m, JoglTextureUtil
+ .getGLInternalFormat(texture.getTextureStoreFormat()), width, height,
+ hasBorder ? 1 : 0, mipSizes[m], data);
+ } else {
+ gl.glTexImage2D(getGLCubeMapFace(face), m, JoglTextureUtil
+ .getGLInternalFormat(texture.getTextureStoreFormat()), width, height,
+ hasBorder ? 1 : 0, JoglTextureUtil.getGLPixelFormat(image.getDataFormat()),
+ JoglTextureUtil.getGLPixelDataType(image.getDataType()), data);
+ }
+ pos += mipSizes[m];
+ }
+ }
+ } else {
+ logger.warning("This card does not support CubeMaps.");
+ return;
+ }
+ } else {
+ data = image.getData(0);
+ int pos = 0;
+ int max = 1;
+
+ if (mipSizes == null) {
+ mipSizes = new int[] { data.capacity() };
+ } else if (texture.getMinificationFilter().usesMipMapLevels()) {
+ max = mipSizes.length;
+ }
+
+ // Set max mip level
+ switch (type) {
+ case TwoDimensional:
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MAX_LEVEL, max - 1);
+ break;
+ case ThreeDimensional:
+ gl.glTexParameteri(GL2ES2.GL_TEXTURE_3D, GL2GL3.GL_TEXTURE_MAX_LEVEL, max - 1);
+ break;
+ case OneDimensional:
+ gl.glTexParameteri(GL2GL3.GL_TEXTURE_1D, GL2GL3.GL_TEXTURE_MAX_LEVEL, max - 1);
+ break;
+ case CubeMap:
+ break;
+ case Rectangle:
+ break;
+ default:
+ break;
+ }
+
+ if (type == Type.ThreeDimensional) {
+ if (caps.isTexture3DSupported()) {
+ // concat data into single buffer:
+ int dSize = 0;
+ int count = 0;
+ for (int x = 0; x < image.getData().size(); x++) {
+ if (image.getData(x) != null) {
+ data = image.getData(x);
+ dSize += data.limit();
+ count++;
+ }
+ }
+ // reuse buffer if we can.
+ if (count != 1) {
+ data = BufferUtils.createByteBuffer(dSize);
+ for (int x = 0; x < image.getData().size(); x++) {
+ if (image.getData(x) != null) {
+ data.put(image.getData(x));
+ }
+ }
+ // ensure the buffer is ready for reading
+ data.flip();
+ }
+ } else {
+ logger.warning("This card does not support Texture3D.");
+ return;
+ }
+ }
+
+ for (int m = 0; m < max; m++) {
+ final int width = Math.max(1, image.getWidth() >> m);
+ final int height = Math.max(1, image.getHeight() >> m);
+
+ data.position(pos);
+ data.limit(pos + mipSizes[m]);
+
+ switch (type) {
+ case TwoDimensional:
+ if (texture.getTextureStoreFormat().isCompressed()) {
+ gl.glCompressedTexImage2D(GL.GL_TEXTURE_2D, m, JoglTextureUtil
+ .getGLInternalFormat(texture.getTextureStoreFormat()), width, height,
+ hasBorder ? 1 : 0, mipSizes[m], data);
+ } else {
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, m, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), width, height, hasBorder ? 1 : 0,
+ JoglTextureUtil.getGLPixelFormat(image.getDataFormat()), JoglTextureUtil
+ .getGLPixelDataType(image.getDataType()), data);
+ }
+ break;
+ case OneDimensional:
+ if (texture.getTextureStoreFormat().isCompressed()) {
+ gl.getGL2GL3().glCompressedTexImage1D(GL2GL3.GL_TEXTURE_1D, m, JoglTextureUtil
+ .getGLInternalFormat(texture.getTextureStoreFormat()), width, hasBorder ? 1
+ : 0, mipSizes[m], data);
+ } else {
+ gl.getGL2GL3().glTexImage1D(GL2GL3.GL_TEXTURE_1D, m, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), width, hasBorder ? 1 : 0, JoglTextureUtil
+ .getGLPixelFormat(image.getDataFormat()), JoglTextureUtil
+ .getGLPixelDataType(image.getDataType()), data);
+ }
+ break;
+ case ThreeDimensional:
+ final int depth = Math.max(1, image.getDepth() >> m);
+ // already checked for support above...
+ if (texture.getTextureStoreFormat().isCompressed()) {
+ gl.getGL2GL3().glCompressedTexImage3D(GL2ES2.GL_TEXTURE_3D, m, JoglTextureUtil
+ .getGLInternalFormat(texture.getTextureStoreFormat()), width, height,
+ depth, hasBorder ? 1 : 0, mipSizes[m], data);
+ } else {
+ gl.getGL2GL3().glTexImage3D(GL2ES2.GL_TEXTURE_3D, m, JoglTextureUtil.getGLInternalFormat(texture
+ .getTextureStoreFormat()), width, height, depth, hasBorder ? 1 : 0,
+ JoglTextureUtil.getGLPixelFormat(image.getDataFormat()), JoglTextureUtil
+ .getGLPixelDataType(image.getDataType()), data);
+ }
+ break;
+ case CubeMap:
+ break;
+ case Rectangle:
+ break;
+ default:
+ break;
+ }
+
+ pos += mipSizes[m];
+ }
+ }
+ if (data != null) {
+ data.clear();
+ }
+ }
+ }
+ }
+
+ public static void apply(final JoglRenderer renderer, final TextureState state) {
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+ final TextureStateRecord record = (TextureStateRecord) context.getStateRecord(StateType.Texture);
+ context.setCurrentState(StateType.Texture, state);
+
+ if (state.isEnabled()) {
+
+ Texture texture;
+ Texture.Type type;
+ TextureUnitRecord unitRecord;
+ TextureRecord texRecord;
+
+ final int glHint = JoglTextureUtil.getPerspHint(state.getCorrectionType());
+ if (!record.isValid() || record.hint != glHint) {
+ // set up correction mode
+ gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, glHint);
+ record.hint = glHint;
+ }
+
+ // loop through all available texture units...
+ for (int i = 0; i < caps.getNumberOfTotalTextureUnits(); i++) {
+ unitRecord = record.units[i];
+
+ // grab a texture for this unit, if available
+ texture = state.getTexture(i);
+
+ // pull our texture id for this texture, for this context.
+ int textureId = texture != null ? texture.getTextureIdForContext(context.getGlContextRep()) : 0;
+
+ // check for invalid textures - ones that have no opengl id and
+ // no image data
+ if (texture != null && textureId == 0 && texture.getImage() == null) {
+ texture = null;
+ }
+
+ // null textures above fixed limit do not need to be disabled
+ // since they are not really part of the pipeline.
+ if (texture == null) {
+ if (i >= caps.getNumberOfFixedTextureUnits()) {
+ continue;
+ } else {
+ // a null texture indicates no texturing at this unit
+ // Disable texturing on this unit if enabled.
+ disableTexturing(unitRecord, record, i, caps);
+
+ if (i < state._keyCache.length) {
+ state._keyCache[i] = null;
+ }
+
+ // next texture!
+ continue;
+ }
+ }
+
+ type = texture.getType();
+
+ // disable other texturing types for this unit, if enabled.
+ disableTexturing(unitRecord, record, i, type, caps);
+
+ // Time to bind the texture, so see if we need to load in image
+ // data for this texture.
+ if (textureId == 0) {
+ // texture not yet loaded.
+ // this will load and bind and set the records...
+ load(texture, i);
+ textureId = texture.getTextureIdForContext(context.getGlContextRep());
+ if (textureId == 0) {
+ continue;
+ }
+ } else if (texture.isDirty(context.getGlContextRep())) {
+ update(texture, i);
+ textureId = texture.getTextureIdForContext(context.getGlContextRep());
+ if (textureId == 0) {
+ continue;
+ }
+ } else {
+ // texture already exists in OpenGL, just bind it if needed
+ if (!unitRecord.isValid() || unitRecord.boundTexture != textureId) {
+ checkAndSetUnit(i, record, caps);
+ gl.glBindTexture(getGLType(type), textureId);
+ if (Constants.stats) {
+ StatCollector.addStat(StatType.STAT_TEXTURE_BINDS, 1);
+ }
+ unitRecord.boundTexture = textureId;
+ }
+ }
+
+ // Use the Java Integer object for the getTextureRecord call to avoid
+ // boxing/unboxing ints for map lookups.
+ final Integer textureIdInteger = texture.getTextureIdForContextAsInteger(context.getGlContextRep());
+
+ // Grab our record for this texture
+ texRecord = record.getTextureRecord(textureIdInteger, texture.getType());
+
+ // Set the keyCache value for this unit of this texture state
+ // This is done so during state comparison we don't have to
+ // spend a lot of time pulling out classes and finding field
+ // data.
+ state._keyCache[i] = texture.getTextureKey();
+
+ // Some texture things only apply to fixed function pipeline
+ if (i < caps.getNumberOfFixedTextureUnits()) {
+
+ // Enable 2D texturing on this unit if not enabled.
+ if (!unitRecord.isValid() || !unitRecord.enabled[type.ordinal()]) {
+ checkAndSetUnit(i, record, caps);
+ gl.glEnable(getGLType(type));
+ unitRecord.enabled[type.ordinal()] = true;
+ }
+
+ // Set our blend color, if needed.
+ applyBlendColor(texture, unitRecord, i, record, caps);
+
+ // Set the texture environment mode if this unit isn't
+ // already set properly
+ applyEnvMode(texture.getApply(), unitRecord, i, record, caps);
+
+ // If our mode is combine, and we support multitexturing
+ // apply combine settings.
+ if (texture.getApply() == ApplyMode.Combine && caps.isMultitextureSupported()
+ && caps.isEnvCombineSupported()) {
+ applyCombineFactors(texture, unitRecord, i, record, caps);
+ }
+ }
+
+ // Other items only apply to textures below the frag unit limit
+ if (i < caps.getNumberOfFragmentTextureUnits()) {
+
+ // texture specific params
+ applyFilter(texture, texRecord, i, record, caps);
+ applyWrap(texture, texRecord, i, record, caps);
+ applyShadow(texture, texRecord, i, record, caps);
+
+ // Set our border color, if needed.
+ applyBorderColor(texture, texRecord, i, record, caps);
+
+ // all states have now been applied for a tex record, so we
+ // can safely make it valid
+ if (!texRecord.isValid()) {
+ texRecord.validate();
+ }
+
+ }
+
+ // Other items only apply to textures below the frag tex coord
+ // unit limit
+ if (i < caps.getNumberOfFragmentTexCoordUnits()) {
+
+ // Now time to play with texture matrices
+ // Determine which transforms to do.
+ applyTextureTransforms(texture, i, record, caps);
+
+ // Now let's look at automatic texture coordinate
+ // generation.
+ applyTexCoordGeneration(texture, unitRecord, i, record, caps);
+
+ // Set our texture lod bias, if needed.
+ applyLodBias(texture, unitRecord, i, record, caps);
+ }
+
+ }
+
+ } else {
+ // turn off texturing
+ TextureUnitRecord unitRecord;
+
+ if (caps.isMultitextureSupported()) {
+ for (int i = 0; i < caps.getNumberOfFixedTextureUnits(); i++) {
+ unitRecord = record.units[i];
+ disableTexturing(unitRecord, record, i, caps);
+ }
+ } else {
+ unitRecord = record.units[0];
+ disableTexturing(unitRecord, record, 0, caps);
+ }
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void disableTexturing(final TextureUnitRecord unitRecord, final TextureStateRecord record,
+ final int unit, final Type exceptedType, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (exceptedType != Type.TwoDimensional) {
+ if (!unitRecord.isValid() || unitRecord.enabled[Type.TwoDimensional.ordinal()]) {
+ // Check we are in the right unit
+ checkAndSetUnit(unit, record, caps);
+ gl.glDisable(GL.GL_TEXTURE_2D);
+ unitRecord.enabled[Type.TwoDimensional.ordinal()] = false;
+ }
+ }
+
+ if (exceptedType != Type.OneDimensional) {
+ if (!unitRecord.isValid() || unitRecord.enabled[Type.OneDimensional.ordinal()]) {
+ // Check we are in the right unit
+ checkAndSetUnit(unit, record, caps);
+ gl.glDisable(GL2GL3.GL_TEXTURE_1D);
+ unitRecord.enabled[Type.OneDimensional.ordinal()] = false;
+ }
+ }
+
+ if (caps.isTexture3DSupported() && exceptedType != Type.ThreeDimensional) {
+ if (!unitRecord.isValid() || unitRecord.enabled[Type.ThreeDimensional.ordinal()]) {
+ // Check we are in the right unit
+ checkAndSetUnit(unit, record, caps);
+ gl.glDisable(GL2ES2.GL_TEXTURE_3D);
+ unitRecord.enabled[Type.ThreeDimensional.ordinal()] = false;
+ }
+ }
+
+ if (caps.isTextureCubeMapSupported() && exceptedType != Type.CubeMap) {
+ if (!unitRecord.isValid() || unitRecord.enabled[Type.CubeMap.ordinal()]) {
+ // Check we are in the right unit
+ checkAndSetUnit(unit, record, caps);
+ gl.glDisable(GL.GL_TEXTURE_CUBE_MAP);
+ unitRecord.enabled[Type.CubeMap.ordinal()] = false;
+ }
+ }
+
+ }
+
+ private static void disableTexturing(final TextureUnitRecord unitRecord, final TextureStateRecord record,
+ final int unit, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!unitRecord.isValid() || unitRecord.enabled[Type.TwoDimensional.ordinal()]) {
+ // Check we are in the right unit
+ checkAndSetUnit(unit, record, caps);
+ gl.glDisable(GL.GL_TEXTURE_2D);
+ unitRecord.enabled[Type.TwoDimensional.ordinal()] = false;
+ }
+
+ if (!unitRecord.isValid() || unitRecord.enabled[Type.OneDimensional.ordinal()]) {
+ // Check we are in the right unit
+ checkAndSetUnit(unit, record, caps);
+ gl.glDisable(GL2GL3.GL_TEXTURE_1D);
+ unitRecord.enabled[Type.OneDimensional.ordinal()] = false;
+ }
+
+ if (caps.isTexture3DSupported()) {
+ if (!unitRecord.isValid() || unitRecord.enabled[Type.ThreeDimensional.ordinal()]) {
+ // Check we are in the right unit
+ checkAndSetUnit(unit, record, caps);
+ gl.glDisable(GL2ES2.GL_TEXTURE_3D);
+ unitRecord.enabled[Type.ThreeDimensional.ordinal()] = false;
+ }
+ }
+
+ if (caps.isTextureCubeMapSupported()) {
+ if (!unitRecord.isValid() || unitRecord.enabled[Type.CubeMap.ordinal()]) {
+ // Check we are in the right unit
+ checkAndSetUnit(unit, record, caps);
+ gl.glDisable(GL.GL_TEXTURE_CUBE_MAP);
+ unitRecord.enabled[Type.CubeMap.ordinal()] = false;
+ }
+ }
+
+ }
+
+ public static void applyCombineFactors(final Texture texture, final TextureUnitRecord unitRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ // check that this is a valid fixed function unit. glTexEnv is only
+ // supported for unit < GL_MAX_TEXTURE_UNITS
+ if (unit >= caps.getNumberOfFixedTextureUnits()) {
+ return;
+ }
+
+ // first thing's first... if we are doing dot3 and don't
+ // support it, disable this texture.
+ boolean checked = false;
+ if (!caps.isEnvDot3TextureCombineSupported()
+ && (texture.getCombineFuncRGB() == CombinerFunctionRGB.Dot3RGB || texture.getCombineFuncRGB() == CombinerFunctionRGB.Dot3RGBA)) {
+
+ // disable
+ disableTexturing(unitRecord, record, unit, caps);
+
+ // No need to continue
+ return;
+ }
+
+ // Okay, now let's set our scales if we need to:
+ // First RGB Combine scale
+ if (!unitRecord.isValid() || unitRecord.envRGBScale != texture.getCombineScaleRGB()) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvf(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_RGB_SCALE, texture.getCombineScaleRGB().floatValue());
+ unitRecord.envRGBScale = texture.getCombineScaleRGB();
+ } // Then Alpha Combine scale
+ if (!unitRecord.isValid() || unitRecord.envAlphaScale != texture.getCombineScaleAlpha()) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvf(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_ALPHA_SCALE, texture.getCombineScaleAlpha().floatValue());
+ unitRecord.envAlphaScale = texture.getCombineScaleAlpha();
+ }
+
+ // Time to set the RGB combines
+ final CombinerFunctionRGB rgbCombineFunc = texture.getCombineFuncRGB();
+ if (!unitRecord.isValid() || unitRecord.rgbCombineFunc != rgbCombineFunc) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_COMBINE_RGB, JoglTextureUtil.getGLCombineFuncRGB(rgbCombineFunc));
+ unitRecord.rgbCombineFunc = rgbCombineFunc;
+ }
+
+ CombinerSource combSrcRGB = texture.getCombineSrc0RGB();
+ if (!unitRecord.isValid() || unitRecord.combSrcRGB0 != combSrcRGB) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2.GL_SOURCE0_RGB, JoglTextureUtil.getGLCombineSrc(combSrcRGB));
+ unitRecord.combSrcRGB0 = combSrcRGB;
+ }
+
+ CombinerOperandRGB combOpRGB = texture.getCombineOp0RGB();
+ if (!unitRecord.isValid() || unitRecord.combOpRGB0 != combOpRGB) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_OPERAND0_RGB, JoglTextureUtil.getGLCombineOpRGB(combOpRGB));
+ unitRecord.combOpRGB0 = combOpRGB;
+ }
+
+ // We only need to do Arg1 or Arg2 if we aren't in Replace mode
+ if (rgbCombineFunc != CombinerFunctionRGB.Replace) {
+
+ combSrcRGB = texture.getCombineSrc1RGB();
+ if (!unitRecord.isValid() || unitRecord.combSrcRGB1 != combSrcRGB) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2.GL_SOURCE1_RGB, JoglTextureUtil.getGLCombineSrc(combSrcRGB));
+ unitRecord.combSrcRGB1 = combSrcRGB;
+ }
+
+ combOpRGB = texture.getCombineOp1RGB();
+ if (!unitRecord.isValid() || unitRecord.combOpRGB1 != combOpRGB) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_OPERAND1_RGB, JoglTextureUtil.getGLCombineOpRGB(combOpRGB));
+ unitRecord.combOpRGB1 = combOpRGB;
+ }
+
+ // We only need to do Arg2 if we are in Interpolate mode
+ if (rgbCombineFunc == CombinerFunctionRGB.Interpolate) {
+
+ combSrcRGB = texture.getCombineSrc2RGB();
+ if (!unitRecord.isValid() || unitRecord.combSrcRGB2 != combSrcRGB) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2.GL_SOURCE2_RGB, JoglTextureUtil.getGLCombineSrc(combSrcRGB));
+ unitRecord.combSrcRGB2 = combSrcRGB;
+ }
+
+ combOpRGB = texture.getCombineOp2RGB();
+ if (!unitRecord.isValid() || unitRecord.combOpRGB2 != combOpRGB) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_OPERAND2_RGB, JoglTextureUtil.getGLCombineOpRGB(combOpRGB));
+ unitRecord.combOpRGB2 = combOpRGB;
+ }
+
+ }
+ }
+
+ // Now Alpha combines
+ final CombinerFunctionAlpha alphaCombineFunc = texture.getCombineFuncAlpha();
+ if (!unitRecord.isValid() || unitRecord.alphaCombineFunc != alphaCombineFunc) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_COMBINE_ALPHA, JoglTextureUtil
+ .getGLCombineFuncAlpha(alphaCombineFunc));
+ unitRecord.alphaCombineFunc = alphaCombineFunc;
+ }
+
+ CombinerSource combSrcAlpha = texture.getCombineSrc0Alpha();
+ if (!unitRecord.isValid() || unitRecord.combSrcAlpha0 != combSrcAlpha) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2.GL_SOURCE0_ALPHA, JoglTextureUtil.getGLCombineSrc(combSrcAlpha));
+ unitRecord.combSrcAlpha0 = combSrcAlpha;
+ }
+
+ CombinerOperandAlpha combOpAlpha = texture.getCombineOp0Alpha();
+ if (!unitRecord.isValid() || unitRecord.combOpAlpha0 != combOpAlpha) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_OPERAND0_ALPHA, JoglTextureUtil.getGLCombineOpAlpha(combOpAlpha));
+ unitRecord.combOpAlpha0 = combOpAlpha;
+ }
+
+ // We only need to do Arg1 or Arg2 if we aren't in Replace mode
+ if (alphaCombineFunc != CombinerFunctionAlpha.Replace) {
+
+ combSrcAlpha = texture.getCombineSrc1Alpha();
+ if (!unitRecord.isValid() || unitRecord.combSrcAlpha1 != combSrcAlpha) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2.GL_SOURCE1_ALPHA, JoglTextureUtil.getGLCombineSrc(combSrcAlpha));
+ unitRecord.combSrcAlpha1 = combSrcAlpha;
+ }
+
+ combOpAlpha = texture.getCombineOp1Alpha();
+ if (!unitRecord.isValid() || unitRecord.combOpAlpha1 != combOpAlpha) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_OPERAND1_ALPHA, JoglTextureUtil.getGLCombineOpAlpha(combOpAlpha));
+ unitRecord.combOpAlpha1 = combOpAlpha;
+ }
+
+ // We only need to do Arg2 if we are in Interpolate mode
+ if (alphaCombineFunc == CombinerFunctionAlpha.Interpolate) {
+
+ combSrcAlpha = texture.getCombineSrc2Alpha();
+ if (!unitRecord.isValid() || unitRecord.combSrcAlpha2 != combSrcAlpha) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2.GL_SOURCE2_ALPHA, JoglTextureUtil.getGLCombineSrc(combSrcAlpha));
+ unitRecord.combSrcAlpha2 = combSrcAlpha;
+ }
+
+ combOpAlpha = texture.getCombineOp2Alpha();
+ if (!unitRecord.isValid() || unitRecord.combOpAlpha2 != combOpAlpha) {
+ if (!checked) {
+ checkAndSetUnit(unit, record, caps);
+ checked = true;
+ }
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_OPERAND2_ALPHA, JoglTextureUtil
+ .getGLCombineOpAlpha(combOpAlpha));
+ unitRecord.combOpAlpha2 = combOpAlpha;
+ }
+ }
+ }
+ }
+
+ public static void applyEnvMode(final ApplyMode mode, final TextureUnitRecord unitRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!unitRecord.isValid() || unitRecord.envMode != mode) {
+ checkAndSetUnit(unit, record, caps);
+ gl.getGL2ES1().glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_TEXTURE_ENV_MODE, JoglTextureUtil.getGLEnvMode(mode));
+ unitRecord.envMode = mode;
+ }
+ }
+
+ public static void applyBlendColor(final Texture texture, final TextureUnitRecord unitRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ final ReadOnlyColorRGBA texBlend = texture.getConstantColor();
+ if (!unitRecord.isValid() || !unitRecord.blendColor.equals(texBlend)) {
+ checkAndSetUnit(unit, record, caps);
+ TextureRecord.colorBuffer.clear();
+ TextureRecord.colorBuffer.put(texBlend.getRed()).put(texBlend.getGreen()).put(texBlend.getBlue()).put(
+ texBlend.getAlpha());
+ TextureRecord.colorBuffer.rewind();
+ gl.getGL2ES1().glTexEnvfv(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_TEXTURE_ENV_COLOR, TextureRecord.colorBuffer);
+ unitRecord.blendColor.set(texBlend);
+ }
+ }
+
+ public static void applyLodBias(final Texture texture, final TextureUnitRecord unitRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (caps.isTextureLodBiasSupported()) {
+ final float bias = texture.getLodBias() < caps.getMaxLodBias() ? texture.getLodBias() : caps
+ .getMaxLodBias();
+ if (!unitRecord.isValid() || unitRecord.lodBias != bias) {
+ checkAndSetUnit(unit, record, caps);
+ gl.getGL2ES1().glTexEnvf(GL2.GL_TEXTURE_FILTER_CONTROL, GL2GL3.GL_TEXTURE_LOD_BIAS, bias);
+ unitRecord.lodBias = bias;
+ }
+ }
+ }
+
+ public static void applyBorderColor(final Texture texture, final TextureRecord texRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ final ReadOnlyColorRGBA texBorder = texture.getBorderColor();
+ if (!texRecord.isValid() || !texRecord.borderColor.equals(texBorder)) {
+ TextureRecord.colorBuffer.clear();
+ TextureRecord.colorBuffer.put(texBorder.getRed()).put(texBorder.getGreen()).put(texBorder.getBlue()).put(
+ texBorder.getAlpha());
+ TextureRecord.colorBuffer.rewind();
+ gl.glTexParameterfv(getGLType(texture.getType()), GL2GL3.GL_TEXTURE_BORDER_COLOR, TextureRecord.colorBuffer);
+ texRecord.borderColor.set(texBorder);
+ }
+ }
+
+ public static void applyTextureTransforms(final Texture texture, final int unit, final TextureStateRecord record,
+ final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ final boolean needsReset = !record.units[unit].identityMatrix;
+
+ // Should we apply the transform?
+ final boolean doTrans = !texture.getTextureMatrix().isIdentity();
+
+ // Now do them.
+ final RendererRecord matRecord = ContextManager.getCurrentContext().getRendererRecord();
+ if (doTrans) {
+ checkAndSetUnit(unit, record, caps);
+ JoglRendererUtil.switchMode(matRecord, GL.GL_TEXTURE);
+
+ record.tmp_matrixBuffer.rewind();
+ texture.getTextureMatrix().toDoubleBuffer(record.tmp_matrixBuffer, true);
+ record.tmp_matrixBuffer.rewind();
+ gl.getGL2().glLoadMatrixd(record.tmp_matrixBuffer);
+
+ record.units[unit].identityMatrix = false;
+ } else if (needsReset) {
+ checkAndSetUnit(unit, record, caps);
+ JoglRendererUtil.switchMode(matRecord, GL.GL_TEXTURE);
+ gl.getGL2().glLoadIdentity();
+ record.units[unit].identityMatrix = true;
+ }
+ // Switch back to the modelview matrix for further operations
+ JoglRendererUtil.switchMode(matRecord, GLMatrixFunc.GL_MODELVIEW);
+ }
+
+ public static void applyTexCoordGeneration(final Texture texture, final TextureUnitRecord unitRecord,
+ final int unit, final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ switch (texture.getEnvironmentalMapMode()) {
+ case None:
+ // No coordinate generation
+ setTextureGen(unitRecord, unit, record, caps, false, false, false, false);
+ break;
+ case SphereMap:
+ // generate spherical texture coordinates
+ if (!unitRecord.isValid() || unitRecord.textureGenSMode != GL2.GL_SPHERE_MAP) {
+ checkAndSetUnit(unit, record, caps);
+
+ gl.getGL2().glTexGeni(GL2.GL_S, GL2ES1.GL_TEXTURE_GEN_MODE, GL2.GL_SPHERE_MAP);
+ unitRecord.textureGenSMode = GL2.GL_SPHERE_MAP;
+
+ gl.getGL2().glTexGeni(GL2.GL_T, GL2ES1.GL_TEXTURE_GEN_MODE, GL2.GL_SPHERE_MAP);
+ unitRecord.textureGenTMode = GL2.GL_SPHERE_MAP;
+ }
+
+ setTextureGen(unitRecord, unit, record, caps, true, true, false, false);
+ break;
+ case NormalMap:
+ // generate normals based texture coordinates
+ if (!unitRecord.isValid() || unitRecord.textureGenSMode != GL2ES1.GL_NORMAL_MAP) {
+ checkAndSetUnit(unit, record, caps);
+ gl.getGL2().glTexGeni(GL2.GL_S, GL2ES1.GL_TEXTURE_GEN_MODE, GL2ES1.GL_NORMAL_MAP);
+ unitRecord.textureGenSMode = GL2ES1.GL_NORMAL_MAP;
+
+ gl.getGL2().glTexGeni(GL2.GL_T, GL2ES1.GL_TEXTURE_GEN_MODE, GL2ES1.GL_NORMAL_MAP);
+ unitRecord.textureGenTMode = GL2ES1.GL_NORMAL_MAP;
+
+ gl.getGL2().glTexGeni(GL2.GL_R, GL2ES1.GL_TEXTURE_GEN_MODE, GL2ES1.GL_NORMAL_MAP);
+ unitRecord.textureGenRMode = GL2ES1.GL_NORMAL_MAP;
+ }
+
+ setTextureGen(unitRecord, unit, record, caps, true, true, true, false);
+ break;
+ case ReflectionMap:
+ // generate reflection texture coordinates
+ if (!unitRecord.isValid() || unitRecord.textureGenSMode != GL2ES1.GL_REFLECTION_MAP) {
+ checkAndSetUnit(unit, record, caps);
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_S, GL2ES1.GL_TEXTURE_GEN_MODE, GL2ES1.GL_REFLECTION_MAP);
+ unitRecord.textureGenSMode = GL2ES1.GL_REFLECTION_MAP;
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_T, GL2ES1.GL_TEXTURE_GEN_MODE, GL2ES1.GL_REFLECTION_MAP);
+ unitRecord.textureGenTMode = GL2ES1.GL_REFLECTION_MAP;
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_R, GL2ES1.GL_TEXTURE_GEN_MODE, GL2ES1.GL_REFLECTION_MAP);
+ unitRecord.textureGenRMode = GL2ES1.GL_REFLECTION_MAP;
+ }
+
+ setTextureGen(unitRecord, unit, record, caps, true, true, true, false);
+ break;
+ case EyeLinear:
+ // do here because we don't check planes
+ checkAndSetUnit(unit, record, caps);
+
+ // generate eye linear texture coordinates
+ if (!unitRecord.isValid() || unitRecord.textureGenSMode != GL2.GL_EYE_LINEAR) {
+ gl.getGL2ES1().glTexGeni(GL2.GL_S, GL2ES1.GL_TEXTURE_GEN_MODE, GL2.GL_EYE_LINEAR);
+ unitRecord.textureGenSMode = GL2.GL_EYE_LINEAR;
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_T, GL2ES1.GL_TEXTURE_GEN_MODE, GL2.GL_EYE_LINEAR);
+ unitRecord.textureGenTMode = GL2.GL_EYE_LINEAR;
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_R, GL2ES1.GL_TEXTURE_GEN_MODE, GL2.GL_EYE_LINEAR);
+ unitRecord.textureGenRMode = GL2.GL_EYE_LINEAR;
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_Q, GL2ES1.GL_TEXTURE_GEN_MODE, GL2.GL_EYE_LINEAR);
+ unitRecord.textureGenQMode = GL2.GL_EYE_LINEAR;
+ }
+
+ record.prepPlane(texture.getEnvPlaneS(), TextureStateRecord.DEFAULT_S_PLANE);
+ gl.getGL2ES1().glTexGenfv(GL2.GL_S, GL2.GL_EYE_PLANE, record.plane);
+ record.prepPlane(texture.getEnvPlaneT(), TextureStateRecord.DEFAULT_T_PLANE);
+ gl.getGL2ES1().glTexGenfv(GL2.GL_T, GL2.GL_EYE_PLANE, record.plane);
+ record.prepPlane(texture.getEnvPlaneR(), TextureStateRecord.DEFAULT_R_PLANE);
+ gl.getGL2ES1().glTexGenfv(GL2.GL_R, GL2.GL_EYE_PLANE, record.plane);
+ record.prepPlane(texture.getEnvPlaneQ(), TextureStateRecord.DEFAULT_Q_PLANE);
+ gl.getGL2ES1().glTexGenfv(GL2.GL_Q, GL2.GL_EYE_PLANE, record.plane);
+
+ setTextureGen(unitRecord, unit, record, caps, true, true, true, true);
+ break;
+ case ObjectLinear:
+ // do here because we don't check planes
+ checkAndSetUnit(unit, record, caps);
+
+ // generate object linear texture coordinates
+ if (!unitRecord.isValid() || unitRecord.textureGenSMode != GL2.GL_OBJECT_LINEAR) {
+ gl.getGL2ES1().glTexGeni(GL2.GL_S, GL2ES1.GL_TEXTURE_GEN_MODE, GL2.GL_OBJECT_LINEAR);
+ unitRecord.textureGenSMode = GL2.GL_OBJECT_LINEAR;
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_T, GL2.GL_TEXTURE_GEN_MODE, GL2.GL_OBJECT_LINEAR);
+ unitRecord.textureGenTMode = GL2.GL_OBJECT_LINEAR;
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_R, GL2.GL_TEXTURE_GEN_MODE, GL2.GL_OBJECT_LINEAR);
+ unitRecord.textureGenRMode = GL2.GL_OBJECT_LINEAR;
+
+ gl.getGL2ES1().glTexGeni(GL2.GL_Q, GL2.GL_TEXTURE_GEN_MODE, GL2.GL_OBJECT_LINEAR);
+ unitRecord.textureGenQMode = GL2.GL_OBJECT_LINEAR;
+ }
+
+ record.prepPlane(texture.getEnvPlaneS(), TextureStateRecord.DEFAULT_S_PLANE);
+ gl.getGL2ES1().glTexGenfv(GL2.GL_S, GL2.GL_OBJECT_PLANE, record.plane);
+ record.prepPlane(texture.getEnvPlaneT(), TextureStateRecord.DEFAULT_T_PLANE);
+ gl.getGL2ES1().glTexGenfv(GL2.GL_T, GL2.GL_OBJECT_PLANE, record.plane);
+ record.prepPlane(texture.getEnvPlaneR(), TextureStateRecord.DEFAULT_R_PLANE);
+ gl.getGL2ES1().glTexGenfv(GL2.GL_R, GL2.GL_OBJECT_PLANE, record.plane);
+ record.prepPlane(texture.getEnvPlaneQ(), TextureStateRecord.DEFAULT_Q_PLANE);
+ gl.getGL2ES1().glTexGenfv(GL2.GL_Q, GL2.GL_OBJECT_PLANE, record.plane);
+
+ setTextureGen(unitRecord, unit, record, caps, true, true, true, true);
+ break;
+ }
+ }
+
+ private static void setTextureGen(final TextureUnitRecord unitRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps, final boolean genS, final boolean genT,
+ final boolean genR, final boolean genQ) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!unitRecord.isValid()) {
+ checkAndSetUnit(unit, record, caps);
+
+ if (genS) {
+ gl.glEnable(GL2.GL_TEXTURE_GEN_S);
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_S);
+ }
+ if (genT) {
+ gl.glEnable(GL2.GL_TEXTURE_GEN_T);
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_T);
+ }
+ if (genR) {
+ gl.glEnable(GL2.GL_TEXTURE_GEN_R);
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_R);
+ }
+ if (genQ) {
+ gl.glEnable(GL2.GL_TEXTURE_GEN_Q);
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_Q);
+ }
+ } else {
+ if (genS != unitRecord.textureGenS) {
+ checkAndSetUnit(unit, record, caps);
+ if (genS) {
+ gl.glEnable(GL2.GL_TEXTURE_GEN_S);
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_S);
+ }
+ }
+ if (genT != unitRecord.textureGenT) {
+ checkAndSetUnit(unit, record, caps);
+ if (genT) {
+ gl.glEnable(GL2.GL_TEXTURE_GEN_T);
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_T);
+ }
+ }
+ if (genR != unitRecord.textureGenR) {
+ checkAndSetUnit(unit, record, caps);
+ if (genR) {
+ gl.glEnable(GL2.GL_TEXTURE_GEN_R);
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_R);
+ }
+ }
+ if (genQ != unitRecord.textureGenQ) {
+ checkAndSetUnit(unit, record, caps);
+ if (genQ) {
+ gl.glEnable(GL2.GL_TEXTURE_GEN_Q);
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_Q);
+ }
+ }
+ }
+
+ unitRecord.textureGenS = genS;
+ unitRecord.textureGenT = genT;
+ unitRecord.textureGenR = genR;
+ unitRecord.textureGenQ = genQ;
+ }
+
+ // If we support multitexturing, specify the unit we are affecting.
+ public static void checkAndSetUnit(final int unit, final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ // No need to worry about valid record, since invalidate sets record's
+ // currentUnit to -1.
+ if (record.currentUnit != unit) {
+ if (unit >= caps.getNumberOfTotalTextureUnits() || !caps.isMultitextureSupported() || unit < 0) {
+ // ignore this request as it is not valid for the user's hardware.
+ return;
+ }
+ gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
+ record.currentUnit = unit;
+ }
+ }
+
+ /**
+ * Check if the filter settings of this particular texture have been changed and apply as needed.
+ *
+ * @param texture
+ * our texture object
+ * @param texRecord
+ * our record of the last state of the texture in gl
+ * @param record
+ */
+ public static void applyShadow(final Texture texture, final TextureRecord texRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ final Type type = texture.getType();
+
+ if (caps.isDepthTextureSupported()) {
+ final int depthMode = JoglTextureUtil.getGLDepthTextureMode(texture.getDepthMode());
+ // set up magnification filter
+ if (!texRecord.isValid() || texRecord.depthTextureMode != depthMode) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(getGLType(type), GL2.GL_DEPTH_TEXTURE_MODE, depthMode);
+ texRecord.depthTextureMode = depthMode;
+ }
+ }
+
+ if (caps.isARBShadowSupported()) {
+ final int depthCompareMode = JoglTextureUtil.getGLDepthTextureCompareMode(texture.getDepthCompareMode());
+ // set up magnification filter
+ if (!texRecord.isValid() || texRecord.depthTextureCompareMode != depthCompareMode) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(getGLType(type), GL2ES2.GL_TEXTURE_COMPARE_MODE, depthCompareMode);
+ texRecord.depthTextureCompareMode = depthCompareMode;
+ }
+
+ final int depthCompareFunc = JoglTextureUtil.getGLDepthTextureCompareFunc(texture.getDepthCompareFunc());
+ // set up magnification filter
+ if (!texRecord.isValid() || texRecord.depthTextureCompareFunc != depthCompareFunc) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(getGLType(type), GL2ES2.GL_TEXTURE_COMPARE_FUNC, depthCompareFunc);
+ texRecord.depthTextureCompareFunc = depthCompareFunc;
+ }
+ }
+ }
+
+ /**
+ * Check if the filter settings of this particular texture have been changed and apply as needed.
+ *
+ * @param texture
+ * our texture object
+ * @param texRecord
+ * our record of the last state of the texture in gl
+ * @param record
+ */
+ public static void applyFilter(final Texture texture, final TextureRecord texRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ final Type type = texture.getType();
+
+ final int magFilter = JoglTextureUtil.getGLMagFilter(texture.getMagnificationFilter());
+ // set up magnification filter
+ if (!texRecord.isValid() || texRecord.magFilter != magFilter) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(getGLType(type), GL.GL_TEXTURE_MAG_FILTER, magFilter);
+ texRecord.magFilter = magFilter;
+ }
+
+ final int minFilter = JoglTextureUtil.getGLMinFilter(texture.getMinificationFilter());
+ // set up mipmap filter
+ if (!texRecord.isValid() || texRecord.minFilter != minFilter) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(getGLType(type), GL.GL_TEXTURE_MIN_FILTER, minFilter);
+ texRecord.minFilter = minFilter;
+ }
+
+ // set up aniso filter
+ if (caps.isAnisoSupported()) {
+ float aniso = texture.getAnisotropicFilterPercent() * (caps.getMaxAnisotropic() - 1.0f);
+ aniso += 1.0f;
+ if (!texRecord.isValid() || texRecord.anisoLevel != aniso) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameterf(getGLType(type), GL.GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
+ texRecord.anisoLevel = aniso;
+ }
+ }
+ }
+
+ /**
+ * Check if the wrap mode of this particular texture has been changed and apply as needed.
+ *
+ * @param texture
+ * our texture object
+ * @param texRecord
+ * our record of the last state of the unit in gl
+ * @param record
+ */
+ public static void applyWrap(final Texture3D texture, final TextureRecord texRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!caps.isTexture3DSupported()) {
+ return;
+ }
+
+ final int wrapS = getGLWrap(texture.getWrap(WrapAxis.S), caps);
+ final int wrapT = getGLWrap(texture.getWrap(WrapAxis.T), caps);
+ final int wrapR = getGLWrap(texture.getWrap(WrapAxis.R), caps);
+
+ if (!texRecord.isValid() || texRecord.wrapS != wrapS) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL2ES2.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_S, wrapS);
+ texRecord.wrapS = wrapS;
+ }
+ if (!texRecord.isValid() || texRecord.wrapT != wrapT) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL2ES2.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_T, wrapT);
+ texRecord.wrapT = wrapT;
+ }
+ if (!texRecord.isValid() || texRecord.wrapR != wrapR) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL2ES2.GL_TEXTURE_3D, GL2ES2.GL_TEXTURE_WRAP_R, wrapR);
+ texRecord.wrapR = wrapR;
+ }
+
+ }
+
+ /**
+ * Check if the wrap mode of this particular texture has been changed and apply as needed.
+ *
+ * @param texture
+ * our texture object
+ * @param texRecord
+ * our record of the last state of the unit in gl
+ * @param record
+ */
+ public static void applyWrap(final Texture1D texture, final TextureRecord texRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ final int wrapS = getGLWrap(texture.getWrap(WrapAxis.S), caps);
+
+ if (!texRecord.isValid() || texRecord.wrapS != wrapS) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL2GL3.GL_TEXTURE_1D, GL.GL_TEXTURE_WRAP_S, wrapS);
+ texRecord.wrapS = wrapS;
+ }
+ }
+
+ /**
+ * Check if the wrap mode of this particular texture has been changed and apply as needed.
+ *
+ * @param texture
+ * our texture object
+ * @param texRecord
+ * our record of the last state of the unit in gl
+ * @param record
+ */
+ public static void applyWrap(final Texture texture, final TextureRecord texRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ if (texture instanceof Texture2D) {
+ applyWrap((Texture2D) texture, texRecord, unit, record, caps);
+ } else if (texture instanceof Texture1D) {
+ applyWrap((Texture1D) texture, texRecord, unit, record, caps);
+ } else if (texture instanceof Texture3D) {
+ applyWrap((Texture3D) texture, texRecord, unit, record, caps);
+ } else if (texture instanceof TextureCubeMap) {
+ applyWrap((TextureCubeMap) texture, texRecord, unit, record, caps);
+ }
+ }
+
+ /**
+ * Check if the wrap mode of this particular texture has been changed and apply as needed.
+ *
+ * @param texture
+ * our texture object
+ * @param texRecord
+ * our record of the last state of the unit in gl
+ * @param record
+ */
+ public static void applyWrap(final Texture2D texture, final TextureRecord texRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ final int wrapS = getGLWrap(texture.getWrap(WrapAxis.S), caps);
+ final int wrapT = getGLWrap(texture.getWrap(WrapAxis.T), caps);
+
+ if (!texRecord.isValid() || texRecord.wrapS != wrapS) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS);
+ texRecord.wrapS = wrapS;
+ }
+ if (!texRecord.isValid() || texRecord.wrapT != wrapT) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
+ texRecord.wrapT = wrapT;
+ }
+
+ }
+
+ /**
+ * Check if the wrap mode of this particular texture has been changed and apply as needed.
+ *
+ * @param cubeMap
+ * our texture object
+ * @param texRecord
+ * our record of the last state of the unit in gl
+ * @param record
+ */
+ public static void applyWrap(final TextureCubeMap cubeMap, final TextureRecord texRecord, final int unit,
+ final TextureStateRecord record, final ContextCapabilities caps) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!caps.isTextureCubeMapSupported()) {
+ return;
+ }
+
+ final int wrapS = getGLWrap(cubeMap.getWrap(WrapAxis.S), caps);
+ final int wrapT = getGLWrap(cubeMap.getWrap(WrapAxis.T), caps);
+ final int wrapR = getGLWrap(cubeMap.getWrap(WrapAxis.R), caps);
+
+ if (!texRecord.isValid() || texRecord.wrapS != wrapS) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL.GL_TEXTURE_CUBE_MAP, GL.GL_TEXTURE_WRAP_S, wrapS);
+ texRecord.wrapS = wrapS;
+ }
+ if (!texRecord.isValid() || texRecord.wrapT != wrapT) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL.GL_TEXTURE_CUBE_MAP, GL.GL_TEXTURE_WRAP_T, wrapT);
+ texRecord.wrapT = wrapT;
+ }
+ if (!texRecord.isValid() || texRecord.wrapR != wrapR) {
+ checkAndSetUnit(unit, record, caps);
+ gl.glTexParameteri(GL.GL_TEXTURE_CUBE_MAP, GL2ES2.GL_TEXTURE_WRAP_R, wrapR);
+ texRecord.wrapR = wrapR;
+ }
+ }
+
+ public static void deleteTexture(final Texture texture) {
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final TextureStateRecord record = (TextureStateRecord) context.getStateRecord(StateType.Texture);
+
+ final Integer id = texture.getTextureIdForContextAsInteger(context.getGlContextRep());
+ if (id.intValue() == 0) {
+ // Not on card... return.
+ return;
+ }
+
+ final IntBuffer idBuffer = BufferUtils.createIntBuffer(1);
+ idBuffer.clear();
+ idBuffer.put(id.intValue());
+ idBuffer.rewind();
+ gl.glDeleteTextures(idBuffer.limit(), idBuffer);
+ record.removeTextureRecord(id);
+ texture.removeFromIdCache(context.getGlContextRep());
+ }
+
+ public static void deleteTextureIds(final Collection<Integer> ids) {
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final TextureStateRecord record = (TextureStateRecord) context.getStateRecord(StateType.Texture);
+
+ final IntBuffer idBuffer = BufferUtils.createIntBuffer(ids.size());
+ idBuffer.clear();
+ for (final Integer i : ids) {
+ if (i != null) {
+ idBuffer.put(i);
+ record.removeTextureRecord(i);
+ }
+ }
+ idBuffer.flip();
+ if (idBuffer.remaining() > 0) {
+ gl.glDeleteTextures(idBuffer.remaining(), idBuffer);
+ }
+ }
+
+ /**
+ * Useful for external jogl based classes that need to safely set the current texture.
+ */
+ public static void doTextureBind(final Texture texture, final int unit, final boolean invalidateState) {
+ final GL gl = GLU.getCurrentGL();
+
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+ final TextureStateRecord record = (TextureStateRecord) context.getStateRecord(StateType.Texture);
+ if (invalidateState) {
+ // Set this to null because no current state really matches anymore
+ context.setCurrentState(StateType.Texture, null);
+ }
+ checkAndSetUnit(unit, record, caps);
+
+ final int id = texture.getTextureIdForContext(context.getGlContextRep());
+ gl.glBindTexture(getGLType(texture.getType()), id);
+ if (Constants.stats) {
+ StatCollector.addStat(StatType.STAT_TEXTURE_BINDS, 1);
+ }
+ if (record != null) {
+ record.units[unit].boundTexture = id;
+ }
+ }
+
+ public static int getGLType(final Type type) {
+ switch (type) {
+ case TwoDimensional:
+ return GL.GL_TEXTURE_2D;
+ case OneDimensional:
+ return GL2GL3.GL_TEXTURE_1D;
+ case ThreeDimensional:
+ return GL2ES2.GL_TEXTURE_3D;
+ case CubeMap:
+ return GL.GL_TEXTURE_CUBE_MAP;
+ case Rectangle:
+ break;
+ default:
+ break;
+ }
+ throw new IllegalArgumentException("invalid texture type: " + type);
+ }
+
+ public static int getGLCubeMapFace(final TextureCubeMap.Face face) {
+ switch (face) {
+ case PositiveX:
+ return GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ case NegativeX:
+ return GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
+ case PositiveY:
+ return GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
+ case NegativeY:
+ return GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+ case PositiveZ:
+ return GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
+ case NegativeZ:
+ return GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+ }
+ throw new IllegalArgumentException("invalid cubemap face: " + face);
+ }
+
+ private static int getGLWrap(final WrapMode wrap, final ContextCapabilities caps) {
+ switch (wrap) {
+ case Repeat:
+ return GL.GL_REPEAT;
+ case MirroredRepeat:
+ if (caps.isTextureMirroredRepeatSupported()) {
+ return GL.GL_MIRRORED_REPEAT;
+ } else {
+ return GL.GL_REPEAT;
+ }
+ case MirrorClamp:
+ if (caps.isTextureMirrorClampSupported()) {
+ return GL2.GL_MIRROR_CLAMP_EXT;
+ }
+ // FALLS THROUGH
+ case Clamp:
+ return GL2.GL_CLAMP;
+ case MirrorBorderClamp:
+ if (caps.isTextureMirrorBorderClampSupported()) {
+ return GL2.GL_MIRROR_CLAMP_TO_BORDER_EXT;
+ }
+ // FALLS THROUGH
+ case BorderClamp:
+ if (caps.isTextureBorderClampSupported()) {
+ return GL2GL3.GL_CLAMP_TO_BORDER;
+ } else {
+ return GL2.GL_CLAMP;
+ }
+ case MirrorEdgeClamp:
+ if (caps.isTextureMirrorEdgeClampSupported()) {
+ return GL2.GL_MIRROR_CLAMP_TO_EDGE_EXT;
+ }
+ // FALLS THROUGH
+ case EdgeClamp:
+ if (caps.isTextureEdgeClampSupported()) {
+ return GL.GL_CLAMP_TO_EDGE;
+ } else {
+ return GL2.GL_CLAMP;
+ }
+ }
+ throw new IllegalArgumentException("invalid WrapMode type: " + wrap);
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglVertexProgramStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglVertexProgramStateUtil.java
new file mode 100644
index 0000000..50258b8
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglVertexProgramStateUtil.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.VertexProgramState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.VertexProgramStateRecord;
+import com.ardor3d.util.geom.BufferUtils;
+
+public abstract class JoglVertexProgramStateUtil {
+ private static final Logger logger = Logger.getLogger(JoglVertexProgramStateUtil.class.getName());
+
+ /**
+ * Queries OpenGL for errors in the vertex program. Errors are logged as SEVERE, noting both the line number and
+ * message.
+ */
+ private static void checkProgramError() {
+ final GL gl = GLU.getCurrentGL();
+
+ if (gl.glGetError() == GL.GL_INVALID_OPERATION) {
+ // retrieve the error position
+ final IntBuffer errorloc = BufferUtils.createIntBuffer(16);
+ gl.glGetIntegerv(GL2.GL_PROGRAM_ERROR_POSITION_ARB, errorloc); // TODO Check for integer
+
+ logger.severe("Error " + gl.glGetString(GL2.GL_PROGRAM_ERROR_STRING_ARB) + " in vertex program on line "
+ + errorloc.get(0));
+ }
+ }
+
+ private static int create(final ByteBuffer program) {
+ final GL gl = GLU.getCurrentGL();
+
+ final IntBuffer buf = BufferUtils.createIntBuffer(1);
+
+ gl.getGL2().glGenProgramsARB(buf.limit(), buf);
+ gl.getGL2().glBindProgramARB(GL2.GL_VERTEX_PROGRAM_ARB, buf.get(0));
+
+ final byte array[] = new byte[program.limit()];
+ program.rewind();
+ program.get(array);
+ gl.getGL2()
+ .glProgramStringARB(GL2.GL_VERTEX_PROGRAM_ARB, GL2.GL_PROGRAM_FORMAT_ASCII_ARB, array.length, new String(
+ array));
+
+ checkProgramError();
+
+ return buf.get(0);
+ }
+
+ public static void apply(final JoglRenderer renderer, final VertexProgramState state) {
+ final GL gl = GLU.getCurrentGL();
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+
+ if (caps.isVertexProgramSupported()) {
+ // ask for the current state record
+ final VertexProgramStateRecord record = (VertexProgramStateRecord) context
+ .getStateRecord(StateType.VertexProgram);
+ context.setCurrentState(StateType.VertexProgram, state);
+
+ if (!record.isValid() || record.getReference() != state) {
+ record.setReference(state);
+ if (state.isEnabled()) {
+ // Vertex program not yet loaded
+ if (state._getProgramID() == -1) {
+ if (state.getProgramAsBuffer() != null) {
+ final int id = create(state.getProgramAsBuffer());
+ state._setProgramID(id);
+ } else {
+ return;
+ }
+ }
+
+ gl.glEnable(GL2.GL_VERTEX_PROGRAM_ARB);
+ gl.getGL2().glBindProgramARB(GL2.GL_VERTEX_PROGRAM_ARB, state._getProgramID());
+
+ // load environmental parameters...
+ for (int i = 0; i < VertexProgramState._getEnvParameters().length; i++) {
+ if (VertexProgramState._getEnvParameters()[i] != null) {
+ gl.getGL2().glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, i, VertexProgramState
+ ._getEnvParameters()[i][0], VertexProgramState._getEnvParameters()[i][1],
+ VertexProgramState._getEnvParameters()[i][2], VertexProgramState
+ ._getEnvParameters()[i][3]);
+ }
+ }
+
+ // load local parameters...
+ if (state.isUsingParameters()) {
+ // no parameters are used
+ for (int i = 0; i < state._getParameters().length; i++) {
+ if (state._getParameters()[i] != null) {
+ gl.getGL2().glProgramLocalParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, i,
+ state._getParameters()[i][0], state._getParameters()[i][1], state
+ ._getParameters()[i][2], state._getParameters()[i][3]);
+ }
+ }
+ }
+
+ } else {
+ gl.glDisable(GL2.GL_VERTEX_PROGRAM_ARB);
+ }
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglWireframeStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglWireframeStateUtil.java
new file mode 100644
index 0000000..bf8b026
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglWireframeStateUtil.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.WireframeState;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.WireframeStateRecord;
+
+public abstract class JoglWireframeStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final WireframeState state) {
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final WireframeStateRecord record = (WireframeStateRecord) context.getStateRecord(StateType.Wireframe);
+ context.setCurrentState(StateType.Wireframe, state);
+
+ if (state.isEnabled()) {
+ renderer.setupLineParameters(state.getLineWidth(), 1, (short) 0xFFFF, state.isAntialiased());
+
+ switch (state.getFace()) {
+ case Front:
+ applyPolyMode(GL2GL3.GL_LINE, GL2GL3.GL_FILL, record);
+ break;
+ case Back:
+ applyPolyMode(GL2GL3.GL_FILL, GL2GL3.GL_LINE, record);
+ break;
+ case FrontAndBack:
+ default:
+ applyPolyMode(GL2GL3.GL_LINE, GL2GL3.GL_LINE, record);
+ break;
+ }
+ } else {
+ applyPolyMode(GL2GL3.GL_FILL, GL2GL3.GL_FILL, record);
+ }
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void applyPolyMode(final int frontMode, final int backMode, final WireframeStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (record.isValid()) {
+ if (frontMode == backMode && (record.frontMode != frontMode || record.backMode != backMode)) {
+ gl.getGL2GL3().glPolygonMode(GL.GL_FRONT_AND_BACK, frontMode);
+ record.frontMode = frontMode;
+ record.backMode = backMode;
+ } else if (frontMode != backMode) {
+ if (record.frontMode != frontMode) {
+ gl.getGL2GL3().glPolygonMode(GL.GL_FRONT, frontMode);
+ record.frontMode = frontMode;
+ }
+ if (record.backMode != backMode) {
+ gl.getGL2GL3().glPolygonMode(GL.GL_BACK, backMode);
+ record.backMode = backMode;
+ }
+ }
+
+ } else {
+ if (frontMode == backMode) {
+ gl.getGL2GL3().glPolygonMode(GL.GL_FRONT_AND_BACK, frontMode);
+ } else if (frontMode != backMode) {
+ gl.getGL2GL3().glPolygonMode(GL.GL_FRONT, frontMode);
+ gl.getGL2GL3().glPolygonMode(GL.GL_BACK, backMode);
+ }
+ record.frontMode = frontMode;
+ record.backMode = backMode;
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglZBufferStateUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglZBufferStateUtil.java
new file mode 100644
index 0000000..b806b02
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglZBufferStateUtil.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.RenderState;
+import com.ardor3d.renderer.state.ZBufferState;
+import com.ardor3d.renderer.state.record.ZBufferStateRecord;
+
+public abstract class JoglZBufferStateUtil {
+
+ public static void apply(final JoglRenderer renderer, final ZBufferState state) {
+ // ask for the current state record
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ZBufferStateRecord record = (ZBufferStateRecord) context.getStateRecord(RenderState.StateType.ZBuffer);
+ context.setCurrentState(RenderState.StateType.ZBuffer, state);
+
+ enableDepthTest(state.isEnabled(), record);
+ if (state.isEnabled()) {
+ int depthFunc = 0;
+ switch (state.getFunction()) {
+ case Never:
+ depthFunc = GL.GL_NEVER;
+ break;
+ case LessThan:
+ depthFunc = GL.GL_LESS;
+ break;
+ case EqualTo:
+ depthFunc = GL.GL_EQUAL;
+ break;
+ case LessThanOrEqualTo:
+ depthFunc = GL.GL_LEQUAL;
+ break;
+ case GreaterThan:
+ depthFunc = GL.GL_GREATER;
+ break;
+ case NotEqualTo:
+ depthFunc = GL.GL_NOTEQUAL;
+ break;
+ case GreaterThanOrEqualTo:
+ depthFunc = GL.GL_GEQUAL;
+ break;
+ case Always:
+ depthFunc = GL.GL_ALWAYS;
+ }
+ applyFunction(depthFunc, record);
+ }
+
+ enableWrite(state.isWritable(), record);
+
+ if (!record.isValid()) {
+ record.validate();
+ }
+ }
+
+ private static void enableDepthTest(final boolean enable, final ZBufferStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (enable && (!record.depthTest || !record.isValid())) {
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ record.depthTest = true;
+ } else if (!enable && (record.depthTest || !record.isValid())) {
+ gl.glDisable(GL.GL_DEPTH_TEST);
+ record.depthTest = false;
+ }
+ }
+
+ private static void applyFunction(final int depthFunc, final ZBufferStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (depthFunc != record.depthFunc || !record.isValid()) {
+ gl.glDepthFunc(depthFunc);
+ record.depthFunc = depthFunc;
+ }
+ }
+
+ private static void enableWrite(final boolean enable, final ZBufferStateRecord record) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (enable != record.writable || !record.isValid()) {
+ gl.glDepthMask(enable);
+ record.writable = enable;
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/shader/JoglShaderUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/shader/JoglShaderUtil.java
new file mode 100644
index 0000000..96927ae
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/shader/JoglShaderUtil.java
@@ -0,0 +1,418 @@
+/**
+ * Copyright (c) 2008-2012 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl.shader;
+
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.renderer.ContextCapabilities;
+import com.ardor3d.renderer.ContextManager;
+import com.ardor3d.renderer.RenderContext;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.jogl.JoglRenderer;
+import com.ardor3d.renderer.state.RenderState.StateType;
+import com.ardor3d.renderer.state.record.ShaderObjectsStateRecord;
+import com.ardor3d.scene.state.jogl.util.JoglRendererUtil;
+import com.ardor3d.util.shader.ShaderVariable;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableFloat;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableFloat2;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableFloat3;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableFloat4;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableFloatArray;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableInt;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableInt2;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableInt3;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableInt4;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableIntArray;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableMatrix2;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableMatrix3;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableMatrix4;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariableMatrix4Array;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariablePointerByte;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariablePointerFloat;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariablePointerFloatMatrix;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariablePointerInt;
+import com.ardor3d.util.shader.uniformtypes.ShaderVariablePointerShort;
+
+/** Utility class for updating shadervariables(uniforms and attributes) */
+public abstract class JoglShaderUtil {
+ private static final Logger logger = Logger.getLogger(JoglShaderUtil.class.getName());
+
+ /**
+ * Updates a uniform shadervariable.
+ *
+ * @param shaderVariable
+ * variable to update
+ */
+ public static void updateShaderUniform(final ShaderVariable shaderVariable) {
+ if (!shaderVariable.hasData()) {
+ throw new IllegalArgumentException("shaderVariable has no data: " + shaderVariable.name + " type: "
+ + shaderVariable.getClass().getName());
+ }
+
+ if (shaderVariable instanceof ShaderVariableInt) {
+ updateShaderUniform((ShaderVariableInt) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableInt2) {
+ updateShaderUniform((ShaderVariableInt2) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableInt3) {
+ updateShaderUniform((ShaderVariableInt3) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableInt4) {
+ updateShaderUniform((ShaderVariableInt4) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableIntArray) {
+ updateShaderUniform((ShaderVariableIntArray) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableFloat) {
+ updateShaderUniform((ShaderVariableFloat) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableFloat2) {
+ updateShaderUniform((ShaderVariableFloat2) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableFloat3) {
+ updateShaderUniform((ShaderVariableFloat3) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableFloat4) {
+ updateShaderUniform((ShaderVariableFloat4) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableFloatArray) {
+ updateShaderUniform((ShaderVariableFloatArray) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableMatrix2) {
+ updateShaderUniform((ShaderVariableMatrix2) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableMatrix3) {
+ updateShaderUniform((ShaderVariableMatrix3) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableMatrix4) {
+ updateShaderUniform((ShaderVariableMatrix4) shaderVariable);
+ } else if (shaderVariable instanceof ShaderVariableMatrix4Array) {
+ updateShaderUniform((ShaderVariableMatrix4Array) shaderVariable);
+ } else {
+ logger.warning("updateShaderUniform: Unknown shaderVariable type!");
+ }
+ }
+
+ /**
+ * Update variableID for uniform shadervariable if needed.
+ *
+ * @param variable
+ * shadervaribale to update ID on
+ * @param programID
+ * shader program context ID
+ */
+ public static void updateUniformLocation(final ShaderVariable variable, final int programID) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (variable.variableID == -1) {
+ variable.variableID = gl.getGL2GL3().glGetUniformLocation(programID, variable.name); // TODO Check variable.name
+
+ if (variable.variableID == -1 && !variable.errorLogged) {
+ logger.severe("Shader uniform [" + variable.name + "] could not be located in shader");
+ variable.errorLogged = true;
+ }
+ }
+ }
+
+ private static void updateShaderUniform(final ShaderVariableInt shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glUniform1i(shaderUniform.variableID, shaderUniform.value1);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableInt2 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glUniform2i(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableInt3 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glUniform3i(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2, shaderUniform.value3);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableInt4 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glUniform4i(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2, shaderUniform.value3,
+ shaderUniform.value4);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableIntArray shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ switch (shaderUniform.size) {
+ case 1:
+ gl.getGL2GL3().glUniform1iv(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value);
+ break;
+ case 2:
+ gl.getGL2GL3().glUniform2iv(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value);
+ break;
+ case 3:
+ gl.getGL2GL3().glUniform3iv(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value);
+ break;
+ case 4:
+ gl.getGL2GL3().glUniform4iv(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value);
+ break;
+ default:
+ throw new IllegalArgumentException("Wrong size: " + shaderUniform.size);
+ }
+ }
+
+ private static void updateShaderUniform(final ShaderVariableFloat shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glUniform1f(shaderUniform.variableID, shaderUniform.value1);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableFloat2 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glUniform2f(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableFloat3 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glUniform3f(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2, shaderUniform.value3);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableFloat4 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ gl.getGL2GL3().glUniform4f(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2, shaderUniform.value3,
+ shaderUniform.value4);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableFloatArray shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ switch (shaderUniform.size) {
+ case 1:
+ gl.getGL2GL3().glUniform1fv(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value);
+ break;
+ case 2:
+ gl.getGL2GL3().glUniform2fv(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value);
+ break;
+ case 3:
+ gl.getGL2GL3().glUniform3fv(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value);
+ break;
+ case 4:
+ gl.getGL2GL3().glUniform4fv(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value);
+ break;
+ default:
+ throw new IllegalArgumentException("Wrong size: " + shaderUniform.size);
+ }
+ }
+
+ private static void updateShaderUniform(final ShaderVariableMatrix2 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ shaderUniform.matrixBuffer.rewind();
+ gl.getGL2GL3().glUniformMatrix2fv(shaderUniform.variableID, 1, shaderUniform.rowMajor, shaderUniform.matrixBuffer);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableMatrix3 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ shaderUniform.matrixBuffer.rewind();
+ gl.getGL2GL3().glUniformMatrix3fv(shaderUniform.variableID, 1, shaderUniform.rowMajor, shaderUniform.matrixBuffer);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableMatrix4 shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ shaderUniform.matrixBuffer.rewind();
+ gl.getGL2GL3().glUniformMatrix4fv(shaderUniform.variableID, 1, shaderUniform.rowMajor, shaderUniform.matrixBuffer);
+ }
+
+ private static void updateShaderUniform(final ShaderVariableMatrix4Array shaderUniform) {
+ final GL gl = GLU.getCurrentGL();
+
+ shaderUniform.matrixBuffer.rewind();
+ // count == number of matrices we are sending, or iotw, limit / 16
+ gl.getGL2GL3().glUniformMatrix4fv(shaderUniform.variableID, shaderUniform.matrixBuffer.limit() >> 4,
+ shaderUniform.rowMajor, shaderUniform.matrixBuffer);
+ }
+
+ /**
+ * Update variableID for attribute shadervariable if needed.
+ *
+ * @param variable
+ * shadervaribale to update ID on
+ * @param programID
+ * shader program context ID
+ */
+ public static void updateAttributeLocation(final ShaderVariable variable, final int programID) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (variable.variableID == -1) {
+ variable.variableID = gl.getGL2GL3().glGetAttribLocation(programID, variable.name); // TODO Check variable.name
+
+ if (variable.variableID == -1 && !variable.errorLogged) {
+ logger.severe("Shader attribute [" + variable.name + "] could not be located in shader");
+ variable.errorLogged = true;
+ }
+ }
+ }
+
+ /**
+ * Updates an vertex attribute pointer.
+ *
+ * @param renderer
+ * the current renderer
+ * @param shaderVariable
+ * variable to update
+ * @param useVBO
+ * if true, we'll use VBO for the attributes, if false we'll use arrays.
+ */
+ public static void updateShaderAttribute(final Renderer renderer, final ShaderVariable shaderVariable,
+ final boolean useVBO) {
+ if (shaderVariable.variableID == -1) {
+ // attribute is not bound, or was not found in shader.
+ return;
+ }
+
+ if (!shaderVariable.hasData()) {
+ throw new IllegalArgumentException("shaderVariable has no data: " + shaderVariable.name + " type: "
+ + shaderVariable.getClass().getName());
+ }
+
+ final RenderContext context = ContextManager.getCurrentContext();
+ final ContextCapabilities caps = context.getCapabilities();
+ if (caps.isVBOSupported() && !useVBO) {
+ renderer.unbindVBO();
+ }
+
+ final ShaderObjectsStateRecord record = (ShaderObjectsStateRecord) context.getStateRecord(StateType.GLSLShader);
+
+ if (shaderVariable instanceof ShaderVariablePointerFloat) {
+ updateShaderAttribute((ShaderVariablePointerFloat) shaderVariable, record, useVBO);
+ } else if (shaderVariable instanceof ShaderVariablePointerFloatMatrix) {
+ updateShaderAttribute((ShaderVariablePointerFloatMatrix) shaderVariable, record, useVBO);
+ } else if (shaderVariable instanceof ShaderVariablePointerByte) {
+ updateShaderAttribute((ShaderVariablePointerByte) shaderVariable, record, useVBO);
+ } else if (shaderVariable instanceof ShaderVariablePointerInt) {
+ updateShaderAttribute((ShaderVariablePointerInt) shaderVariable, record, useVBO);
+ } else if (shaderVariable instanceof ShaderVariablePointerShort) {
+ updateShaderAttribute((ShaderVariablePointerShort) shaderVariable, record, useVBO);
+ } else {
+ logger.warning("updateShaderAttribute: Unknown shaderVariable type!");
+ return;
+ }
+ }
+
+ public static void useShaderProgram(final int id, final ShaderObjectsStateRecord record) {
+ if (record.shaderId != id) {
+ GLU.getCurrentGL().getGL2().glUseProgramObjectARB(id);
+ record.shaderId = id;
+ }
+ }
+
+ private static void enableVertexAttribute(final ShaderVariable var, final ShaderObjectsStateRecord record) {
+ if (!record.enabledAttributes.contains(var)) {
+ if (var.getSize() == 1) {
+ GLU.getCurrentGL().getGL2GL3().glEnableVertexAttribArray(var.variableID);
+ } else {
+ final GL gl = GLU.getCurrentGL();
+ for (int i = 0, max = var.getSize(); i < max; i++) {
+ gl.getGL2GL3().glEnableVertexAttribArray(var.variableID + i);
+ }
+ }
+ record.enabledAttributes.add(var);
+ }
+ }
+
+ private static void updateShaderAttribute(final ShaderVariablePointerFloat variable,
+ final ShaderObjectsStateRecord record, final boolean useVBO) {
+ enableVertexAttribute(variable, record);
+ if (useVBO) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final int vboId = JoglRenderer.setupVBO(variable.data, context);
+ JoglRendererUtil.setBoundVBO(context.getRendererRecord(), vboId);
+ GLU.getCurrentGL().getGL2GL3().glVertexAttribPointer(variable.variableID, variable.size, GL.GL_FLOAT,
+ variable.normalized, variable.stride, 0);
+ } else {
+ variable.data.getBuffer().rewind();
+ GLU.getCurrentGL().getGL2GL3().glVertexAttribPointer(variable.variableID, variable.size, GL.GL_FLOAT,
+ variable.normalized, variable.stride, variable.data.getBuffer());
+ }
+ }
+
+ private static void updateShaderAttribute(final ShaderVariablePointerFloatMatrix variable,
+ final ShaderObjectsStateRecord record, final boolean useVBO) {
+ final GL gl = GLU.getCurrentGL();
+ final int size = variable.size;
+ final int length = variable.data.getBuffer().capacity() / size;
+ final RenderContext context = ContextManager.getCurrentContext();
+ int pos = 0;
+ enableVertexAttribute(variable, record);
+ for (int i = 0; i < size; i++) {
+ pos = (i * length);
+ if (useVBO) {
+ final int vboId = JoglRenderer.setupVBO(variable.data, context);
+ JoglRendererUtil.setBoundVBO(context.getRendererRecord(), vboId);
+ gl.getGL2GL3().glVertexAttribPointer(variable.variableID + i, size, GL.GL_FLOAT, variable.normalized, 0, pos);
+ } else {
+ variable.data.getBuffer().limit(pos + length - 1);
+ variable.data.getBuffer().position(pos);
+ gl.getGL2GL3().glVertexAttribPointer(variable.variableID + i, size, GL.GL_FLOAT, variable.normalized, 0,
+ variable.data.getBuffer());
+ }
+ }
+ }
+
+ private static void updateShaderAttribute(final ShaderVariablePointerByte variable,
+ final ShaderObjectsStateRecord record, final boolean useVBO) {
+ enableVertexAttribute(variable, record);
+ if (useVBO) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final int vboId = JoglRenderer.setupVBO(variable.data, context);
+ JoglRendererUtil.setBoundVBO(context.getRendererRecord(), vboId);
+ GLU.getCurrentGL().getGL2GL3().glVertexAttribPointer(variable.variableID, variable.size,
+ variable.unsigned ? GL.GL_UNSIGNED_BYTE : GL.GL_BYTE, variable.normalized, variable.stride, 0);
+ } else {
+ variable.data.getBuffer().rewind();
+ GLU.getCurrentGL().getGL2GL3().glVertexAttribPointer(variable.variableID, variable.size,
+ variable.unsigned ? GL.GL_UNSIGNED_BYTE : GL.GL_BYTE, variable.normalized, variable.stride,
+ variable.data.getBuffer());
+ }
+ }
+
+ private static void updateShaderAttribute(final ShaderVariablePointerInt variable,
+ final ShaderObjectsStateRecord record, final boolean useVBO) {
+ enableVertexAttribute(variable, record);
+ if (useVBO) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final int vboId = JoglRenderer.setupVBO(variable.data, context);
+ JoglRendererUtil.setBoundVBO(context.getRendererRecord(), vboId);
+ GLU.getCurrentGL().getGL2GL3().glVertexAttribPointer(variable.variableID, variable.size,
+ variable.unsigned ? GL.GL_UNSIGNED_INT : GL2ES2.GL_INT, variable.normalized, variable.stride, 0);
+ } else {
+ variable.data.getBuffer().rewind();
+ GLU.getCurrentGL().getGL2GL3().glVertexAttribPointer(variable.variableID, variable.size,
+ variable.unsigned ? GL.GL_UNSIGNED_INT : GL2ES2.GL_INT, variable.normalized, variable.stride,
+ variable.data.getBuffer());
+ }
+ }
+
+ private static void updateShaderAttribute(final ShaderVariablePointerShort variable,
+ final ShaderObjectsStateRecord record, final boolean useVBO) {
+ enableVertexAttribute(variable, record);
+ if (useVBO) {
+ final RenderContext context = ContextManager.getCurrentContext();
+ final int vboId = JoglRenderer.setupVBO(variable.data, context);
+ JoglRendererUtil.setBoundVBO(context.getRendererRecord(), vboId);
+ GLU.getCurrentGL().getGL2GL3().glVertexAttribPointer(variable.variableID, variable.size,
+ variable.unsigned ? GL.GL_UNSIGNED_SHORT : GL.GL_SHORT, variable.normalized, variable.stride, 0);
+ } else {
+ variable.data.getBuffer().rewind();
+ GLU.getCurrentGL().getGL2GL3().glVertexAttribPointer(variable.variableID, variable.size,
+ variable.unsigned ? GL.GL_UNSIGNED_SHORT : GL.GL_SHORT, variable.normalized, variable.stride,
+ variable.data.getBuffer());
+ }
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglRendererUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglRendererUtil.java
new file mode 100644
index 0000000..88f006e
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglRendererUtil.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl.util;
+
+import java.util.Stack;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.glu.GLU;
+
+import com.ardor3d.math.Rectangle2;
+import com.ardor3d.math.type.ReadOnlyRectangle2;
+import com.ardor3d.renderer.state.record.RendererRecord;
+
+public abstract class JoglRendererUtil {
+
+ public static void switchMode(final RendererRecord rendRecord, final int mode) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!rendRecord.isMatrixValid() || rendRecord.getMatrixMode() != mode) {
+ gl.getGL2().glMatrixMode(mode);
+ rendRecord.setMatrixMode(mode);
+ rendRecord.setMatrixValid(true);
+ }
+ }
+
+ public static void setBoundVBO(final RendererRecord rendRecord, final int id) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!rendRecord.isVboValid() || rendRecord.getCurrentVboId() != id) {
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, id);
+ rendRecord.setCurrentVboId(id);
+ rendRecord.setVboValid(true);
+ }
+ }
+
+ public static void setBoundElementVBO(final RendererRecord rendRecord, final int id) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (!rendRecord.isElementVboValid() || rendRecord.getCurrentElementVboId() != id) {
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, id);
+ rendRecord.setCurrentElementVboId(id);
+ rendRecord.setElementVboValid(true);
+ }
+ }
+
+ public static void applyScissors(final RendererRecord rendRecord) {
+ final GL gl = GLU.getCurrentGL();
+ final Stack<ReadOnlyRectangle2> clips = rendRecord.getScissorClips();
+
+ if (clips.size() > 0) {
+ final Rectangle2 init = Rectangle2.fetchTempInstance();
+ init.set(-1, -1, -1, -1);
+ ReadOnlyRectangle2 r;
+ boolean first = true;
+ for (int i = clips.size(); --i >= 0;) {
+ r = clips.get(i);
+
+ if (r == null) {
+ break;
+ }
+ if (first) {
+ init.set(r);
+ first = false;
+ } else {
+ init.intersect(r, init);
+ }
+ if (init.getWidth() <= 0 || init.getHeight() <= 0) {
+ init.setWidth(0);
+ init.setHeight(0);
+ break;
+ }
+ }
+
+ if (init.getWidth() == -1) {
+ setClippingEnabled(rendRecord, false);
+ } else {
+ setClippingEnabled(rendRecord, true);
+ gl.glScissor(init.getX(), init.getY(), init.getWidth(), init.getHeight());
+ }
+ Rectangle2.releaseTempInstance(init);
+ } else {
+ // no clips, so disable
+ setClippingEnabled(rendRecord, false);
+ }
+ }
+
+ public static void setClippingEnabled(final RendererRecord rendRecord, final boolean enabled) {
+ final GL gl = GLU.getCurrentGL();
+
+ if (enabled && (!rendRecord.isClippingTestValid() || !rendRecord.isClippingTestEnabled())) {
+ gl.glEnable(GL.GL_SCISSOR_TEST);
+ rendRecord.setClippingTestEnabled(true);
+ } else if (!enabled && (!rendRecord.isClippingTestValid() || rendRecord.isClippingTestEnabled())) {
+ gl.glDisable(GL.GL_SCISSOR_TEST);
+ rendRecord.setClippingTestEnabled(false);
+ }
+ rendRecord.setClippingTestValid(true);
+ }
+}
diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglTextureUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglTextureUtil.java
new file mode 100644
index 0000000..2e9ab9e
--- /dev/null
+++ b/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglTextureUtil.java
@@ -0,0 +1,611 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.scene.state.jogl.util;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+
+import com.ardor3d.image.ImageDataFormat;
+import com.ardor3d.image.PixelDataType;
+import com.ardor3d.image.Texture.ApplyMode;
+import com.ardor3d.image.Texture.CombinerFunctionAlpha;
+import com.ardor3d.image.Texture.CombinerFunctionRGB;
+import com.ardor3d.image.Texture.CombinerOperandAlpha;
+import com.ardor3d.image.Texture.CombinerOperandRGB;
+import com.ardor3d.image.Texture.CombinerSource;
+import com.ardor3d.image.Texture.DepthTextureCompareFunc;
+import com.ardor3d.image.Texture.DepthTextureCompareMode;
+import com.ardor3d.image.Texture.DepthTextureMode;
+import com.ardor3d.image.Texture.MagnificationFilter;
+import com.ardor3d.image.Texture.MinificationFilter;
+import com.ardor3d.image.TextureStoreFormat;
+import com.ardor3d.renderer.state.TextureState.CorrectionType;
+
+public abstract class JoglTextureUtil {
+
+ public static int getGLInternalFormat(final TextureStoreFormat format) {
+ switch (format) {
+ // first some frequently used formats
+ case RGBA8:
+ return GL.GL_RGBA8;
+ case RGB8:
+ return GL.GL_RGB8;
+ case Alpha8:
+ return GL2.GL_ALPHA8;
+ case CompressedRGBA:
+ return GL2GL3.GL_COMPRESSED_RGBA;
+ case CompressedRGB:
+ return GL2GL3.GL_COMPRESSED_RGB;
+ case CompressedRG:
+ return GL2GL3.GL_COMPRESSED_RG;
+ case CompressedRed:
+ return GL2GL3.GL_COMPRESSED_RED;
+ case CompressedLuminance:
+ return GL2.GL_COMPRESSED_LUMINANCE;
+ case CompressedLuminanceAlpha:
+ return GL2.GL_COMPRESSED_LUMINANCE_ALPHA;
+ case NativeDXT1:
+ return GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ case NativeDXT1A:
+ return GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ case NativeDXT3:
+ return GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ case NativeDXT5:
+ return GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ case NativeLATC_L:
+ return GL2.GL_COMPRESSED_LUMINANCE_LATC1_EXT;
+ case NativeLATC_LA:
+ return GL2.GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
+
+ // The rest...
+ case Alpha4:
+ return GL2.GL_ALPHA4;
+ case Alpha12:
+ return GL2.GL_ALPHA12;
+ case Alpha16:
+ return GL2.GL_ALPHA16;
+ case Luminance4:
+ return GL2.GL_LUMINANCE4;
+ case Luminance8:
+ return GL2.GL_LUMINANCE8;
+ case Luminance12:
+ return GL2.GL_LUMINANCE12;
+ case Luminance16:
+ return GL2.GL_LUMINANCE16;
+ case Intensity4:
+ return GL2.GL_INTENSITY4;
+ case Intensity8:
+ return GL2.GL_INTENSITY8;
+ case Intensity12:
+ return GL2.GL_INTENSITY12;
+ case Intensity16:
+ return GL2.GL_INTENSITY16;
+ case Luminance4Alpha4:
+ return GL2.GL_LUMINANCE4_ALPHA4;
+ case Luminance6Alpha2:
+ return GL2.GL_LUMINANCE6_ALPHA2;
+ case Luminance8Alpha8:
+ return GL2.GL_LUMINANCE8_ALPHA8;
+ case Luminance12Alpha4:
+ return GL2.GL_LUMINANCE12_ALPHA4;
+ case Luminance12Alpha12:
+ return GL2.GL_LUMINANCE12_ALPHA12;
+ case Luminance16Alpha16:
+ return GL2.GL_LUMINANCE16_ALPHA16;
+ case R3G3B2:
+ return GL2GL3.GL_R3_G3_B2;
+ case RGB4:
+ return GL2GL3.GL_RGB4;
+ case RGB5:
+ return GL2GL3.GL_RGB5;
+ case RGB10:
+ return GL.GL_RGB10;
+ case RGB12:
+ return GL2GL3.GL_RGB12;
+ case RGB16:
+ return GL2GL3.GL_RGB16;
+ case RGBA2:
+ return GL2GL3.GL_RGBA2;
+ case RGBA4:
+ return GL.GL_RGBA4;
+ case RGB5A1:
+ return GL.GL_RGB5_A1;
+ case RGB10A2:
+ return GL.GL_RGB10_A2;
+ case RGBA12:
+ return GL2GL3.GL_RGBA12;
+ case RGBA16:
+ return GL2GL3.GL_RGBA16;
+ case Depth:
+ return GL2ES2.GL_DEPTH_COMPONENT;
+ case Depth16:
+ return GL.GL_DEPTH_COMPONENT16;
+ case Depth24:
+ return GL.GL_DEPTH_COMPONENT24;
+ case Depth32:
+ return GL.GL_DEPTH_COMPONENT32;
+ case Depth32F:
+ return GL2GL3.GL_DEPTH_COMPONENT32F;
+ case RGB16F:
+ return GL2ES2.GL_RGB16F;
+ case RGB32F:
+ return GL.GL_RGB32F;
+ case RGBA16F:
+ return GL2ES2.GL_RGBA16F;
+ case RGBA32F:
+ return GL.GL_RGBA32F;
+ case Alpha16F:
+ return GL2.GL_ALPHA16F;
+ case Alpha32F:
+ return GL2.GL_ALPHA32F;
+ case Luminance16F:
+ return GL2.GL_LUMINANCE16F;
+ case Luminance32F:
+ return GL2.GL_LUMINANCE32F;
+ case LuminanceAlpha16F:
+ return GL2.GL_LUMINANCE_ALPHA16F;
+ case LuminanceAlpha32F:
+ return GL2.GL_LUMINANCE_ALPHA32F;
+ case Intensity16F:
+ return GL2.GL_INTENSITY16F;
+ case Intensity32F:
+ return GL2.GL_INTENSITY32F;
+ case R8:
+ return GL2ES2.GL_R8;
+ case R16:
+ return GL2GL3.GL_R16;
+ case RG8:
+ return GL2ES2.GL_RG8;
+ case RG16:
+ return GL2GL3.GL_RG16;
+ case R16F:
+ return GL2ES2.GL_R16F;
+ case R32F:
+ return GL2GL3.GL_R32F;
+ case RG16F:
+ return GL2ES2.GL_RG16F;
+ case RG32F:
+ return GL2GL3.GL_RG32F;
+ case R8I:
+ return GL2GL3.GL_R8I;
+ case R8UI:
+ return GL2GL3.GL_R8UI;
+ case R16I:
+ return GL2GL3.GL_R16I;
+ case R16UI:
+ return GL2GL3.GL_R16UI;
+ case R32I:
+ return GL2GL3.GL_R32I;
+ case R32UI:
+ return GL2GL3.GL_R32UI;
+ case RG8I:
+ return GL2GL3.GL_RG8I;
+ case RG8UI:
+ return GL2GL3.GL_RG8UI;
+ case RG16I:
+ return GL2GL3.GL_RG16I;
+ case RG16UI:
+ return GL2GL3.GL_RG16UI;
+ case RG32I:
+ return GL2GL3.GL_RG32I;
+ case RG32UI:
+ return GL2GL3.GL_RG32UI;
+ default:
+ break;
+ }
+ throw new IllegalArgumentException("Incorrect format set: " + format);
+ }
+
+ public static int getGLPixelDataType(final PixelDataType type) {
+ switch (type) {
+ case Byte:
+ return GL.GL_BYTE;
+ case Float:
+ return GL.GL_FLOAT;
+ case HalfFloat:
+ return GL.GL_HALF_FLOAT;
+ case Short:
+ return GL.GL_SHORT;
+ case UnsignedShort:
+ return GL.GL_UNSIGNED_SHORT;
+ case Int:
+ return GL2ES2.GL_INT;
+ case UnsignedInt:
+ return GL.GL_UNSIGNED_INT;
+ case UnsignedByte:
+ return GL.GL_UNSIGNED_BYTE;
+ default:
+ throw new Error("Unhandled type: " + type);
+ }
+ }
+
+ public static int getGLPixelFormat(final ImageDataFormat format) {
+ switch (format) {
+ case RGBA:
+ return GL.GL_RGBA;
+ case RGB:
+ return GL.GL_RGB;
+ case Alpha:
+ return GL.GL_ALPHA;
+ case Luminance:
+ return GL.GL_LUMINANCE;
+ case Intensity:
+ return GL2.GL_INTENSITY;
+ case LuminanceAlpha:
+ return GL.GL_LUMINANCE_ALPHA;
+ case Depth:
+ return GL2ES2.GL_DEPTH_COMPONENT;
+ case BGR:
+ return GL2GL3.GL_BGR;
+ case BGRA:
+ return GL.GL_BGRA;
+ case Red:
+ return GL2ES2.GL_RED;
+ case Blue:
+ return GL2GL3.GL_BLUE;
+ case Green:
+ return GL2GL3.GL_GREEN;
+ case ColorIndex:
+ return GL2.GL_COLOR_INDEX;
+ case StencilIndex:
+ return GL2ES2.GL_STENCIL_INDEX;
+ case PrecompressedDXT1:
+ break;
+ case PrecompressedDXT1A:
+ break;
+ case PrecompressedDXT3:
+ break;
+ case PrecompressedDXT5:
+ break;
+ case PrecompressedLATC_L:
+ break;
+ case PrecompressedLATC_LA:
+ break;
+ case RG:
+ break;
+ default:
+ break;
+ }
+ throw new IllegalArgumentException("Incorrect format set: " + format);
+ }
+
+ public static int getGLPixelFormatFromStoreFormat(final TextureStoreFormat format) {
+ switch (format) {
+ case RGBA2:
+ case RGBA4:
+ case RGBA8:
+ case RGB5A1:
+ case RGB10A2:
+ case RGBA12:
+ case RGBA16:
+ case CompressedRGBA:
+ case NativeDXT1A:
+ case NativeDXT3:
+ case NativeDXT5:
+ case RGBA16F:
+ case RGBA32F:
+ return GL.GL_RGBA;
+ case R3G3B2:
+ case RGB4:
+ case RGB5:
+ case RGB8:
+ case RGB10:
+ case RGB12:
+ case RGB16:
+ case CompressedRGB:
+ case NativeDXT1:
+ case RGB16F:
+ case RGB32F:
+ return GL.GL_RGB;
+ case Alpha4:
+ case Alpha8:
+ case Alpha12:
+ case Alpha16:
+ case Alpha16F:
+ case Alpha32F:
+ return GL.GL_ALPHA;
+ case Luminance4:
+ case Luminance8:
+ case Luminance12:
+ case Luminance16:
+ case Luminance16F:
+ case Luminance32F:
+ case CompressedLuminance:
+ case NativeLATC_L:
+ return GL.GL_LUMINANCE;
+ case Intensity4:
+ case Intensity8:
+ case Intensity12:
+ case Intensity16:
+ case Intensity16F:
+ case Intensity32F:
+ return GL2.GL_INTENSITY;
+ case Luminance4Alpha4:
+ case Luminance6Alpha2:
+ case Luminance8Alpha8:
+ case Luminance12Alpha4:
+ case Luminance12Alpha12:
+ case Luminance16Alpha16:
+ case LuminanceAlpha16F:
+ case LuminanceAlpha32F:
+ case CompressedLuminanceAlpha:
+ case NativeLATC_LA:
+ return GL.GL_LUMINANCE_ALPHA;
+ case Depth:
+ case Depth16:
+ case Depth24:
+ case Depth32:
+ case Depth32F:
+ return GL2ES2.GL_DEPTH_COMPONENT;
+ case R8:
+ case R16:
+ case R16F:
+ case R32F:
+ case R8I:
+ case R8UI:
+ case R16I:
+ case R16UI:
+ case R32I:
+ case R32UI:
+ case CompressedRed:
+ return GL2ES2.GL_RED;
+ case RG8:
+ case RG16:
+ case RG16F:
+ case RG32F:
+ case RG8I:
+ case RG8UI:
+ case RG16I:
+ case RG16UI:
+ case RG32I:
+ case RG32UI:
+ case CompressedRG:
+ return GL2ES2.GL_RG;
+ default:
+ break;
+ }
+ throw new IllegalArgumentException("Incorrect format set: " + format);
+ }
+
+ public static int getGLDepthTextureMode(final DepthTextureMode mode) {
+ switch (mode) {
+ case Alpha:
+ return GL.GL_ALPHA;
+ case Luminance:
+ return GL.GL_LUMINANCE;
+ case Intensity:
+ default:
+ return GL2.GL_INTENSITY;
+ }
+ }
+
+ public static int getGLDepthTextureCompareMode(final DepthTextureCompareMode mode) {
+ switch (mode) {
+ case RtoTexture:
+ return GL2.GL_COMPARE_R_TO_TEXTURE;
+ case None:
+ default:
+ return GL.GL_NONE;
+ }
+ }
+
+ public static int getGLDepthTextureCompareFunc(final DepthTextureCompareFunc func) {
+ switch (func) {
+ case GreaterThanEqual:
+ return GL.GL_GEQUAL;
+ case LessThanEqual:
+ default:
+ return GL.GL_LEQUAL;
+ }
+ }
+
+ public static int getGLMagFilter(final MagnificationFilter magFilter) {
+ switch (magFilter) {
+ case Bilinear:
+ return GL.GL_LINEAR;
+ case NearestNeighbor:
+ default:
+ return GL.GL_NEAREST;
+
+ }
+ }
+
+ public static int getGLMinFilter(final MinificationFilter filter) {
+ switch (filter) {
+ case BilinearNoMipMaps:
+ return GL.GL_LINEAR;
+ case Trilinear:
+ return GL.GL_LINEAR_MIPMAP_LINEAR;
+ case BilinearNearestMipMap:
+ return GL.GL_LINEAR_MIPMAP_NEAREST;
+ case NearestNeighborNoMipMaps:
+ return GL.GL_NEAREST;
+ case NearestNeighborNearestMipMap:
+ return GL.GL_NEAREST_MIPMAP_NEAREST;
+ case NearestNeighborLinearMipMap:
+ return GL.GL_NEAREST_MIPMAP_LINEAR;
+ }
+ throw new IllegalArgumentException("invalid MinificationFilter type: " + filter);
+ }
+
+ public static int getGLEnvMode(final ApplyMode apply) {
+ switch (apply) {
+ case Replace:
+ return GL.GL_REPLACE;
+ case Blend:
+ return GL.GL_BLEND;
+ case Combine:
+ return GL2ES1.GL_COMBINE;
+ case Decal:
+ return GL2ES1.GL_DECAL;
+ case Add:
+ return GL2ES1.GL_ADD;
+ case Modulate:
+ return GL2ES1.GL_MODULATE;
+ }
+ throw new IllegalArgumentException("invalid ApplyMode type: " + apply);
+ }
+
+ public static int getPerspHint(final CorrectionType type) {
+ switch (type) {
+ case Perspective:
+ return GL.GL_NICEST;
+ case Affine:
+ return GL.GL_FASTEST;
+ }
+ throw new IllegalArgumentException("unknown correction type: " + type);
+ }
+
+ public static int getGLCombineOpRGB(final CombinerOperandRGB operand) {
+ switch (operand) {
+ case SourceColor:
+ return GL.GL_SRC_COLOR;
+ case OneMinusSourceColor:
+ return GL.GL_ONE_MINUS_SRC_COLOR;
+ case SourceAlpha:
+ return GL.GL_SRC_ALPHA;
+ case OneMinusSourceAlpha:
+ return GL.GL_ONE_MINUS_SRC_ALPHA;
+ }
+ throw new IllegalArgumentException("invalid CombinerOperandRGB type: " + operand);
+ }
+
+ public static int getGLCombineOpAlpha(final CombinerOperandAlpha operand) {
+ switch (operand) {
+ case SourceAlpha:
+ return GL.GL_SRC_ALPHA;
+ case OneMinusSourceAlpha:
+ return GL.GL_ONE_MINUS_SRC_ALPHA;
+ }
+ throw new IllegalArgumentException("invalid CombinerOperandAlpha type: " + operand);
+ }
+
+ public static int getGLCombineSrc(final CombinerSource combineSrc) {
+ switch (combineSrc) {
+ case CurrentTexture:
+ return GL.GL_TEXTURE;
+ case PrimaryColor:
+ return GL2ES1.GL_PRIMARY_COLOR;
+ case Constant:
+ return GL2ES1.GL_CONSTANT;
+ case Previous:
+ return GL2ES1.GL_PREVIOUS;
+ case TextureUnit0:
+ return GL.GL_TEXTURE0;
+ case TextureUnit1:
+ return GL.GL_TEXTURE1;
+ case TextureUnit2:
+ return GL.GL_TEXTURE2;
+ case TextureUnit3:
+ return GL.GL_TEXTURE3;
+ case TextureUnit4:
+ return GL.GL_TEXTURE4;
+ case TextureUnit5:
+ return GL.GL_TEXTURE5;
+ case TextureUnit6:
+ return GL.GL_TEXTURE6;
+ case TextureUnit7:
+ return GL.GL_TEXTURE7;
+ case TextureUnit8:
+ return GL.GL_TEXTURE8;
+ case TextureUnit9:
+ return GL.GL_TEXTURE9;
+ case TextureUnit10:
+ return GL.GL_TEXTURE10;
+ case TextureUnit11:
+ return GL.GL_TEXTURE11;
+ case TextureUnit12:
+ return GL.GL_TEXTURE12;
+ case TextureUnit13:
+ return GL.GL_TEXTURE13;
+ case TextureUnit14:
+ return GL.GL_TEXTURE14;
+ case TextureUnit15:
+ return GL.GL_TEXTURE15;
+ case TextureUnit16:
+ return GL.GL_TEXTURE16;
+ case TextureUnit17:
+ return GL.GL_TEXTURE17;
+ case TextureUnit18:
+ return GL.GL_TEXTURE18;
+ case TextureUnit19:
+ return GL.GL_TEXTURE19;
+ case TextureUnit20:
+ return GL.GL_TEXTURE20;
+ case TextureUnit21:
+ return GL.GL_TEXTURE21;
+ case TextureUnit22:
+ return GL.GL_TEXTURE22;
+ case TextureUnit23:
+ return GL.GL_TEXTURE23;
+ case TextureUnit24:
+ return GL.GL_TEXTURE24;
+ case TextureUnit25:
+ return GL.GL_TEXTURE25;
+ case TextureUnit26:
+ return GL.GL_TEXTURE26;
+ case TextureUnit27:
+ return GL.GL_TEXTURE27;
+ case TextureUnit28:
+ return GL.GL_TEXTURE28;
+ case TextureUnit29:
+ return GL.GL_TEXTURE29;
+ case TextureUnit30:
+ return GL.GL_TEXTURE30;
+ case TextureUnit31:
+ return GL.GL_TEXTURE31;
+ }
+ throw new IllegalArgumentException("invalid CombinerSource type: " + combineSrc);
+ }
+
+ public static int getGLCombineFuncAlpha(final CombinerFunctionAlpha combineFunc) {
+ switch (combineFunc) {
+ case Modulate:
+ return GL2ES1.GL_MODULATE;
+ case Replace:
+ return GL.GL_REPLACE;
+ case Add:
+ return GL2ES1.GL_ADD;
+ case AddSigned:
+ return GL2ES1.GL_ADD_SIGNED;
+ case Subtract:
+ return GL2ES1.GL_SUBTRACT;
+ case Interpolate:
+ return GL2ES1.GL_INTERPOLATE;
+ }
+ throw new IllegalArgumentException("invalid CombinerFunctionAlpha type: " + combineFunc);
+ }
+
+ public static int getGLCombineFuncRGB(final CombinerFunctionRGB combineFunc) {
+ switch (combineFunc) {
+ case Modulate:
+ return GL2ES1.GL_MODULATE;
+ case Replace:
+ return GL.GL_REPLACE;
+ case Add:
+ return GL2ES1.GL_ADD;
+ case AddSigned:
+ return GL2ES1.GL_ADD_SIGNED;
+ case Subtract:
+ return GL2ES1.GL_SUBTRACT;
+ case Interpolate:
+ return GL2ES1.GL_INTERPOLATE;
+ case Dot3RGB:
+ return GL2ES1.GL_DOT3_RGB;
+ case Dot3RGBA:
+ return GL2ES1.GL_DOT3_RGBA;
+ }
+ throw new IllegalArgumentException("invalid CombinerFunctionRGB type: " + combineFunc);
+ }
+}