diff options
Diffstat (limited to 'trunk/ardor3d-jogl')
63 files changed, 9689 insertions, 0 deletions
diff --git a/trunk/ardor3d-jogl/.classpath b/trunk/ardor3d-jogl/.classpath new file mode 100644 index 0000000..9f624f9 --- /dev/null +++ b/trunk/ardor3d-jogl/.classpath @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/ardor3d-core"/>
+ <classpathentry kind="lib" path="lib/jogl/gluegen-rt.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jogl/jogl.jar">
+ <attributes>
+ <attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="ardor3d-jogl/lib/jogl/native/windows-amd64"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/trunk/ardor3d-jogl/.project b/trunk/ardor3d-jogl/.project new file mode 100644 index 0000000..095e1c0 --- /dev/null +++ b/trunk/ardor3d-jogl/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>ardor3d-jogl</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/trunk/ardor3d-jogl/.settings/org.eclipse.core.resources.prefs b/trunk/ardor3d-jogl/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..dc6c01a --- /dev/null +++ b/trunk/ardor3d-jogl/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +#Wed Jan 07 11:33:09 PST 2009 +eclipse.preferences.version=1 +encoding/<project>=UTF-8 diff --git a/trunk/ardor3d-jogl/.settings/org.eclipse.jdt.core.prefs b/trunk/ardor3d-jogl/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..7858c9b --- /dev/null +++ b/trunk/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/trunk/ardor3d-jogl/.settings/org.eclipse.jdt.ui.prefs b/trunk/ardor3d-jogl/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..f479490 --- /dev/null +++ b/trunk/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 <http\://www.ardor3d.com/LICENSE>.\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/trunk/ardor3d-jogl/lib/jogl/COPYRIGHT.txt b/trunk/ardor3d-jogl/lib/jogl/COPYRIGHT.txt new file mode 100644 index 0000000..360d374 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/COPYRIGHT.txt @@ -0,0 +1,31 @@ + +Copyright 2007 Sun Microsystems, Inc., 4150 Network +Circle, Santa Clara, California 95054, U.S.A. All rights +reserved. + +U.S. Government Rights - Commercial software. Government +users are subject to the Sun Microsystems, Inc. +standard license agreement and applicable provisions of +the FAR and its supplements. + +Use is subject to license terms. + +This distribution may include materials developed by third +parties. + +Sun, Sun Microsystems, the Sun logo and Java are trademarks +or registered trademarks of Sun Microsystems, Inc. in the +U.S. and other countries. + +OpenGL is a registered trademark of Silicon Graphics, Inc. + +This product is covered and controlled by U.S. Export +Control laws and may be subject to the export or import +laws in other countries. Nuclear, missile, chemical +biological weapons or nuclear maritime end uses or end +users, whether direct or indirect, are strictly prohibited. +Export or reexport to countries subject to U.S. embargo or +to entities identified on U.S. export exclusion lists, +including, but not limited to, the denied persons and +specially designated nationals lists is strictly prohibited. + diff --git a/trunk/ardor3d-jogl/lib/jogl/LICENSE-JOGL-1.1.2-pre-20080523.txt b/trunk/ardor3d-jogl/lib/jogl/LICENSE-JOGL-1.1.2-pre-20080523.txt new file mode 100644 index 0000000..cd35e88 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/LICENSE-JOGL-1.1.2-pre-20080523.txt @@ -0,0 +1,152 @@ +JOGL is released under the BSD license. The full license terms follow: + + Copyright (c) 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistribution of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistribution in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of Sun Microsystems, Inc. or the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + This software is provided "AS IS," without a warranty of any kind. ALL + EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + You acknowledge that this software is not designed or intended for use + in the design, construction, operation or maintenance of any nuclear + facility. + +The JOGL source tree contains code ported from the OpenGL sample +implementation by Silicon Graphics, Inc. This code is licensed under +the SGI Free Software License B (Sun is redistributing the modified code +under a slightly modified, alternative license, which is described two +paragraphs below after "NOTE:"): + + License Applicability. Except to the extent portions of this file are + made subject to an alternative license as permitted in the SGI Free + Software License B, Version 1.1 (the "License"), the contents of this + file are subject only to the provisions of the License. You may not use + this file except in compliance with the License. You may obtain a copy + of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + + http://oss.sgi.com/projects/FreeB + + Note that, as provided in the License, the Software is distributed on an + "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + + NOTE: The Original Code (as defined below) has been licensed to Sun + Microsystems, Inc. ("Sun") under the SGI Free Software License B + (Version 1.1), shown above ("SGI License"). Pursuant to Section + 3.2(3) of the SGI License, Sun is distributing the Covered Code to + you under an alternative license ("Alternative License"). This + Alternative License includes all of the provisions of the SGI License + except that Section 2.2 and 11 are omitted. Any differences between + the Alternative License and the SGI License are offered solely by Sun + and not by SGI. + + Original Code. The Original Code is: OpenGL Sample Implementation, + Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + Copyright in any portions created by third parties is as indicated + elsewhere herein. All Rights Reserved. + + Additional Notice Provisions: The application programming interfaces + established by SGI in conjunction with the Original Code are The + OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + Window System(R) (Version 1.3), released October 19, 1998. This software + was created using the OpenGL(R) version 1.2.1 Sample Implementation + published by SGI, but has not been independently verified as being + compliant with the OpenGL(R) version 1.2.1 Specification. + + +The JOGL source tree contains code from the LWJGL project which is +similarly covered by the BSD license: + + Copyright (c) 2002-2004 LWJGL Project + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of 'LWJGL' nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The JOGL source tree also contains a Java port of Brian Paul's Tile +Rendering library, used with permission of the author under the BSD +license instead of the original LGPL: + + Copyright (c) 1997-2005 Brian Paul. All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistribution of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistribution in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of Brian Paul or the names of contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + This software is provided "AS IS," without a warranty of any + kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + EXCLUDED. THE COPYRIGHT HOLDERS AND CONTRIBUTORS SHALL NOT BE + LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO + EVENT WILL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY + LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + INABILITY TO USE THIS SOFTWARE, EVEN IF THE COPYRIGHT HOLDERS OR + CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. diff --git a/trunk/ardor3d-jogl/lib/jogl/gluegen-rt.jar b/trunk/ardor3d-jogl/lib/jogl/gluegen-rt.jar Binary files differnew file mode 100644 index 0000000..2251781 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/gluegen-rt.jar diff --git a/trunk/ardor3d-jogl/lib/jogl/jogl.jar b/trunk/ardor3d-jogl/lib/jogl/jogl.jar Binary files differnew file mode 100644 index 0000000..7293e6d --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/jogl.jar diff --git a/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libgluegen-rt.so b/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libgluegen-rt.so Binary files differnew file mode 100644 index 0000000..1482430 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libgluegen-rt.so diff --git a/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl.so b/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl.so Binary files differnew file mode 100644 index 0000000..51adbdb --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl.so diff --git a/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl_awt.so b/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl_awt.so Binary files differnew file mode 100644 index 0000000..7ea1354 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl_awt.so diff --git a/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl_cg.so b/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl_cg.so Binary files differnew file mode 100644 index 0000000..95a0374 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/linux-i586/libjogl_cg.so diff --git a/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libgluegen-rt.jnilib b/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libgluegen-rt.jnilib Binary files differnew file mode 100644 index 0000000..1956280 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libgluegen-rt.jnilib diff --git a/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl.jnilib b/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl.jnilib Binary files differnew file mode 100644 index 0000000..85dac01 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl.jnilib diff --git a/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl_awt.jnilib b/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl_awt.jnilib Binary files differnew file mode 100644 index 0000000..2f16fbf --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl_awt.jnilib diff --git a/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl_cg.jnilib b/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl_cg.jnilib Binary files differnew file mode 100644 index 0000000..5627121 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/macosx-universal/libjogl_cg.jnilib diff --git a/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/gluegen-rt.dll b/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/gluegen-rt.dll Binary files differnew file mode 100644 index 0000000..a7eb6f5 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/gluegen-rt.dll diff --git a/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl.dll b/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl.dll Binary files differnew file mode 100644 index 0000000..990986f --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl.dll diff --git a/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl_awt.dll b/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl_awt.dll Binary files differnew file mode 100644 index 0000000..d247b4a --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl_awt.dll diff --git a/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl_cg.dll b/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl_cg.dll Binary files differnew file mode 100644 index 0000000..9e2f371 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/windows-amd64/jogl_cg.dll diff --git a/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/gluegen-rt.dll b/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/gluegen-rt.dll Binary files differnew file mode 100644 index 0000000..9b373f3 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/gluegen-rt.dll diff --git a/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl.dll b/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl.dll Binary files differnew file mode 100644 index 0000000..ce466f0 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl.dll diff --git a/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl_awt.dll b/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl_awt.dll Binary files differnew file mode 100644 index 0000000..2f0b6a6 --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl_awt.dll diff --git a/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl_cg.dll b/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl_cg.dll Binary files differnew file mode 100644 index 0000000..985781d --- /dev/null +++ b/trunk/ardor3d-jogl/lib/jogl/native/windows_i586/jogl_cg.dll diff --git a/trunk/ardor3d-jogl/pom.xml b/trunk/ardor3d-jogl/pom.xml new file mode 100644 index 0000000..c810d3e --- /dev/null +++ b/trunk/ardor3d-jogl/pom.xml @@ -0,0 +1,51 @@ +<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.8-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>net.java.dev.jogl</groupId> + <artifactId>jogl</artifactId> + </dependency> + <!-- + NOTE: This code commented out by Petter 090224, since it isn't really ready to be used, + and since it is at the moment more work than it is worth to get it ready. Later on, when + we have solved some more fundamental problems, it is probably time to revisit this. + --> + + <!-- dependency> + <groupId>net.java.dev.jogl</groupId> + <artifactId>jogl-natives</artifactId> + </dependency --> + <dependency> + <groupId>com.projectdarkstar.ext.net.java.dev.gluegen</groupId> + <artifactId>gluegen-rt</artifactId> + </dependency> + </dependencies> +</project> + diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java new file mode 100644 index 0000000..48e594d --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java @@ -0,0 +1,45 @@ +/** + * 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 javax.media.opengl.GLCapabilities; + +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(); + 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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglAwtCanvas.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglAwtCanvas.java new file mode 100644 index 0000000..dd5cc8e --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglAwtCanvas.java @@ -0,0 +1,70 @@ +/** + * 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.GLCanvas; + +import com.ardor3d.annotation.MainThread; +import com.ardor3d.framework.Canvas; +import com.ardor3d.framework.DisplaySettings; + +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; + + public JoglAwtCanvas(final DisplaySettings settings, final JoglCanvasRenderer canvasRenderer) { + super(CapsUtil.getCapsForSettings(settings)); + _settings = settings; + _canvasRenderer = canvasRenderer; + + setFocusable(true); + requestFocus(); + setSize(_settings.getWidth(), _settings.getHeight()); + setIgnoreRepaint(true); + setAutoSwapBufferMode(false); + + _canvasRenderer.setContext(getContext()); + } + + @MainThread + public void init() { + if (_inited) { + return; + } + + _canvasRenderer.init(_settings, true); // true - do swap in renderer. + _inited = true; + } + + public void draw(final CountDownLatch latch) { + if (!_inited) { + init(); + } + + if (isShowing()) { + _canvasRenderer.draw(); + } + if (latch != null) { + latch.countDown(); + } + } + + public JoglCanvasRenderer getCanvasRenderer() { + return _canvasRenderer; + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvas.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvas.java new file mode 100644 index 0000000..0a85152 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvas.java @@ -0,0 +1,280 @@ +/** + * 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.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.GLContext; +import javax.media.opengl.GLException; + +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); // To change body of overridden methods use File | Settings | File Templates. + } + + @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) { + // TODO Auto-generated method stub + } + + public void setVSyncEnabled(final boolean enabled) { + if (GLContext.getCurrent() != null) { + // Release the OpenGL resources. + GLContext.getCurrent().getGL().setSwapInterval(enabled ? 1 : 0); + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvasRenderer.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvasRenderer.java new file mode 100644 index 0000000..555ceda --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglCanvasRenderer.java @@ -0,0 +1,248 @@ +/**
+ * 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.logging.Logger;
+
+import javax.media.opengl.DebugGL;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+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());
+
+ // NOTE: This code commented out by Petter 090224, since it isn't really ready to be used,
+ // and since it is at the moment more work than it is worth to get it ready. Later on, when
+ // we have solved some more fundamental problems, it is probably time to revisit this.
+
+ // ensure availability of JOGL natives
+ // {
+ // final String[] libraryPaths = JoglLibraryPaths.getLibraryPaths(System.getProperty("os.name"), System
+ // .getProperty("os.arch"));
+ //
+ // try {
+ // NativeLoader.makeLibrariesAvailable(libraryPaths);
+ // } catch (final Exception e) {
+ // ; // ignore
+ // }
+ // }
+
+ 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;
+ int attempt = 1;
+ while ((value = _context.makeCurrent()) == GLContext.CONTEXT_NOT_CURRENT) {
+ if (attempt == MAX_CONTEXT_GRAB_ATTEMPTS) {
+ // failed, throw exception
+ throw new Ardor3dException("Failed to claim OpenGL context.");
+ }
+ attempt++;
+ try {
+ Thread.sleep(5);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ }
+ 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())) {
+ _context.release();
+ }
+ }
+
+ @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().createExternalGLContext();
+ }
+
+ _context.makeCurrent();
+
+ // 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());
+ }
+ }
+
+ 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 DebugGL(_context.getGL()));
+ _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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglLibraryPaths.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglLibraryPaths.java new file mode 100644 index 0000000..ba92685 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglLibraryPaths.java @@ -0,0 +1,59 @@ +/** + * 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; + +/** + * 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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java new file mode 100644 index 0000000..61716d7 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglContextCapabilities.java @@ -0,0 +1,242 @@ +/** + * 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.renderer.jogl; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import javax.media.opengl.GL; +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(GL.GL_MAX_TEXTURE_LOD_BIAS_EXT, buf); + _maxTextureLodBias = buf.get(0); + } else { + _maxTextureLodBias = 0f; + } + + gl.glGetIntegerv(GL.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"); + + if (_glslSupported) { + gl.glGetIntegerv(GL.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(GL.GL_MAX_COLOR_ATTACHMENTS_EXT, 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(GL.GL_MAX_SAMPLES_EXT, 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(GL.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(GL.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(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, buf); + _numVertexTexUnits = buf.get(0); + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_IMAGE_UNITS_ARB, buf); + _numFragmentTexUnits = buf.get(0); + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_COORDS_ARB, 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(GL.GL_SHADING_LANGUAGE_VERSION); + } catch (final Exception e) { + _shadingLanguageVersion = "Unable to retrieve shading language version."; + } + } else { + _shadingLanguageVersion = "Not supported."; + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglPbufferTextureRenderer.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglPbufferTextureRenderer.java new file mode 100644 index 0000000..9003eb4 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglPbufferTextureRenderer.java @@ -0,0 +1,367 @@ +/** + * 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.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.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(); + final GLCapabilities caps = new GLCapabilities(); + 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(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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglRenderer.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglRenderer.java new file mode 100644 index 0000000..88c9bbf --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglRenderer.java @@ -0,0 +1,1747 @@ +/** + * 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.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.GLContext; +import javax.media.opengl.GLException; +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.AbstractBufferData.VBOAccessMode; +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.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 |= GL.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, GL.GL_PROJECTION); + gl.glPushMatrix(); + gl.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.glOrtho(0, viewportWidth, 0, viewportHeight, -1, 1); + JoglRendererUtil.switchMode(matRecord, GL.GL_MODELVIEW); + gl.glPushMatrix(); + gl.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, GL.GL_PROJECTION); + gl.glPopMatrix(); + JoglRendererUtil.switchMode(matRecord, GL.GL_MODELVIEW); + gl.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() != GL.GL_RESCALE_NORMAL) { + if (rendRecord.getNormalMode() == GL.GL_NORMALIZE) { + gl.glDisable(GL.GL_NORMALIZE); + } + gl.glEnable(GL.GL_RESCALE_NORMAL); + rendRecord.setNormalMode(GL.GL_RESCALE_NORMAL); + } else if (rendRecord.getNormalMode() != GL.GL_NORMALIZE) { + if (rendRecord.getNormalMode() == GL.GL_RESCALE_NORMAL) { + gl.glDisable(GL.GL_RESCALE_NORMAL); + } + gl.glEnable(GL.GL_NORMALIZE); + rendRecord.setNormalMode(GL.GL_NORMALIZE); + } + } else { + if (rendRecord.getNormalMode() == GL.GL_RESCALE_NORMAL) { + gl.glDisable(GL.GL_RESCALE_NORMAL); + } else if (rendRecord.getNormalMode() == GL.GL_NORMALIZE) { + gl.glDisable(GL.GL_NORMALIZE); + } + rendRecord.setNormalMode(GL.GL_ZERO); + } + } else { + if (!worldTransform.getMatrix().isIdentity()) { + // *might* be scaled... + if (rendRecord.getNormalMode() != GL.GL_NORMALIZE) { + if (rendRecord.getNormalMode() == GL.GL_RESCALE_NORMAL) { + gl.glDisable(GL.GL_RESCALE_NORMAL); + } + gl.glEnable(GL.GL_NORMALIZE); + rendRecord.setNormalMode(GL.GL_NORMALIZE); + } + } else { + // not scaled + if (rendRecord.getNormalMode() == GL.GL_RESCALE_NORMAL) { + gl.glDisable(GL.GL_RESCALE_NORMAL); + } else if (rendRecord.getNormalMode() == GL.GL_NORMALIZE) { + gl.glDisable(GL.GL_NORMALIZE); + } + rendRecord.setNormalMode(GL.GL_ZERO); + } + } + break; + case AlwaysNormalize: + if (rendRecord.getNormalMode() != GL.GL_NORMALIZE) { + if (rendRecord.getNormalMode() == GL.GL_RESCALE_NORMAL) { + gl.glDisable(GL.GL_RESCALE_NORMAL); + } + gl.glEnable(GL.GL_NORMALIZE); + rendRecord.setNormalMode(GL.GL_NORMALIZE); + } + break; + case UseProvided: + default: + if (rendRecord.getNormalMode() == GL.GL_RESCALE_NORMAL) { + gl.glDisable(GL.GL_RESCALE_NORMAL); + } else if (rendRecord.getNormalMode() == GL.GL_NORMALIZE) { + gl.glDisable(GL.GL_NORMALIZE); + } + rendRecord.setNormalMode(GL.GL_ZERO); + break; + } + } else { + if (rendRecord.getNormalMode() == GL.GL_RESCALE_NORMAL) { + gl.glDisable(GL.GL_RESCALE_NORMAL); + } else if (rendRecord.getNormalMode() == GL.GL_NORMALIZE) { + gl.glDisable(GL.GL_NORMALIZE); + } + rendRecord.setNormalMode(GL.GL_ZERO); + } + } + + public void applyDefaultColor(final ReadOnlyColorRGBA defaultColor) { + final GL gl = GLU.getCurrentGL(); + if (defaultColor != null) { + gl.glColor4f(defaultColor.getRed(), defaultColor.getGreen(), defaultColor.getBlue(), + defaultColor.getAlpha()); + } else { + gl.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.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(GL.GL_UNPACK_ROW_LENGTH, rowLength); + } + if (origSkipPixels != srcOffsetX) { + gl.glPixelStorei(GL.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(GL.GL_UNPACK_SKIP_ROWS, srcOffsetY); + } + if (origImageHeight != imageHeight) { + gl.glPixelStorei(GL.GL_UNPACK_IMAGE_HEIGHT, imageHeight); + } + if (origSkipImages != srcOffsetZ) { + gl.glPixelStorei(GL.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.glTexSubImage1D(GL.GL_TEXTURE_1D, 0, dstOffsetX, dstWidth, pixelFormat, GL.GL_UNSIGNED_BYTE, + source); + break; + case ThreeDimensional: + gl.glTexSubImage3D(GL.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(GL.GL_UNPACK_ROW_LENGTH, origRowLength); + } + // Restore skip pixels. + if (origSkipPixels != srcOffsetX) { + gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, origSkipPixels); + } + // Restore skip rows. + if (origSkipRows != srcOffsetY) { + gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, origSkipRows); + } + // Restore image height. + if (origImageHeight != imageHeight) { + gl.glPixelStorei(GL.GL_UNPACK_IMAGE_HEIGHT, origImageHeight); + } + // Restore skip images. + if (origSkipImages != srcOffsetZ) { + gl.glPixelStorei(GL.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, GL.GL_MODELVIEW); + gl.glPushMatrix(); + gl.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, GL.GL_MODELVIEW); + gl.glPopMatrix(); + } + + public void setupVertexData(final FloatBufferData vertexBufferData) { + final GL gl = GLU.getCurrentGL(); + + final FloatBuffer vertexBuffer = vertexBufferData != null ? vertexBufferData.getBuffer() : null; + + if (vertexBuffer == null) { + gl.glDisableClientState(GL.GL_VERTEX_ARRAY); + } else { + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + vertexBuffer.rewind(); + gl.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.glDisableClientState(GL.GL_NORMAL_ARRAY); + } else { + gl.glEnableClientState(GL.GL_NORMAL_ARRAY); + normalBuffer.rewind(); + gl.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.glDisableClientState(GL.GL_COLOR_ARRAY); + } else { + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + colorBuffer.rewind(); + gl.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.glDisableClientState(GL.GL_FOG_COORDINATE_ARRAY); + } else { + gl.glEnableClientState(GL.GL_FOG_COORDINATE_ARRAY); + fogBuffer.rewind(); + gl.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.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY); + + continue; + } + } else { + checkAndSetTextureArrayUnit(i, gl, rendRecord, caps); + + if (!valid || !wasOn) { + // enable state + gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + + // enable bit in tracking int + enabledTextures |= (2 << i); + } + + final FloatBufferData textureBufferData = textureCoords.get(i); + final FloatBuffer textureBuffer = textureBufferData.getBuffer(); + + gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + textureBuffer.rewind(); + gl.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.glDrawElementsInstancedEXT(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.glDrawElementsInstancedEXT(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.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB, 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.glBufferSubDataARB(GL.GL_ARRAY_BUFFER_ARB, 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.glBufferSubDataARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, 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.glBufferDataARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, 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.glEnableClientState(GL.GL_VERTEX_ARRAY); + JoglRendererUtil.setBoundVBO(rendRecord, vboID); + gl.glVertexPointer(data.getValuesPerTuple(), GL.GL_FLOAT, 0, 0); + } else { + gl.glDisableClientState(GL.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.glEnableClientState(GL.GL_NORMAL_ARRAY); + JoglRendererUtil.setBoundVBO(rendRecord, vboID); + gl.glNormalPointer(GL.GL_FLOAT, 0, 0); + } else { + gl.glDisableClientState(GL.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.glEnableClientState(GL.GL_COLOR_ARRAY); + JoglRendererUtil.setBoundVBO(rendRecord, vboID); + gl.glColorPointer(data.getValuesPerTuple(), GL.GL_FLOAT, 0, 0); + } else { + gl.glDisableClientState(GL.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.glEnableClientState(GL.GL_FOG_COORDINATE_ARRAY_EXT); + JoglRendererUtil.setBoundVBO(rendRecord, vboID); + gl.glFogCoordPointerEXT(GL.GL_FLOAT, 0, 0); + } else { + gl.glDisableClientState(GL.GL_FOG_COORDINATE_ARRAY_EXT); + } + } + + 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.glDisableClientState(GL.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.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + } + + // set our active vbo + JoglRendererUtil.setBoundVBO(rendRecord, vboID); + + // send data + gl.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.glDisableClientState(GL.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.glNormalPointer(GL.GL_FLOAT, 0, offsetBytes); + gl.glEnableClientState(GL.GL_NORMAL_ARRAY); + offsetBytes += normalCoords.getBufferLimit() * 4; + } else { + gl.glDisableClientState(GL.GL_NORMAL_ARRAY); + } + + if (colorCoords != null) { + updateVBO(colorCoords, rendRecord, vboID, offsetBytes); + gl.glColorPointer(colorCoords.getValuesPerTuple(), GL.GL_FLOAT, 0, offsetBytes); + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + offsetBytes += colorCoords.getBufferLimit() * 4; + } else { + gl.glDisableClientState(GL.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.glDisableClientState(GL.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.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + } + + // send data + gl.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.glVertexPointer(vertexCoords.getValuesPerTuple(), GL.GL_FLOAT, 0, offsetBytes); + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + } else { + gl.glDisableClientState(GL.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.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB, bufferSize, null, getGLVBOAccessMode(interleaved.getVboAccessMode())); + + int offset = 0; + if (normalCoords != null) { + normalCoords.getBuffer().rewind(); + gl.glBufferSubDataARB(GL.GL_ARRAY_BUFFER_ARB, offset, normalCoords.getBufferLimit() * 4, + normalCoords.getBuffer()); + offset += normalCoords.getBufferLimit() * 4; + } + if (colorCoords != null) { + colorCoords.getBuffer().rewind(); + gl.glBufferSubDataARB(GL.GL_ARRAY_BUFFER_ARB, 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.glBufferSubDataARB(GL.GL_ARRAY_BUFFER_ARB, offset, textureBufferData.getBufferLimit() * 4, + textureBuffer); + offset += textureBufferData.getBufferLimit() * 4; + } + } + } + } + if (vertexCoords != null) { + vertexCoords.getBuffer().rewind(); + gl.glBufferSubDataARB(GL.GL_ARRAY_BUFFER_ARB, 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.glDrawElementsInstancedEXT(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.glDrawElementsInstancedEXT(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.glDrawArraysInstancedEXT(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.glDrawArraysInstancedEXT(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.glGenBuffersARB(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_ARB; + switch (vboAccessMode) { + case StaticDraw: + glMode = GL.GL_STATIC_DRAW_ARB; + break; + case StaticRead: + glMode = GL.GL_STATIC_READ_ARB; + break; + case StaticCopy: + glMode = GL.GL_STATIC_COPY_ARB; + break; + case DynamicDraw: + glMode = GL.GL_DYNAMIC_DRAW_ARB; + break; + case DynamicRead: + glMode = GL.GL_DYNAMIC_READ_ARB; + break; + case DynamicCopy: + glMode = GL.GL_DYNAMIC_COPY_ARB; + break; + case StreamDraw: + glMode = GL.GL_STREAM_DRAW_ARB; + break; + case StreamRead: + glMode = GL.GL_STREAM_READ_ARB; + break; + case StreamCopy: + glMode = GL.GL_STREAM_COPY_ARB; + 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 = GL.GL_QUADS; + break; + case QuadStrip: + glMode = GL.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, GL.GL_MODELVIEW); + + loadMatrix(matrix); + } + + public void setProjectionMatrix(final FloatBuffer matrix) { + final RendererRecord matRecord = ContextManager.getCurrentContext().getRendererRecord(); + JoglRendererUtil.switchMode(matRecord, GL.GL_PROJECTION); + + loadMatrix(matrix); + } + + private void loadMatrix(final FloatBuffer matrix) { + GLU.getCurrentGL().glLoadMatrixf(matrix); + } + + public FloatBuffer getModelViewMatrix(final FloatBuffer store) { + return getMatrix(GL.GL_MODELVIEW_MATRIX, store); + } + + public FloatBuffer getProjectionMatrix(final FloatBuffer store) { + return getMatrix(GL.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 Back: + break; + case Front: + buffer = GL.GL_FRONT; + break; + case BackLeft: + buffer = GL.GL_BACK_LEFT; + break; + case BackRight: + buffer = GL.GL_BACK_RIGHT; + break; + case FrontLeft: + buffer = GL.GL_FRONT_LEFT; + break; + case FrontRight: + buffer = GL.GL_FRONT_RIGHT; + break; + case FrontAndBack: + buffer = GL.GL_FRONT_AND_BACK; + break; + case Left: + buffer = GL.GL_LEFT; + break; + case Right: + buffer = GL.GL_RIGHT; + break; + case Aux0: + buffer = GL.GL_AUX0; + break; + case Aux1: + buffer = GL.GL_AUX1; + break; + case Aux2: + buffer = GL.GL_AUX2; + break; + case Aux3: + buffer = GL.GL_AUX3; + break; + } + + GLU.getCurrentGL().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(GL.GL_LINE_STIPPLE); + lineRecord.stippled = true; + } + + if (!lineRecord.isValid() || stippleFactor != lineRecord.stippleFactor + || stipplePattern != lineRecord.stipplePattern) { + gl.glLineStipple(stippleFactor, stipplePattern); + lineRecord.stippleFactor = stippleFactor; + lineRecord.stipplePattern = stipplePattern; + } + } else if (!lineRecord.isValid() || lineRecord.stippled) { + gl.glDisable(GL.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.glPointSize(pointSize); + if (antialiased) { + gl.glEnable(GL.GL_POINT_SMOOTH); + gl.glHint(GL.GL_POINT_SMOOTH_HINT, GL.GL_NICEST); + } + + if (isSprite && context.getCapabilities().isPointSpritesSupported()) { + gl.glEnable(GL.GL_POINT_SPRITE_ARB); + gl.glTexEnvi(GL.GL_POINT_SPRITE_ARB, GL.GL_COORD_REPLACE_ARB, GL.GL_TRUE); + } + + if (useDistanceAttenuation && context.getCapabilities().isPointParametersSupported()) { + gl.glPointParameterfvARB(GL.GL_POINT_DISTANCE_ATTENUATION_ARB, attenuationCoefficients); + gl.glPointParameterfARB(GL.GL_POINT_SIZE_MIN_ARB, minPointSize); + gl.glPointParameterfARB(GL.GL_POINT_SIZE_MAX_ARB, 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.glGenLists(1); + + gl.glNewList(id, GL.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().glEndList(); + } + + /** + * Draw the given display list. + */ + public void renderDisplayList(final int displayListID) { + final GL gl = GLU.getCurrentGL(); + + gl.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.glClientActiveTexture(GL.GL_TEXTURE0 + unit); + record.setCurrentTextureArraysUnit(unit); + } + } +}
\ No newline at end of file diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRenderer.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRenderer.java new file mode 100644 index 0000000..3110ff0 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRenderer.java @@ -0,0 +1,569 @@ +/** + * 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.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.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_EXT + 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.glGenerateMipmapEXT(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.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT + colorsAdded, + GL.GL_TEXTURE_2D, tex.getTextureIdForContext(context.getGlContextRep()), 0); + } else if (tex.getType() == Type.CubeMap) { + gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT + 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.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, + GL.GL_TEXTURE_2D, tex.getTextureIdForContext(context.getGlContextRep()), 0); + } else if (tex.getType() == Type.CubeMap) { + gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, + 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.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, + GL.GL_RENDERBUFFER_EXT, _depthRBID); + _usingDepthRB = true; + } + + setDrawBuffers(colorsAdded); + setReadBuffer(colorsAdded != 0 ? GL.GL_COLOR_ATTACHMENT0_EXT : 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.glGenerateMipmapEXT(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.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_RENDERBUFFER_EXT, + 0); + + // Setup depth texture into FBO + if (tex.getType() == Type.TwoDimensional) { + gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_TEXTURE_2D, + textureId, 0); + } else if (tex.getType() == Type.CubeMap) { + gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, + 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.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, + textureId, 0); + } else if (tex.getType() == Type.CubeMap) { + gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, + JoglTextureStateUtil.getGLCubeMapFace(((TextureCubeMap) tex).getCurrentRTTFace()), textureId, 0); + } else { + throw new IllegalArgumentException("Can not render to texture of type: " + tex.getType()); + } + + // setup depth RB + gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT, + _depthRBID); + + setDrawBuffer(GL.GL_COLOR_ATTACHMENT0_EXT); + setReadBuffer(GL.GL_COLOR_ATTACHMENT0_EXT); + } + + // Check FBO complete + checkFBOComplete(_fboID); + } + + private void setReadBuffer(final int attachVal) { + final GL gl = GLU.getCurrentGL(); + + gl.glReadBuffer(attachVal); + } + + private void setDrawBuffer(final int attachVal) { + final GL gl = GLU.getCurrentGL(); + + gl.glDrawBuffer(attachVal); + } + + private void setDrawBuffers(final int maxEntry) { + final GL gl = GLU.getCurrentGL(); + + if (maxEntry <= 1) { + setDrawBuffer(maxEntry != 0 ? GL.GL_COLOR_ATTACHMENT0_EXT : GL.GL_NONE); + } else { + // We should only get to this point if we support ARBDrawBuffers. + _attachBuffer.clear(); + _attachBuffer.limit(maxEntry); + gl.glDrawBuffersARB(_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.glGenerateMipmapEXT(JoglTextureStateUtil.getGLType(tex.getType())); + } + } + + @Override + protected void setMSFBO() { + final GL gl = GLU.getCurrentGL(); + + gl.glBindFramebufferEXT(GL.GL_DRAW_FRAMEBUFFER_EXT, _msfboID); + } + + @Override + protected void blitMSFBO() { + final GL gl = GLU.getCurrentGL(); + + gl.glBindFramebufferEXT(GL.GL_READ_FRAMEBUFFER_EXT, _msfboID); + gl.glBindFramebufferEXT(GL.GL_DRAW_FRAMEBUFFER_EXT, _fboID); + gl.glBlitFramebufferEXT(0, 0, _width, _height, 0, 0, _width, _height, GL.GL_COLOR_BUFFER_BIT + | GL.GL_DEPTH_BUFFER_BIT, GL.GL_NEAREST); + + gl.glBindFramebufferEXT(GL.GL_READ_FRAMEBUFFER_EXT, 0); + gl.glBindFramebufferEXT(GL.GL_DRAW_FRAMEBUFFER_EXT, 0); + gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 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.glCheckFramebufferStatusEXT(GL.GL_FRAMEBUFFER_EXT); + switch (status) { + case GL.GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + throw new IllegalStateException("FrameBuffer: " + fboID + + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT exception"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + throw new IllegalStateException("FrameBuffer: " + fboID + + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT exception"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + throw new IllegalStateException("FrameBuffer: " + fboID + + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT exception"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + throw new IllegalStateException("FrameBuffer: " + fboID + + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT exception"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + throw new IllegalStateException("FrameBuffer: " + fboID + + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT exception"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + throw new IllegalStateException("FrameBuffer: " + fboID + + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT exception"); + case GL.GL_FRAMEBUFFER_UNSUPPORTED_EXT: + throw new IllegalStateException("FrameBuffer: " + fboID + + ", has caused a GL_FRAMEBUFFER_UNSUPPORTED_EXT exception"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: + 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.glGenFramebuffersEXT(1, buffer); // generate id + _fboID = buffer.get(0); + + // Create a depth renderbuffer to use for RTT use + gl.glGenRenderbuffersEXT(1, buffer); // generate id + _depthRBID = buffer.get(0); + gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, _depthRBID); + int format = GL.GL_DEPTH_COMPONENT; + if (_supportsDepthTexture && _depthBits > 0) { + switch (_depthBits) { + case 16: + format = GL.GL_DEPTH_COMPONENT16_ARB; + break; + case 24: + format = GL.GL_DEPTH_COMPONENT24_ARB; + break; + case 32: + format = GL.GL_DEPTH_COMPONENT32_ARB; + break; + default: + // stick with the "undefined" GL_DEPTH_COMPONENT + } + } + gl.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT, format, _width, _height); + + // unbind... + gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, 0); + gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0); + + // If we support it, rustle up a multisample framebuffer + renderbuffers + if (_samples != 0 && _supportsMultisample) { + // create ms framebuffer object + gl.glGenFramebuffersEXT(1, buffer); + _msfboID = buffer.get(0); + + // create ms renderbuffers + gl.glGenRenderbuffersEXT(1, buffer); // generate id + _mscolorRBID = buffer.get(0); + gl.glGenRenderbuffersEXT(1, buffer); // generate id + _msdepthRBID = buffer.get(0); + + // set up renderbuffer properties + gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, _mscolorRBID); + gl.glRenderbufferStorageMultisampleEXT(GL.GL_RENDERBUFFER_EXT, _samples, GL.GL_RGBA, _width, _height); + + gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, _msdepthRBID); + gl.glRenderbufferStorageMultisampleEXT(GL.GL_RENDERBUFFER_EXT, _samples, format, _width, _height); + + gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, 0); + + gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, _msfboID); + gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, + GL.GL_RENDERBUFFER_EXT, _mscolorRBID); + gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, + GL.GL_RENDERBUFFER_EXT, _msdepthRBID); + + // check for errors + checkFBOComplete(_msfboID); + + // release + gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 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.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, _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.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 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.glDeleteFramebuffersEXT(id.limit(), id); + } + + if (_depthRBID != 0) { + final IntBuffer id = BufferUtils.createIntBuffer(1); + id.put(_depthRBID); + id.rewind(); + gl.glDeleteRenderbuffersEXT(id.limit(), id); + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRendererProvider.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRendererProvider.java new file mode 100644 index 0000000..a725a16 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/renderer/jogl/JoglTextureRendererProvider.java @@ -0,0 +1,49 @@ +/**
+ * 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.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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglBlendStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglBlendStateUtil.java new file mode 100644 index 0000000..e4b29da --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglBlendStateUtil.java @@ -0,0 +1,421 @@ +/** + * 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 javax.media.opengl.GL; +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.glBlendEquationSeparateEXT(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.glBlendEquationSeparateEXT(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.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.glBlendFuncSeparateEXT(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.glBlendFuncSeparateEXT(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 GL.GL_CONSTANT_COLOR; + } + // FALLS THROUGH + case OneMinusConstantColor: + if (caps.isConstantBlendColorSupported()) { + return GL.GL_ONE_MINUS_CONSTANT_COLOR; + } + // FALLS THROUGH + case ConstantAlpha: + if (caps.isConstantBlendColorSupported()) { + return GL.GL_CONSTANT_ALPHA; + } + // FALLS THROUGH + case OneMinusConstantAlpha: + if (caps.isConstantBlendColorSupported()) { + return GL.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 GL.GL_CONSTANT_COLOR; + } + // FALLS THROUGH + case OneMinusConstantColor: + if (caps.isConstantBlendColorSupported()) { + return GL.GL_ONE_MINUS_CONSTANT_COLOR; + } + // FALLS THROUGH + case ConstantAlpha: + if (caps.isConstantBlendColorSupported()) { + return GL.GL_CONSTANT_ALPHA; + } + // FALLS THROUGH + case OneMinusConstantAlpha: + if (caps.isConstantBlendColorSupported()) { + return GL.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 GL.GL_MIN; + } + // FALLS THROUGH + case Max: + if (caps.isMinMaxBlendEquationsSupported()) { + return GL.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(GL.GL_ALPHA_TEST); + record.testEnabled = true; + } + final int glFunc = getGLFuncValue(state.getTestFunction()); + if (record.alphaFunc != glFunc || record.alphaRef != state.getReference()) { + gl.glAlphaFunc(glFunc, state.getReference()); + record.alphaFunc = glFunc; + record.alphaRef = state.getReference(); + } + } else if (record.testEnabled) { + gl.glDisable(GL.GL_ALPHA_TEST); + record.testEnabled = false; + } + + } else { + if (enabled) { + gl.glEnable(GL.GL_ALPHA_TEST); + record.testEnabled = true; + final int glFunc = getGLFuncValue(state.getTestFunction()); + gl.glAlphaFunc(glFunc, state.getReference()); + record.alphaFunc = glFunc; + record.alphaRef = state.getReference(); + } else { + gl.glDisable(GL.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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglClipStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglClipStateUtil.java new file mode 100644 index 0000000..591d6f1 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglClipStateUtil.java @@ -0,0 +1,72 @@ +/** + * 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 javax.media.opengl.GL; +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(GL.GL_CLIP_PLANE0 + planeIndex); + record.planeEnabled[planeIndex] = true; + } + + record.buf.rewind(); + record.buf.put(state.getPlaneEquations(planeIndex)); + record.buf.flip(); + gl.glClipPlane(GL.GL_CLIP_PLANE0 + planeIndex, record.buf); + + } else { + if (!record.isValid() || record.planeEnabled[planeIndex]) { + gl.glDisable(GL.GL_CLIP_PLANE0 + planeIndex); + record.planeEnabled[planeIndex] = false; + } + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglColorMaskStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglColorMaskStateUtil.java new file mode 100644 index 0000000..b056612 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglColorMaskStateUtil.java @@ -0,0 +1,47 @@ +/** + * 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 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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglCullStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglCullStateUtil.java new file mode 100644 index 0000000..c19c1e8 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglCullStateUtil.java @@ -0,0 +1,103 @@ +/** + * 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 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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFogStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFogStateUtil.java new file mode 100644 index 0000000..04619cb --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFogStateUtil.java @@ -0,0 +1,167 @@ +/** + * 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 javax.media.opengl.GL; +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.glFogf(GL.GL_FOG_START, state.getStart()); + record.fogStart = state.getStart(); + } + if (record.fogEnd != state.getEnd()) { + gl.glFogf(GL.GL_FOG_END, state.getEnd()); + record.fogEnd = state.getEnd(); + } + if (record.density != state.getDensity()) { + gl.glFogf(GL.GL_FOG_DENSITY, state.getDensity()); + record.density = state.getDensity(); + } + } else { + gl.glFogf(GL.GL_FOG_START, state.getStart()); + record.fogStart = state.getStart(); + gl.glFogf(GL.GL_FOG_END, state.getEnd()); + record.fogEnd = state.getEnd(); + gl.glFogf(GL.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(GL.GL_FOG); + record.enabled = true; + } else if (!enable && record.enabled) { + gl.glDisable(GL.GL_FOG); + record.enabled = false; + } + } else { + if (enable) { + gl.glEnable(GL.GL_FOG); + } else { + gl.glDisable(GL.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.glFogfv(GL.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.glFogi(GL.GL_FOG_COORDINATE_SOURCE_EXT, GL.GL_FRAGMENT_DEPTH_EXT); + } else { + gl.glFogi(GL.GL_FOG_COORDINATE_SOURCE_EXT, GL.GL_FOG_COORDINATE_EXT); + } + } + } + } + + private static void applyFogMode(final DensityFunction densityFunction, final FogStateRecord record) { + final GL gl = GLU.getCurrentGL(); + + int glMode = 0; + switch (densityFunction) { + case Exponential: + glMode = GL.GL_EXP; + break; + case Linear: + glMode = GL.GL_LINEAR; + break; + case ExponentialSquared: + glMode = GL.GL_EXP2; + break; + } + + if (!record.isValid() || record.fogMode != glMode) { + gl.glFogi(GL.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(GL.GL_FOG_HINT, glHint); + record.fogHint = glHint; + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFragmentProgramStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFragmentProgramStateUtil.java new file mode 100644 index 0000000..ebda6a0 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglFragmentProgramStateUtil.java @@ -0,0 +1,124 @@ +/** + * 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.logging.Logger; + +import javax.media.opengl.GL; +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(GL.GL_PROGRAM_ERROR_POSITION_ARB, errorloc); // TODO Check for integer + + logger.severe("Error " + gl.glGetString(GL.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.glGenProgramsARB(buf.limit(), buf); // TODO Check <size> + gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, buf.get(0)); + + final byte array[] = new byte[program.limit()]; + program.rewind(); + program.get(array); + gl.glProgramStringARB(GL.GL_FRAGMENT_PROGRAM_ARB, GL.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(GL.GL_FRAGMENT_PROGRAM_ARB); + gl.glBindProgramARB(GL.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.glProgramLocalParameter4fARB(GL.GL_FRAGMENT_PROGRAM_ARB, i, + state._getParameters()[i][0], state._getParameters()[i][1], state + ._getParameters()[i][2], state._getParameters()[i][3]); + } + } + } + + } else { + gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); + } + } + + if (!record.isValid()) { + record.validate(); + } + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglLightStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglLightStateUtil.java new file mode 100644 index 0000000..c608883 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglLightStateUtil.java @@ -0,0 +1,409 @@ +/** + * 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 javax.media.opengl.GL; +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(GL.GL_LIGHT0 + index); + } else { + gl.glDisable(GL.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(GL.GL_LIGHTING); + } else { + gl.glDisable(GL.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.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE); + } else { + gl.glLightModeli(GL.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.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE); + } else { + gl.glLightModeli(GL.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.glLightModeli(GL.GL_LIGHT_MODEL_COLOR_CONTROL, GL.GL_SEPARATE_SPECULAR_COLOR); + } else { + gl.glLightModeli(GL.GL_LIGHT_MODEL_COLOR_CONTROL, GL.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.glLightModelfv(GL.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.glLightfv(GL.GL_LIGHT0 + index, GL.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.glLightfv(GL.GL_LIGHT0 + index, GL.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.glLightfv(GL.GL_LIGHT0 + index, GL.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.glLightfv(GL.GL_LIGHT0 + index, GL.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.glLightfv(GL.GL_LIGHT0 + index, GL.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.glLightf(GL.GL_LIGHT0 + index, GL.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.glLightf(GL.GL_LIGHT0 + index, GL.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.glLightf(GL.GL_LIGHT0 + index, GL.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.glLightf(GL.GL_LIGHT0 + index, GL.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.glLightf(GL.GL_LIGHT0 + index, GL.GL_SPOT_CUTOFF, cutoff); + lr.setSpotCutoff(cutoff); + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglMaterialStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglMaterialStateUtil.java new file mode 100644 index 0000000..cc6b956 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglMaterialStateUtil.java @@ -0,0 +1,207 @@ +/** + * 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 javax.media.opengl.GL; +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.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.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.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; + } + 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(GL.GL_COLOR_MATERIAL); + } else { + final int glMat = getGLColorMaterial(colorMaterial); + final int glFace = getGLMaterialFace(face); + + gl.glColorMaterial(glFace, glMat); + gl.glEnable(GL.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.glMaterialf(getGLMaterialFace(MaterialFace.FrontAndBack), GL.GL_SHININESS, frontShininess); + record.backShininess = record.frontShininess = frontShininess; + } + } else { + if (!record.isValid() || frontShininess != record.frontShininess) { + gl.glMaterialf(getGLMaterialFace(MaterialFace.Front), GL.GL_SHININESS, frontShininess); + record.frontShininess = frontShininess; + } + + if (!record.isValid() || backShininess != record.backShininess) { + gl.glMaterialf(getGLMaterialFace(MaterialFace.Back), GL.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 GL.GL_AMBIENT; + case Diffuse: + return GL.GL_DIFFUSE; + case AmbientAndDiffuse: + return GL.GL_AMBIENT_AND_DIFFUSE; + case Emissive: + return GL.GL_EMISSION; + case Specular: + return GL.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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglOffsetStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglOffsetStateUtil.java new file mode 100644 index 0000000..c209fcb --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglOffsetStateUtil.java @@ -0,0 +1,90 @@ +/** + * 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 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.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 GL.GL_POLYGON_OFFSET_LINE; + case Point: + return GL.GL_POLYGON_OFFSET_POINT; + } + throw new IllegalArgumentException("invalid type: " + type); + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShaderObjectsStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShaderObjectsStateUtil.java new file mode 100644 index 0000000..308e5fe --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShaderObjectsStateUtil.java @@ -0,0 +1,306 @@ +/** + * 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.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.glCreateProgramObjectARB(); + } + + if (state.getVertexShader() != null) { + if (state._vertexShaderID != -1) { + removeVertShader(state); + } + + state._vertexShaderID = gl.glCreateShaderObjectARB(GL.GL_VERTEX_SHADER_ARB); + + // Create the sources + final byte array[] = new byte[state.getVertexShader().limit()]; + state.getVertexShader().rewind(); + state.getVertexShader().get(array); + gl.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.glCompileShaderARB(state._vertexShaderID); + gl.glGetObjectParameterivARB(state._vertexShaderID, GL.GL_OBJECT_COMPILE_STATUS_ARB, compiled); + checkProgramError(compiled, state._vertexShaderID, state._vertexShaderName); + + // Attach the program + gl.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.glCreateShaderObjectARB(GL.GL_FRAGMENT_SHADER_ARB); + + // Create the sources + final byte array[] = new byte[state.getFragmentShader().limit()]; + state.getFragmentShader().rewind(); + state.getFragmentShader().get(array); + gl.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.glCompileShaderARB(state._fragmentShaderID); + gl.glGetObjectParameterivARB(state._fragmentShaderID, GL.GL_OBJECT_COMPILE_STATUS_ARB, compiled); + checkProgramError(compiled, state._fragmentShaderID, state._fragmentShaderName); + + // Attach the program + gl.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.glCreateShaderObjectARB(GL.GL_GEOMETRY_SHADER_EXT); + + // Create the sources + final byte array[] = new byte[state.getGeometryShader().limit()]; + state.getGeometryShader().rewind(); + state.getGeometryShader().get(array); + gl.glShaderSourceARB(state._geometryShaderID, 1, new String[] { new String(array) }, + new int[] { array.length }, 0); + + // Compile the fragment shader + final IntBuffer compiled = BufferUtils.createIntBuffer(1); + gl.glCompileShaderARB(state._geometryShaderID); + gl.glGetObjectParameterivARB(state._geometryShaderID, GL.GL_OBJECT_COMPILE_STATUS_ARB, compiled); + checkProgramError(compiled, state._geometryShaderID, state._geometryShaderName); + + // Attach the program + gl.glAttachObjectARB(state._programID, state._geometryShaderID); + } else if (state._geometryShaderID != -1) { + removeGeomShader(state); + state._geometryShaderID = -1; + } + } + + gl.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.glGetObjectParameterivARB(programId, GL.GL_LINK_STATUS, compiled); + if (compiled.get(0) == GL.GL_FALSE) { + gl.glGetObjectParameterivARB(programId, GL.GL_INFO_LOG_LENGTH, compiled); + final int length = compiled.get(0); + String out = null; + if (length > 0) { + final ByteBuffer infoLog = BufferUtils.createByteBuffer(length); + + gl.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.glDetachObjectARB(state._programID, state._fragmentShaderID); + gl.glDeleteObjectARB(state._fragmentShaderID); + } + } + + /** Removes the vertex shader */ + private static void removeVertShader(final GLSLShaderObjectsState state) { + final GL gl = GLU.getCurrentGL(); + + if (state._vertexShaderID != -1) { + gl.glDetachObjectARB(state._programID, state._vertexShaderID); + gl.glDeleteObjectARB(state._vertexShaderID); + } + } + + /** Removes the geometry shader */ + private static void removeGeomShader(final GLSLShaderObjectsState state) { + final GL gl = GLU.getCurrentGL(); + + if (state._geometryShaderID != -1) { + gl.glDetachObjectARB(state._programID, state._geometryShaderID); + gl.glDeleteObjectARB(state._geometryShaderID); + } + } + + /** + * 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 + * @param shaderName + */ + 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.glGetObjectParameterivARB(id, GL.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.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.glDisableVertexAttribArrayARB(var.variableID); + } else { + for (int j = 0, maxJ = var.getSize(); j < maxJ; j++) { + gl.glDisableVertexAttribArrayARB(var.variableID + j); + } + } + } + record.enabledAttributes.clear(); + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShadingStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShadingStateUtil.java new file mode 100644 index 0000000..a5b1016 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglShadingStateUtil.java @@ -0,0 +1,56 @@ +/** + * 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 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.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()) : GL.GL_SMOOTH; + // only apply if we're different. Update record to reflect any changes. + if (!record.isValid() || toApply != record.lastShade) { + gl.glShadeModel(toApply); + record.lastShade = toApply; + } + + if (!record.isValid()) { + record.validate(); + } + } + + private static int getGLShade(final ShadingMode shadeMode) { + switch (shadeMode) { + case Smooth: + return GL.GL_SMOOTH; + case Flat: + return GL.GL_FLAT; + } + throw new IllegalStateException("unknown shade mode: " + shadeMode); + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglStencilStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglStencilStateUtil.java new file mode 100644 index 0000000..2749f52 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglStencilStateUtil.java @@ -0,0 +1,197 @@ +/** + * 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 javax.media.opengl.GL; +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.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.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_EXT; + } + // FALLS THROUGH + case Decrement: + return GL.GL_DECR; + case IncrementWrap: + if (caps.isStencilWrapSupported()) { + return GL.GL_INCR_WRAP_EXT; + } + // 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(GL.GL_STENCIL_TEST_TWO_SIDE_EXT); + } else if (!enable && record.useTwoSided) { + gl.glDisable(GL.GL_STENCIL_TEST_TWO_SIDE_EXT); + } + } else { + if (enable) { + gl.glEnable(GL.GL_STENCIL_TEST_TWO_SIDE_EXT); + } else { + gl.glDisable(GL.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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglTextureStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglTextureStateUtil.java new file mode 100644 index 0000000..e81cb74 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglTextureStateUtil.java @@ -0,0 +1,1710 @@ +/** + * 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.GLException; +import javax.media.opengl.glu.GLU; + +import com.ardor3d.image.Image; +import com.ardor3d.image.Texture; +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.Texture1D; +import com.ardor3d.image.Texture2D; +import com.ardor3d.image.Texture3D; +import com.ardor3d.image.TextureCubeMap; +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.RenderState.StateType; +import com.ardor3d.renderer.state.TextureState; +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 GLU(); + + // 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.glTexImage1D(GL.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.glTexImage3D(GL.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; + } + } 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), GL.GL_GENERATE_MIPMAP_SGIS, 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.glTexImage1D(GL.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.glTexImage3D(GL.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; + } + + if (texture.getTextureMaxLevel() >= 0) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.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), GL.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, GL.GL_TEXTURE_MAX_LEVEL, max - 1); + break; + case ThreeDimensional: + gl.glTexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_MAX_LEVEL, max - 1); + break; + case OneDimensional: + gl.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_MAX_LEVEL, max - 1); + 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.glCompressedTexImage1D(GL.GL_TEXTURE_1D, m, + JoglTextureUtil.getGLInternalFormat(texture.getTextureStoreFormat()), + width, hasBorder ? 1 : 0, mipSizes[m], data); + } else { + gl.glTexImage1D(GL.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.glCompressedTexImage3D(GL.GL_TEXTURE_3D, m, + JoglTextureUtil.getGLInternalFormat(texture.getTextureStoreFormat()), + width, height, depth, hasBorder ? 1 : 0, mipSizes[m], data); + } else { + gl.glTexImage3D(GL.GL_TEXTURE_3D, m, + JoglTextureUtil.getGLInternalFormat(texture.getTextureStoreFormat()), + width, height, depth, hasBorder ? 1 : 0, + JoglTextureUtil.getGLPixelFormat(image.getDataFormat()), + JoglTextureUtil.getGLPixelDataType(image.getDataType()), data); + } + 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(GL.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(GL.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(GL.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(GL.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(GL.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.glTexEnvf(GL.GL_TEXTURE_ENV, GL.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.glTexEnvf(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvi(GL.GL_TEXTURE_ENV, GL.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.glTexEnvfv(GL.GL_TEXTURE_ENV, GL.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.glTexEnvf(GL.GL_TEXTURE_FILTER_CONTROL_EXT, GL.GL_TEXTURE_LOD_BIAS_EXT, 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()), GL.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.glLoadMatrixd(record.tmp_matrixBuffer); + + record.units[unit].identityMatrix = false; + } else if (needsReset) { + checkAndSetUnit(unit, record, caps); + JoglRendererUtil.switchMode(matRecord, GL.GL_TEXTURE); + gl.glLoadIdentity(); + record.units[unit].identityMatrix = true; + } + // Switch back to the modelview matrix for further operations + JoglRendererUtil.switchMode(matRecord, GL.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 != GL.GL_SPHERE_MAP) { + checkAndSetUnit(unit, record, caps); + + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); + unitRecord.textureGenSMode = GL.GL_SPHERE_MAP; + + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); + unitRecord.textureGenTMode = GL.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 != GL.GL_NORMAL_MAP) { + checkAndSetUnit(unit, record, caps); + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + unitRecord.textureGenSMode = GL.GL_NORMAL_MAP; + + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + unitRecord.textureGenTMode = GL.GL_NORMAL_MAP; + + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + unitRecord.textureGenRMode = GL.GL_NORMAL_MAP; + } + + setTextureGen(unitRecord, unit, record, caps, true, true, true, false); + break; + case ReflectionMap: + // generate reflection texture coordinates + if (!unitRecord.isValid() || unitRecord.textureGenSMode != GL.GL_REFLECTION_MAP) { + checkAndSetUnit(unit, record, caps); + + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP); + unitRecord.textureGenSMode = GL.GL_REFLECTION_MAP; + + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP); + unitRecord.textureGenTMode = GL.GL_REFLECTION_MAP; + + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP); + unitRecord.textureGenRMode = GL.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 != GL.GL_EYE_LINEAR) { + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + unitRecord.textureGenSMode = GL.GL_EYE_LINEAR; + + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + unitRecord.textureGenTMode = GL.GL_EYE_LINEAR; + + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + unitRecord.textureGenRMode = GL.GL_EYE_LINEAR; + + gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + unitRecord.textureGenQMode = GL.GL_EYE_LINEAR; + } + + record.prepPlane(texture.getEnvPlaneS(), TextureStateRecord.DEFAULT_S_PLANE); + gl.glTexGenfv(GL.GL_S, GL.GL_EYE_PLANE, record.plane); + record.prepPlane(texture.getEnvPlaneT(), TextureStateRecord.DEFAULT_T_PLANE); + gl.glTexGenfv(GL.GL_T, GL.GL_EYE_PLANE, record.plane); + record.prepPlane(texture.getEnvPlaneR(), TextureStateRecord.DEFAULT_R_PLANE); + gl.glTexGenfv(GL.GL_R, GL.GL_EYE_PLANE, record.plane); + record.prepPlane(texture.getEnvPlaneQ(), TextureStateRecord.DEFAULT_Q_PLANE); + gl.glTexGenfv(GL.GL_Q, GL.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 != GL.GL_OBJECT_LINEAR) { + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + unitRecord.textureGenSMode = GL.GL_OBJECT_LINEAR; + + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + unitRecord.textureGenTMode = GL.GL_OBJECT_LINEAR; + + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + unitRecord.textureGenRMode = GL.GL_OBJECT_LINEAR; + + gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + unitRecord.textureGenQMode = GL.GL_OBJECT_LINEAR; + } + + record.prepPlane(texture.getEnvPlaneS(), TextureStateRecord.DEFAULT_S_PLANE); + gl.glTexGenfv(GL.GL_S, GL.GL_OBJECT_PLANE, record.plane); + record.prepPlane(texture.getEnvPlaneT(), TextureStateRecord.DEFAULT_T_PLANE); + gl.glTexGenfv(GL.GL_T, GL.GL_OBJECT_PLANE, record.plane); + record.prepPlane(texture.getEnvPlaneR(), TextureStateRecord.DEFAULT_R_PLANE); + gl.glTexGenfv(GL.GL_R, GL.GL_OBJECT_PLANE, record.plane); + record.prepPlane(texture.getEnvPlaneQ(), TextureStateRecord.DEFAULT_Q_PLANE); + gl.glTexGenfv(GL.GL_Q, GL.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(GL.GL_TEXTURE_GEN_S); + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_S); + } + if (genT) { + gl.glEnable(GL.GL_TEXTURE_GEN_T); + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_T); + } + if (genR) { + gl.glEnable(GL.GL_TEXTURE_GEN_R); + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_R); + } + if (genQ) { + gl.glEnable(GL.GL_TEXTURE_GEN_Q); + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_Q); + } + } else { + if (genS != unitRecord.textureGenS) { + checkAndSetUnit(unit, record, caps); + if (genS) { + gl.glEnable(GL.GL_TEXTURE_GEN_S); + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_S); + } + } + if (genT != unitRecord.textureGenT) { + checkAndSetUnit(unit, record, caps); + if (genT) { + gl.glEnable(GL.GL_TEXTURE_GEN_T); + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_T); + } + } + if (genR != unitRecord.textureGenR) { + checkAndSetUnit(unit, record, caps); + if (genR) { + gl.glEnable(GL.GL_TEXTURE_GEN_R); + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_R); + } + } + if (genQ != unitRecord.textureGenQ) { + checkAndSetUnit(unit, record, caps); + if (genQ) { + gl.glEnable(GL.GL_TEXTURE_GEN_Q); + } else { + gl.glDisable(GL.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), GL.GL_DEPTH_TEXTURE_MODE_ARB, 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), GL.GL_TEXTURE_COMPARE_MODE_ARB, 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), GL.GL_TEXTURE_COMPARE_FUNC_ARB, 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 > MathUtils.ZERO_TOLERANCE)) { + 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(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_S, wrapS); + texRecord.wrapS = wrapS; + } + if (!texRecord.isValid() || texRecord.wrapT != wrapT) { + checkAndSetUnit(unit, record, caps); + gl.glTexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_T, wrapT); + texRecord.wrapT = wrapT; + } + if (!texRecord.isValid() || texRecord.wrapR != wrapR) { + checkAndSetUnit(unit, record, caps); + gl.glTexParameteri(GL.GL_TEXTURE_3D, GL.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(GL.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, GL.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 GL.GL_TEXTURE_1D; + case ThreeDimensional: + return GL.GL_TEXTURE_3D; + case CubeMap: + return GL.GL_TEXTURE_CUBE_MAP; + } + 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_ARB; + } else { + return GL.GL_REPEAT; + } + case MirrorClamp: + if (caps.isTextureMirrorClampSupported()) { + return GL.GL_MIRROR_CLAMP_EXT; + } + // FALLS THROUGH + case Clamp: + return GL.GL_CLAMP; + case MirrorBorderClamp: + if (caps.isTextureMirrorBorderClampSupported()) { + return GL.GL_MIRROR_CLAMP_TO_BORDER_EXT; + } + // FALLS THROUGH + case BorderClamp: + if (caps.isTextureBorderClampSupported()) { + return GL.GL_CLAMP_TO_BORDER; + } else { + return GL.GL_CLAMP; + } + case MirrorEdgeClamp: + if (caps.isTextureMirrorEdgeClampSupported()) { + return GL.GL_MIRROR_CLAMP_TO_EDGE_EXT; + } + // FALLS THROUGH + case EdgeClamp: + if (caps.isTextureEdgeClampSupported()) { + return GL.GL_CLAMP_TO_EDGE; + } else { + return GL.GL_CLAMP; + } + } + throw new IllegalArgumentException("invalid WrapMode type: " + wrap); + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglVertexProgramStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglVertexProgramStateUtil.java new file mode 100644 index 0000000..a980b66 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglVertexProgramStateUtil.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.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.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(GL.GL_PROGRAM_ERROR_POSITION_ARB, errorloc); // TODO Check for integer + + logger.severe("Error " + gl.glGetString(GL.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.glGenProgramsARB(buf.limit(), buf); + gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, buf.get(0)); + + final byte array[] = new byte[program.limit()]; + program.rewind(); + program.get(array); + gl + .glProgramStringARB(GL.GL_VERTEX_PROGRAM_ARB, GL.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(GL.GL_VERTEX_PROGRAM_ARB); + gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, state._getProgramID()); + + // load environmental parameters... + for (int i = 0; i < VertexProgramState._getEnvParameters().length; i++) { + if (VertexProgramState._getEnvParameters()[i] != null) { + gl.glProgramEnvParameter4fARB(GL.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.glProgramLocalParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, i, + state._getParameters()[i][0], state._getParameters()[i][1], state + ._getParameters()[i][2], state._getParameters()[i][3]); + } + } + } + + } else { + gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); + } + } + + if (!record.isValid()) { + record.validate(); + } + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglWireframeStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglWireframeStateUtil.java new file mode 100644 index 0000000..cd6ee71 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglWireframeStateUtil.java @@ -0,0 +1,85 @@ +/** + * 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 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.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(GL.GL_LINE, GL.GL_FILL, record); + break; + case Back: + applyPolyMode(GL.GL_FILL, GL.GL_LINE, record); + break; + case FrontAndBack: + default: + applyPolyMode(GL.GL_LINE, GL.GL_LINE, record); + break; + } + } else { + applyPolyMode(GL.GL_FILL, GL.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.glPolygonMode(GL.GL_FRONT_AND_BACK, frontMode); + record.frontMode = frontMode; + record.backMode = backMode; + } else if (frontMode != backMode) { + if (record.frontMode != frontMode) { + gl.glPolygonMode(GL.GL_FRONT, frontMode); + record.frontMode = frontMode; + } + if (record.backMode != backMode) { + gl.glPolygonMode(GL.GL_BACK, backMode); + record.backMode = backMode; + } + } + + } else { + if (frontMode == backMode) { + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, frontMode); + } else if (frontMode != backMode) { + gl.glPolygonMode(GL.GL_FRONT, frontMode); + gl.glPolygonMode(GL.GL_BACK, backMode); + } + record.frontMode = frontMode; + record.backMode = backMode; + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglZBufferStateUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglZBufferStateUtil.java new file mode 100644 index 0000000..12f542a --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/JoglZBufferStateUtil.java @@ -0,0 +1,98 @@ +/** + * 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 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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/shader/JoglShaderUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/shader/JoglShaderUtil.java new file mode 100644 index 0000000..cab297a --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/shader/JoglShaderUtil.java @@ -0,0 +1,416 @@ +/** + * 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.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.glGetUniformLocationARB(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.glUniform1iARB(shaderUniform.variableID, shaderUniform.value1); + } + + private static void updateShaderUniform(final ShaderVariableInt2 shaderUniform) { + final GL gl = GLU.getCurrentGL(); + + gl.glUniform2iARB(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2); + } + + private static void updateShaderUniform(final ShaderVariableInt3 shaderUniform) { + final GL gl = GLU.getCurrentGL(); + + gl.glUniform3iARB(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2, shaderUniform.value3); + } + + private static void updateShaderUniform(final ShaderVariableInt4 shaderUniform) { + final GL gl = GLU.getCurrentGL(); + + gl.glUniform4iARB(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.glUniform1ivARB(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value); + break; + case 2: + gl.glUniform2ivARB(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value); + break; + case 3: + gl.glUniform3ivARB(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value); + break; + case 4: + gl.glUniform4ivARB(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.glUniform1fARB(shaderUniform.variableID, shaderUniform.value1); + } + + private static void updateShaderUniform(final ShaderVariableFloat2 shaderUniform) { + final GL gl = GLU.getCurrentGL(); + + gl.glUniform2fARB(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2); + } + + private static void updateShaderUniform(final ShaderVariableFloat3 shaderUniform) { + final GL gl = GLU.getCurrentGL(); + + gl.glUniform3fARB(shaderUniform.variableID, shaderUniform.value1, shaderUniform.value2, shaderUniform.value3); + } + + private static void updateShaderUniform(final ShaderVariableFloat4 shaderUniform) { + final GL gl = GLU.getCurrentGL(); + + gl.glUniform4fARB(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.glUniform1fvARB(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value); + break; + case 2: + gl.glUniform2fvARB(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value); + break; + case 3: + gl.glUniform3fvARB(shaderUniform.variableID, shaderUniform.value.remaining(), shaderUniform.value); + break; + case 4: + gl.glUniform4fvARB(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.glUniformMatrix2fv(shaderUniform.variableID, 1, shaderUniform.rowMajor, shaderUniform.matrixBuffer); + } + + private static void updateShaderUniform(final ShaderVariableMatrix3 shaderUniform) { + final GL gl = GLU.getCurrentGL(); + + shaderUniform.matrixBuffer.rewind(); + gl.glUniformMatrix3fv(shaderUniform.variableID, 1, shaderUniform.rowMajor, shaderUniform.matrixBuffer); + } + + private static void updateShaderUniform(final ShaderVariableMatrix4 shaderUniform) { + final GL gl = GLU.getCurrentGL(); + + shaderUniform.matrixBuffer.rewind(); + gl.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.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.glGetAttribLocationARB(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().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().glEnableVertexAttribArrayARB(var.variableID); + } else { + final GL gl = GLU.getCurrentGL(); + for (int i = 0, max = var.getSize(); i < max; i++) { + gl.glEnableVertexAttribArrayARB(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().glVertexAttribPointerARB(variable.variableID, variable.size, GL.GL_FLOAT, + variable.normalized, variable.stride, 0); + } else { + variable.data.getBuffer().rewind(); + GLU.getCurrentGL().glVertexAttribPointerARB(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.glVertexAttribPointerARB(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.glVertexAttribPointerARB(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().glVertexAttribPointerARB(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().glVertexAttribPointerARB(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().glVertexAttribPointerARB(variable.variableID, variable.size, + variable.unsigned ? GL.GL_UNSIGNED_INT : GL.GL_INT, variable.normalized, variable.stride, 0); + } else { + variable.data.getBuffer().rewind(); + GLU.getCurrentGL().glVertexAttribPointerARB(variable.variableID, variable.size, + variable.unsigned ? GL.GL_UNSIGNED_INT : GL.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().glVertexAttribPointerARB(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().glVertexAttribPointerARB(variable.variableID, variable.size, + variable.unsigned ? GL.GL_UNSIGNED_SHORT : GL.GL_SHORT, variable.normalized, variable.stride, + variable.data.getBuffer()); + } + } +} diff --git a/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglRendererUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglRendererUtil.java new file mode 100644 index 0000000..c763e63 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglRendererUtil.java @@ -0,0 +1,107 @@ +/** + * 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.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.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.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 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.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, 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/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglTextureUtil.java b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglTextureUtil.java new file mode 100644 index 0000000..2733e72 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/java/com/ardor3d/scene/state/jogl/util/JoglTextureUtil.java @@ -0,0 +1,613 @@ +/** + * 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.util; + +import javax.media.opengl.GL; + +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 GL.GL_ALPHA8; + case CompressedRGBA: + return GL.GL_COMPRESSED_RGBA; + case CompressedRGB: + return GL.GL_COMPRESSED_RGB; + case CompressedRG: + return 0x8226;// GL.GL_COMPRESSED_RG; + case CompressedRed: + return 0x8225;// GL.GL_COMPRESSED_RED; + case CompressedLuminance: + return GL.GL_COMPRESSED_LUMINANCE; + case CompressedLuminanceAlpha: + return GL.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 GL.GL_COMPRESSED_LUMINANCE_LATC1_EXT; + case NativeLATC_LA: + return GL.GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; + + // The rest... + case Alpha4: + return GL.GL_ALPHA4; + case Alpha12: + return GL.GL_ALPHA12; + case Alpha16: + return GL.GL_ALPHA16; + case Luminance4: + return GL.GL_LUMINANCE4; + case Luminance8: + return GL.GL_LUMINANCE8; + case Luminance12: + return GL.GL_LUMINANCE12; + case Luminance16: + return GL.GL_LUMINANCE16; + case Intensity4: + return GL.GL_INTENSITY4; + case Intensity8: + return GL.GL_INTENSITY8; + case Intensity12: + return GL.GL_INTENSITY12; + case Intensity16: + return GL.GL_INTENSITY16; + case Luminance4Alpha4: + return GL.GL_LUMINANCE4_ALPHA4; + case Luminance6Alpha2: + return GL.GL_LUMINANCE6_ALPHA2; + case Luminance8Alpha8: + return GL.GL_LUMINANCE8_ALPHA8; + case Luminance12Alpha4: + return GL.GL_LUMINANCE12_ALPHA4; + case Luminance12Alpha12: + return GL.GL_LUMINANCE12_ALPHA12; + case Luminance16Alpha16: + return GL.GL_LUMINANCE16_ALPHA16; + case R3G3B2: + return GL.GL_R3_G3_B2; + case RGB4: + return GL.GL_RGB4; + case RGB5: + return GL.GL_RGB5; + case RGB10: + return GL.GL_RGB10; + case RGB12: + return GL.GL_RGB12; + case RGB16: + return GL.GL_RGB16; + case RGBA2: + return GL.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 GL.GL_RGBA12; + case RGBA16: + return GL.GL_RGBA16; + case Depth: + return GL.GL_DEPTH_COMPONENT; + case Depth16: + return GL.GL_DEPTH_COMPONENT16_ARB; + case Depth24: + return GL.GL_DEPTH_COMPONENT24_ARB; + case Depth32: + return GL.GL_DEPTH_COMPONENT32_ARB; + case Depth32F: + return GL.GL_DEPTH_COMPONENT32F_NV; + case RGB16F: + return GL.GL_RGB16F_ARB; + case RGB32F: + return GL.GL_RGB32F_ARB; + case RGBA16F: + return GL.GL_RGBA16F_ARB; + case RGBA32F: + return GL.GL_RGBA32F_ARB; + case Alpha16F: + return GL.GL_ALPHA16F_ARB; + case Alpha32F: + return GL.GL_ALPHA32F_ARB; + case Luminance16F: + return GL.GL_LUMINANCE16F_ARB; + case Luminance32F: + return GL.GL_LUMINANCE32F_ARB; + case LuminanceAlpha16F: + return GL.GL_LUMINANCE_ALPHA16F_ARB; + case LuminanceAlpha32F: + return GL.GL_LUMINANCE_ALPHA32F_ARB; + case Intensity16F: + return GL.GL_INTENSITY16F_ARB; + case Intensity32F: + return GL.GL_INTENSITY32F_ARB; + case R8: + return 0x8229;// GL.GL_R8; + case R16: + return 0x822A;// GL.GL_R16; + case RG8: + return 0x822B;// GL.GL_RG8; + case RG16: + return 0x822C;// GL.GL_RG16; + case R16F: + return 0x822D;// GL.GL_R16F; + case R32F: + return 0x822E;// GL.GL_R32F; + case RG16F: + return 0x822F;// GL.GL_RG16F; + case RG32F: + return 0x8230;// GL.GL_RG32F; + case R8I: + return 0x8231;// GL.GL_R8I; + case R8UI: + return 0x8232;// GL.GL_R8UI; + case R16I: + return 0x8233;// GL.GL_R16I; + case R16UI: + return 0x8234;// GL.GL_R16UI; + case R32I: + return 0x8235;// GL.GL_R32I; + case R32UI: + return 0x8236;// GL.GL_R32UI; + case RG8I: + return 0x8237;// GL.GL_RG8I; + case RG8UI: + return 0x8238;// GL.GL_RG8UI; + case RG16I: + return 0x8239;// GL.GL_RG16I; + case RG16UI: + return 0x823A;// GL.GL_RG16UI; + case RG32I: + return 0x823B;// GL.GL_RG32I; + case RG32UI: + return 0x823C;// GL.GL_RG32UI; + } + 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_ARB; + case Short: + return GL.GL_SHORT; + case UnsignedShort: + return GL.GL_UNSIGNED_SHORT; + case Int: + return GL.GL_INT; + case UnsignedInt: + return GL.GL_UNSIGNED_INT; + case UnsignedByte: + return GL.GL_UNSIGNED_BYTE; + case UnsignedByte_3_3_2: + return GL.GL_UNSIGNED_BYTE_3_3_2; + case UnsignedByte_2_3_3_Rev: + return GL.GL_UNSIGNED_BYTE_2_3_3_REV; + case UnsignedShort_5_6_5: + return GL.GL_UNSIGNED_SHORT_5_6_5; + case UnsignedShort_5_6_5_Rev: + return GL.GL_UNSIGNED_SHORT_5_6_5_REV; + case UnsignedShort_4_4_4_4: + return GL.GL_UNSIGNED_SHORT_4_4_4_4; + case UnsignedShort_4_4_4_4_Rev: + return GL.GL_UNSIGNED_SHORT_4_4_4_4_REV; + case UnsignedShort_5_5_5_1: + return GL.GL_UNSIGNED_SHORT_5_5_5_1; + case UnsignedShort_1_5_5_5_Rev: + return GL.GL_UNSIGNED_SHORT_1_5_5_5_REV; + case UnsignedInt_8_8_8_8: + return GL.GL_UNSIGNED_INT_8_8_8_8; + case UnsignedInt_8_8_8_8_Rev: + return GL.GL_UNSIGNED_INT_8_8_8_8_REV; + case UnsignedInt_10_10_10_2: + return GL.GL_UNSIGNED_INT_10_10_10_2; + case UnsignedInt_2_10_10_10_Rev: + return GL.GL_UNSIGNED_INT_2_10_10_10_REV; + 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 RG: + return 0x8227;// GL.GL_RG; + case Alpha: + return GL.GL_ALPHA; + case Luminance: + return GL.GL_LUMINANCE; + case Intensity: + return GL.GL_INTENSITY; + case LuminanceAlpha: + return GL.GL_LUMINANCE_ALPHA; + case Depth: + return GL.GL_DEPTH_COMPONENT; + case BGR: + return GL.GL_BGR; + case BGRA: + return GL.GL_BGRA; + case Red: + return GL.GL_RED; + case Blue: + return GL.GL_BLUE; + case Green: + return GL.GL_GREEN; + case ColorIndex: + return GL.GL_COLOR_INDEX; + case StencilIndex: + return GL.GL_STENCIL_INDEX; + } + 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 GL.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 GL.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 GL.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 0x8227; // Jogl1 missing GL_RG + } + 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 GL.GL_INTENSITY; + } + } + + public static int getGLDepthTextureCompareMode(final DepthTextureCompareMode mode) { + switch (mode) { + case RtoTexture: + return GL.GL_COMPARE_R_TO_TEXTURE_ARB; + 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 GL.GL_COMBINE; + case Decal: + return GL.GL_DECAL; + case Add: + return GL.GL_ADD; + case Modulate: + return GL.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 GL.GL_PRIMARY_COLOR; + case Constant: + return GL.GL_CONSTANT; + case Previous: + return GL.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 GL.GL_MODULATE; + case Replace: + return GL.GL_REPLACE; + case Add: + return GL.GL_ADD; + case AddSigned: + return GL.GL_ADD_SIGNED; + case Subtract: + return GL.GL_SUBTRACT; + case Interpolate: + return GL.GL_INTERPOLATE; + } + throw new IllegalArgumentException("invalid CombinerFunctionAlpha type: " + combineFunc); + } + + public static int getGLCombineFuncRGB(final CombinerFunctionRGB combineFunc) { + switch (combineFunc) { + case Modulate: + return GL.GL_MODULATE; + case Replace: + return GL.GL_REPLACE; + case Add: + return GL.GL_ADD; + case AddSigned: + return GL.GL_ADD_SIGNED; + case Subtract: + return GL.GL_SUBTRACT; + case Interpolate: + return GL.GL_INTERPOLATE; + case Dot3RGB: + return GL.GL_DOT3_RGB; + case Dot3RGBA: + return GL.GL_DOT3_RGBA; + } + throw new IllegalArgumentException("invalid CombinerFunctionRGB type: " + combineFunc); + } +} diff --git a/trunk/ardor3d-jogl/src/main/native/macosx/libgluegen-rt.jnilib b/trunk/ardor3d-jogl/src/main/native/macosx/libgluegen-rt.jnilib Binary files differnew file mode 100644 index 0000000..1956280 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/native/macosx/libgluegen-rt.jnilib diff --git a/trunk/ardor3d-jogl/src/main/native/macosx/libjogl.jnilib b/trunk/ardor3d-jogl/src/main/native/macosx/libjogl.jnilib Binary files differnew file mode 100644 index 0000000..85dac01 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/native/macosx/libjogl.jnilib diff --git a/trunk/ardor3d-jogl/src/main/native/macosx/libjogl_awt.jnilib b/trunk/ardor3d-jogl/src/main/native/macosx/libjogl_awt.jnilib Binary files differnew file mode 100644 index 0000000..2f16fbf --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/native/macosx/libjogl_awt.jnilib diff --git a/trunk/ardor3d-jogl/src/main/native/macosx/libjogl_cg.jnilib b/trunk/ardor3d-jogl/src/main/native/macosx/libjogl_cg.jnilib Binary files differnew file mode 100644 index 0000000..5627121 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/native/macosx/libjogl_cg.jnilib diff --git a/trunk/ardor3d-jogl/src/main/native/win32/gluegen-rt.dll b/trunk/ardor3d-jogl/src/main/native/win32/gluegen-rt.dll Binary files differnew file mode 100644 index 0000000..9b373f3 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/native/win32/gluegen-rt.dll diff --git a/trunk/ardor3d-jogl/src/main/native/win32/jogl.dll b/trunk/ardor3d-jogl/src/main/native/win32/jogl.dll Binary files differnew file mode 100644 index 0000000..ce466f0 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/native/win32/jogl.dll diff --git a/trunk/ardor3d-jogl/src/main/native/win32/jogl_awt.dll b/trunk/ardor3d-jogl/src/main/native/win32/jogl_awt.dll Binary files differnew file mode 100644 index 0000000..2f0b6a6 --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/native/win32/jogl_awt.dll diff --git a/trunk/ardor3d-jogl/src/main/native/win32/jogl_cg.dll b/trunk/ardor3d-jogl/src/main/native/win32/jogl_cg.dll Binary files differnew file mode 100644 index 0000000..985781d --- /dev/null +++ b/trunk/ardor3d-jogl/src/main/native/win32/jogl_cg.dll |