diff --git a/core/.settings/org.eclipse.jdt.core.prefs b/core/.settings/org.eclipse.jdt.core.prefs index e2158402c..83612999f 100644 --- a/core/.settings/org.eclipse.jdt.core.prefs +++ b/core/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,248 @@ -#Mon Jul 17 22:49:52 EDT 2006 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1 -org.eclipse.jdt.core.compiler.compliance=1.3 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore -org.eclipse.jdt.core.compiler.source=1.3 +#Tue Jul 18 18:46:40 EDT 2006 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1 +org.eclipse.jdt.core.compiler.compliance=1.3 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore +org.eclipse.jdt.core.compiler.source=1.3 +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=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=82 +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=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +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=1 +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=0 +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=false +org.eclipse.jdt.core.formatter.comment.format_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_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=80 +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_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_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=false +org.eclipse.jdt.core.formatter.indentation.size=2 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=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_anonymous_type_declaration=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=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=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_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=80 +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=2 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false diff --git a/core/.settings/org.eclipse.jdt.ui.prefs b/core/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..3bfe298dd --- /dev/null +++ b/core/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,4 @@ +#Tue Jul 18 14:22:13 EDT 2006 +eclipse.preferences.version=1 +formatter_settings_version=8 +org.eclipse.jdt.ui.text.custom_code_templates= diff --git a/core/src/processing/core/PConstants.java b/core/src/processing/core/PConstants.java index b3b7553da..641b1285b 100644 --- a/core/src/processing/core/PConstants.java +++ b/core/src/processing/core/PConstants.java @@ -326,12 +326,14 @@ public interface PConstants { static final int MY = 10; static final int MZ = 11; - static final int SR = 12; // stroke colors + /** stroke argb values */ + static final int SR = 12; static final int SG = 13; static final int SB = 14; static final int SA = 15; - static final int SW = 16; // stroke weight + /** stroke weight */ + static final int SW = 16; // not used in rendering // only used for calculating colors diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java index 4d23f84e6..9141f4903 100644 --- a/core/src/processing/core/PGraphics.java +++ b/core/src/processing/core/PGraphics.java @@ -201,7 +201,7 @@ public abstract class PGraphics extends PImage implements PConstants { // ........................................................ - Path path; + //Path path; // ........................................................ @@ -604,15 +604,6 @@ public abstract class PGraphics extends PImage implements PConstants { // other stroke attributes are set in the initializers // inside the class (see above, strokeWeight = 1 et al) - // if this fella is associated with an applet, then clear its background. - // if it's been created by someone else through createGraphics, - // they have to call background() themselves, otherwise everything gets - // a gray background (when just a transparent surface or an empty pdf - // is what's desired) - if (parent != null) { - background(204); - } - // init shape stuff shape = 0; @@ -631,14 +622,26 @@ public abstract class PGraphics extends PImage implements PConstants { textAlign = LEFT; textMode = MODEL; + // if this fella is associated with an applet, then clear its background. + // if it's been created by someone else through createGraphics, + // they have to call background() themselves, otherwise everything gets + // a gray background (when just a transparent surface or an empty pdf + // is what's desired) + if (parent != null) { + background(204); + } + defaultsInited = true; } + /* protected void flush() { // no-op, mostly for P3D to write sorted stuff } + */ + ////////////////////////////////////////////////////////////// @@ -666,6 +669,7 @@ public abstract class PGraphics extends PImage implements PConstants { hints[which] = true; } + /** * Disable a hint. */ @@ -673,6 +677,7 @@ public abstract class PGraphics extends PImage implements PConstants { hints[which] = false; } + ////////////////////////////////////////////////////////////// @@ -708,7 +713,8 @@ public abstract class PGraphics extends PImage implements PConstants { * the code and maintain it. for beta, the latter is most important so * that's how things are implemented. */ - public void beginShape(int kind) { + abstract public void beginShape(int kind); + /* shape = kind; // reset vertex, line and triangle information @@ -721,23 +727,72 @@ public abstract class PGraphics extends PImage implements PConstants { //strokeChanged = false; //fillChanged = false; //normalChanged = false; - } + */ public void normal(float nx, float ny, float nz) { depthError("normal"); } + + /** + * Set texture mode to either to use coordinates based on the IMAGE + * (more intuitive for new users) or NORMALIZED (better for advanced chaps) + */ public void textureMode(int mode) { - depthError("textureMode"); + this.textureMode = mode; } + + /** + * Set texture image for current shape. + * Needs to be called between @see beginShape and @see endShape + * + * @param image reference to a PImage object + */ public void texture(PImage image) { - depthError("texture"); + textureImage = image; + } + + + /** + * Set (U, V) coords for the next vertex in the current shape. + * This is ugly as its own function, and will (almost?) always be + * coincident with a call to vertex. As of beta, this was moved to + * the protected method you see here, and called from an optional + * param of and overloaded vertex(). + *

+ * The parameters depend on the current textureMode. When using + * textureMode(IMAGE), the coordinates will be relative to the size + * of the image texture, when used with textureMode(NORMAL), + * they'll be in the range 0..1. + *

+ * Used by both PGraphics2D (for images) and PGraphics3D. + */ + protected void textureVertex(float u, float v) { + if (textureImage == null) { + throw new RuntimeException("need to set an image with texture() " + + "before using u and v coordinates"); + } + if (textureMode == IMAGE) { + u /= (float) textureImage.width; + v /= (float) textureImage.height; + } + + textureU = u; + textureV = v; + + if (textureU < 0) textureU = 0; + else if (textureU > ONE) textureU = ONE; + + if (textureV < 0) textureV = 0; + else if (textureV > ONE) textureV = ONE; } - public void vertex(float x, float y) { + // eventually need to push a "default" setup down to this class + abstract public void vertex(float x, float y); + /* splineVertexCount = 0; //float vertex[]; @@ -872,35 +927,150 @@ public abstract class PGraphics extends PImage implements PConstants { } break; } + */ + + + abstract public void vertex(float x, float y, float z); + + + abstract public void vertex(float x, float y, float u, float v); + + + abstract public void vertex(float x, float y, float z, float u, float v); + + + public void bezierVertex(float x2, float y2, + float x3, float y3, + float x4, float y4) { + bezierVertex(x2, y2, Float.MAX_VALUE, + x3, y3, Float.MAX_VALUE, + x4, y4, Float.MAX_VALUE); + } + + + /** + * See notes with the bezier() function. + */ + public void bezierVertex(float x2, float y2, float z2, + float x3, float y3, float z3, + float x4, float y4, float z4) { + if (shape != POLYGON) { + throw new RuntimeException("beginShape() and vertex() " + + "must be used before bezierVertex()"); + } + if (splineVertexCount > 0) { + float vertex[] = splineVertices[splineVertexCount-1]; + splineVertex(vertex[MX], vertex[MY], vertex[MZ], true); + + } else if (vertexCount > 0) { + // make sure there's at least a call to vertex() + float vertex[] = vertices[vertexCount-1]; + splineVertex(vertex[MX], vertex[MY], vertex[MZ], true); + + } else { + throw new RuntimeException("A call to vertex() must be used " + + "before bezierVertex()"); + } + splineVertex(x2, y2, z2, true); + splineVertex(x3, y3, z3, true); + splineVertex(x4, y4, z4, true); + } + + + /** + * See notes with the curve() function. + */ + public void curveVertex(float x, float y) { + splineVertex(x, y, Float.MAX_VALUE, false); } - public void vertex(float x, float y, float z) { - depthErrorXYZ("vertex"); + /** + * See notes with the curve() function. + */ + public void curveVertex(float x, float y, float z) { + splineVertex(x, y, z, false); } - public void vertex(float x, float y, float u, float v) { - throw new RuntimeException("vertex() with u, v coordinates " + - "can only be used with OPENGL or P3D"); - } - - - public void vertex(float x, float y, float z, float u, float v) { - throw new RuntimeException("vertex() with u, v coordinates " + - "can only be used with OPENGL or P3D"); - } - - - public void bezierVertex(float x1, float y1, - float x2, float y2, - float x3, float y3) { - // if there hasn't yet been a call to vertex(), throw an error - - // otherwise, draw a bezier segment to this point + protected void splineVertex(float x, float y, float z, boolean bezier) { + // to improve processing applet load times, don't allocate + // space for the vertex data until actual use + if (splineVertices == null) { + splineVertices = new float[DEFAULT_SPLINE_VERTICES][VERTEX_FIELD_COUNT]; + } + + // if more than 128 points, shift everything back to the beginning + if (splineVertexCount == DEFAULT_SPLINE_VERTICES) { + System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-3], 0, + splineVertices[0], 0, VERTEX_FIELD_COUNT); + System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-2], 0, + splineVertices[1], 0, VERTEX_FIELD_COUNT); + System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-1], 0, + splineVertices[2], 0, VERTEX_FIELD_COUNT); + splineVertexCount = 3; + } + + float vertex[] = splineVertices[splineVertexCount]; + + vertex[MX] = x; + vertex[MY] = y; + + if (fill) { + vertex[R] = fillR; + vertex[G] = fillG; + vertex[B] = fillB; + vertex[A] = fillA; + } + + if (stroke) { + vertex[SR] = strokeR; + vertex[SG] = strokeG; + vertex[SB] = strokeB; + vertex[SA] = strokeA; + vertex[SW] = strokeWeight; + } + + if (textureImage != null) { + vertex[U] = textureU; + vertex[V] = textureV; + } + + // when the coords are Float.MAX_VALUE, then treat as a 2D curve + int dimensions = (x == Float.MAX_VALUE) ? 2 : 3; + + if (dimensions == 3) { + vertex[MZ] = z; + + vertex[NX] = normalX; + vertex[NY] = normalY; + vertex[NZ] = normalZ; + } + + splineVertexCount++; + + // draw a segment if there are enough points + if (splineVertexCount > 3) { + if (bezier) { + if ((splineVertexCount % 4) == 0) { + if (!bezierInited) bezier_init(); + splineSegment(splineVertexCount-4, + splineVertexCount-4, + bezier_draw, dimensions, + bezierDetail); + } + } else { // catmull-rom curve (!bezier) + if (!curve_inited) curve_init(); + splineSegment(splineVertexCount-4, + splineVertexCount-3, + curve_draw, dimensions, + curveDetail); + } + } } +/* protected void bezier_vertex(float x, float y) { vertexCount = 0; @@ -941,33 +1111,41 @@ public abstract class PGraphics extends PImage implements PConstants { "LINE_LOOP and POLYGON shapes"); } } + */ + /* public void bezierVertex(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3) { depthErrorXYZ("bezierVertex"); } + */ /** * See notes with the curve() function. */ + /* public void curveVertex(float x, float y) { //throw new RuntimeException("curveVertex() temporarily disabled"); // TODO get matrix setup happening } + */ /** * See notes with the curve() function. */ + /* public void curveVertex(float x, float y, float z) { depthErrorXYZ("curveVertex"); } + */ - public void endShape() { + abstract public void endShape(); + /* shape = 0; switch (shape) { @@ -986,6 +1164,7 @@ public abstract class PGraphics extends PImage implements PConstants { break; } } + */ @@ -1036,6 +1215,7 @@ public abstract class PGraphics extends PImage implements PConstants { // STROKE/FILL/DRAW + /* //protected void fill_shape(Shape s) { protected void fill_shape(Path s) { if (fill) { @@ -1063,44 +1243,64 @@ public abstract class PGraphics extends PImage implements PConstants { //graphics.draw(s); } } + */ - + ////////////////////////////////////////////////////////////// - // POINT + // SIMPLE SHAPES WITH ANALOGUES IN beginShape() public void point(float x, float y) { - // TODO + beginShape(POINTS); + vertex(x, y); + endShape(); } public void point(float x, float y, float z) { - depthErrorXYZ("point"); + beginShape(POINTS); + vertex(x, y, z); + endShape(); } public void line(float x1, float y1, float x2, float y2) { - // TODO + beginShape(LINES); + vertex(x1, y1); + vertex(x2, y2); + endShape(); } public void line(float x1, float y1, float z1, float x2, float y2, float z2) { - depthErrorXYZ("line"); + beginShape(LINES); + vertex(x1, y1, z1); + vertex(x2, y2, z2); + endShape(); } public void triangle(float x1, float y1, float x2, float y2, float x3, float y3) { - // TODO + beginShape(TRIANGLES); + vertex(x1, y1); + vertex(x2, y2); + vertex(x3, y3); + endShape(); } public void quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { - // TODO + beginShape(QUADS); + vertex(x1, y1); + vertex(x2, y2); + vertex(x3, y3); + vertex(x4, y4); + endShape(); } @@ -1153,7 +1353,12 @@ public abstract class PGraphics extends PImage implements PConstants { protected void rectImpl(float x1, float y1, float x2, float y2) { - // TODO write rect drawing function + beginShape(QUADS); + vertex(x1, y1); + vertex(x2, y1); + vertex(x2, y2); + vertex(x1, y2); + endShape(); } @@ -1586,6 +1791,62 @@ public abstract class PGraphics extends PImage implements PConstants { * for catmull-rom curves, the first control point (x2, y2, z2) * is the first drawn point, and is accumulated to. */ + protected void splineSegment(int offset, int start, float m[][], + int dimensions, int segments) { + float x1 = splineVertices[offset+0][MX]; + float x2 = splineVertices[offset+1][MX]; + float x3 = splineVertices[offset+2][MX]; + float x4 = splineVertices[offset+3][MX]; + float x0 = splineVertices[start][MX]; + + float y1 = splineVertices[offset+0][MY]; + float y2 = splineVertices[offset+1][MY]; + float y3 = splineVertices[offset+2][MY]; + float y4 = splineVertices[offset+3][MY]; + float y0 = splineVertices[start][MY]; + + float xplot1 = m[1][0]*x1 + m[1][1]*x2 + m[1][2]*x3 + m[1][3]*x4; + float xplot2 = m[2][0]*x1 + m[2][1]*x2 + m[2][2]*x3 + m[2][3]*x4; + float xplot3 = m[3][0]*x1 + m[3][1]*x2 + m[3][2]*x3 + m[3][3]*x4; + + float yplot1 = m[1][0]*y1 + m[1][1]*y2 + m[1][2]*y3 + m[1][3]*y4; + float yplot2 = m[2][0]*y1 + m[2][1]*y2 + m[2][2]*y3 + m[2][3]*y4; + float yplot3 = m[3][0]*y1 + m[3][1]*y2 + m[3][2]*y3 + m[3][3]*y4; + + // vertex() will reset splineVertexCount, so save it + int cvertexSaved = splineVertexCount; + + if (dimensions == 3) { + float z1 = splineVertices[offset+0][MZ]; + float z2 = splineVertices[offset+1][MZ]; + float z3 = splineVertices[offset+2][MZ]; + float z4 = splineVertices[offset+3][MZ]; + float z0 = splineVertices[start][MZ]; + + float zplot1 = m[1][0]*z1 + m[1][1]*z2 + m[1][2]*z3 + m[1][3]*z4; + float zplot2 = m[2][0]*z1 + m[2][1]*z2 + m[2][2]*z3 + m[2][3]*z4; + float zplot3 = m[3][0]*z1 + m[3][1]*z2 + m[3][2]*z3 + m[3][3]*z4; + + vertex(x0, y0, z0); + for (int j = 0; j < segments; j++) { + x0 += xplot1; xplot1 += xplot2; xplot2 += xplot3; + y0 += yplot1; yplot1 += yplot2; yplot2 += yplot3; + z0 += zplot1; zplot1 += zplot2; zplot2 += zplot3; + vertex(x0, y0, z0); + } + } else { + vertex(x0, y0); + for (int j = 0; j < segments; j++) { + x0 += xplot1; xplot1 += xplot2; xplot2 += xplot3; + y0 += yplot1; yplot1 += yplot2; yplot2 += yplot3; + vertex(x0, y0); + } + } + splineVertexCount = cvertexSaved; + } + + + /* protected void spline2_segment(int offset, int start, float m[][], int segments) { float x1 = splineVertices[offset][MX]; @@ -1668,6 +1929,7 @@ public abstract class PGraphics extends PImage implements PConstants { } splineVertexCount = cvertexSaved; } + */ @@ -3391,13 +3653,21 @@ public abstract class PGraphics extends PImage implements PConstants { "with P3D or OPENGL."); } + protected void depthErrorXYZ(String method) { throw new RuntimeException(method + "(x, y, z) can only be used with " + "OPENGL or P3D, use " + method + "(x, y) instead."); } + + + protected void unavailableError(String methodStr) { + throw new RuntimeException(methodStr + + " is not available with this renderer"); + } + ////////////////////////////////////////////////////////////// // COLOR MANIPULATION @@ -3553,11 +3823,23 @@ public abstract class PGraphics extends PImage implements PConstants { } + + ////////////////////////////////////////////////////////////// + + // MATH + + + static final float sqrt(float a) { + return (float)Math.sqrt(a); + } + + ////////////////////////////////////////////////////////////// // PATH + /* class Path { public void moveTo(float x, float y) { // ignore @@ -3574,7 +3856,8 @@ public abstract class PGraphics extends PImage implements PConstants { public void closePath() { // ignore } } - + */ + ////////////////////////////////////////////////////////////// @@ -3611,7 +3894,7 @@ public abstract class PGraphics extends PImage implements PConstants { public void endRaw() { if (raw != null) { // for 3D, need to flush any geometry that's been stored for sorting - raw.flush(); + //raw.flush(); // this should be called by endDraw() instead // just like beginDraw, this will have to be called because // endDraw() will be happening outside of draw() diff --git a/core/src/processing/core/PGraphics2D.java b/core/src/processing/core/PGraphics2D.java index fa48ed456..79bc93cb6 100644 --- a/core/src/processing/core/PGraphics2D.java +++ b/core/src/processing/core/PGraphics2D.java @@ -27,9 +27,6 @@ import java.awt.Toolkit; import java.awt.image.DirectColorModel; import java.awt.image.MemoryImageSource; -//import java.awt.*; -//import java.awt.image.*; - /** * Subclass of PGraphics that handles fast 2D rendering, @@ -38,6 +35,29 @@ import java.awt.image.MemoryImageSource; */ public class PGraphics2D extends PGraphics { + PPolygon polygon; // general polygon to use for shape + PPolygon fpolygon; // used to fill polys for tri or quad strips + PPolygon spolygon; // stroke/line polygon + float svertices[][]; // temp vertices used for stroking end of poly + + // polygon that handles tesselation + private PPolygon tpolygon; + private int TPOLYGON_MAX_VERTICES = 512; + private int tpolygon_vertex_order[]; // = new int[MAX_VERTICES]; + + PLine line; + + boolean untransformed; + boolean strokeChanged = true; + boolean fillChanged = true; + + static final int CVERTEX_ALLOC = 128; + float cvertex[][] = new float[CVERTEX_ALLOC][VERTEX_FIELD_COUNT]; + int cvertexIndex; + + + ////////////////////////////////////////////////////////////// + protected PGraphics2D() { } @@ -83,11 +103,22 @@ public class PGraphics2D extends PGraphics { } + ////////////////////////////////////////////////////////////// + + public void beginDraw() { // need to call defaults(), but can only be done when it's ok // to draw (i.e. for opengl, no drawing can be done outside // beginDraw/endDraw). - if (!defaultsInited) defaults(); + if (!defaultsInited) { + defaults(); + + polygon = new PPolygon(this); + fpolygon = new PPolygon(this); + spolygon = new PPolygon(this); + spolygon.vertexCount = 4; + svertices = new float[2][]; + } resetMatrix(); // reset model matrix @@ -105,4 +136,1428 @@ public class PGraphics2D extends PGraphics { // when this PGraphics is drawn using image(). endPixels(); } -} \ No newline at end of file + + + ////////////////////////////////////////////////////////////// + + + public void beginShape(int kind) { + shape = kind; + vertexCount = 0; + splineVertexCount = 0; + + polygon.reset(0); + fpolygon.reset(4); + spolygon.reset(4); + + polygon.interpUV = false; + } + + + // PGraphics will throw a depthError + //public void normal(float nx, float ny, float nz) + + // PGraphics will handle setting these + //public void textureMode(int mode) + //public void texture(PImage image) + //protected void textureVertex(float u, float v) + + + public void vertex(float x, float y) { + float vertex[] = polygon.nextVertex(); + cvertexIndex = 0; // reset curves to start + + vertex[MX] = x; + vertex[MY] = y; + + if (fill) { + vertex[R] = fillR; + vertex[G] = fillG; + vertex[B] = fillB; + vertex[A] = fillA; + } + + if (stroke) { + vertex[SR] = strokeR; + vertex[SG] = strokeG; + vertex[SB] = strokeB; + vertex[SA] = strokeA; + vertex[SW] = strokeWeight; + } + + // this complicated if construct may defeat the purpose + if (textureImage != null) { + vertex[U] = textureU; + vertex[V] = textureV; + } + } + + + public void vertex(float x, float y, float u, float v) { + textureVertex(u, v); + vertex(x, y); + } + + + public void vertex(float x, float y, float z) { + depthErrorXYZ("vertex"); + } + + + public void vertex(float x, float y, float z, float u, float v) { + depthErrorXYZ("vertex"); + } + + + public void endShape() { + // clear the 'shape drawing' flag in case of early exit + //shape = 0; + // hm can't do anymore.. + + int vertexCount = polygon.vertexCount; + float vertices[][] = polygon.vertices; + + if (untransformed) { + for (int i = 0; i < vertexCount; i++) { + vertices[i][X] = vertices[i][MX]; + vertices[i][Y] = vertices[i][MY]; + } + } else { + for (int i = 0; i < vertexCount; i++) { + vertices[i][X] = m00*vertices[i][MX] + m01*vertices[i][MY] + m03; + vertices[i][Y] = m10*vertices[i][MX] + m11*vertices[i][MY] + m13; + } + } + + // ------------------------------------------------------------------ + // TEXTURES + + if (polygon.interpUV) { + fpolygon.texture(textureImage); //polygon.timage); + } + + + // ------------------------------------------------------------------ + // COLORS + // calculate RGB for each vertex + + spolygon.interpARGB = strokeChanged; //false; + fpolygon.interpARGB = fillChanged; //false; + + // all the values for r, g, b have been set with calls to vertex() + // (no need to re-calculate anything here) + + + // ------------------------------------------------------------------ + // RENDER SHAPES + + int increment; + + switch (shape) { + case POINTS: + if (untransformed && (strokeWeight == 1)) { + if (!strokeChanged) { + for (int i = 0; i < vertexCount; i++) { + thin_point((int) vertices[i][X], (int) vertices[i][Y], + 0, strokeColor); + } + } else { + for (int i = 0; i < vertexCount; i++) { + thin_point((int) vertices[i][X], (int) vertices[i][Y], + 0, float_color(vertices[i][SR], + vertices[i][SG], + vertices[i][SB])); + } + //strokei = strokeiSaved; + } + } else { + float f[] = vertices[0]; + + for (int i = 0; i < vertexCount; i++) { + float v[] = vertices[i]; + + // if this is the first time (i == 0) + // or if lighting is enabled + // or the stroke color has changed inside beginShape/endShape + // then re-calculate the color at this vertex + if ((i == 0) || strokeChanged) { + // push calculated color into 'f' (this way, f is always valid) + calc_lighting(v[SR], v[SG], v[SB], + v[X], v[Y], v[Z], + v[NX], v[NY], v[NZ], f, R); + } + // uses [SA], since stroke alpha isn't moved into [A] the + // way that [SR] goes to [R] etc on the calc_lighting call + // (there's no sense in copying it to [A], except consistency + // in the code.. but why the extra slowness?) + thick_point(v[X], v[Y], v[Z], f[R], f[G], f[B], f[SA]); + } + } + break; + + case LINES: + //case LINE_STRIP: + //case LINE_LOOP: + if (!stroke) return; + + // if it's a line loop, copy the vertex data to the last element + if (shape == LINE_LOOP) { + float v0[] = polygon.vertices[0]; + float v1[] = polygon.nextVertex(); + vertexCount++; // since it had already been read above + + v1[X] = v0[X]; v1[Y] = v0[Y]; v1[Z] = v0[Z]; + v1[SR] = v0[SR]; v1[SG] = v0[SG]; v1[SB] = v0[SB]; + } + + // increment by two for individual lines + increment = (shape == LINES) ? 2 : 1; + draw_lines(vertices, vertexCount-1, 1, increment, 0); + break; + + case TRIANGLES: + case TRIANGLE_STRIP: + increment = (shape == TRIANGLES) ? 3 : 1; + // do fill and stroke separately because otherwise + // the lines will be stroked more than necessary + if (fill) { + fpolygon.vertexCount = 3; + for (int i = 0; i < vertexCount-2; i += increment) { + for (int j = 0; j < 3; j++) { + fpolygon.vertices[j][R] = vertices[i+j][R]; + fpolygon.vertices[j][G] = vertices[i+j][G]; + fpolygon.vertices[j][B] = vertices[i+j][B]; + fpolygon.vertices[j][A] = vertices[i+j][A]; + + fpolygon.vertices[j][X] = vertices[i+j][X]; + fpolygon.vertices[j][Y] = vertices[i+j][Y]; + fpolygon.vertices[j][Z] = vertices[i+j][Z]; + + if (polygon.interpUV) { + fpolygon.vertices[j][U] = vertices[i+j][U]; + fpolygon.vertices[j][V] = vertices[i+j][V]; + } + } + fpolygon.render(); + } + } + if (stroke) { + // first draw all vertices as a line strip + if (shape == TRIANGLE_STRIP) { + draw_lines(vertices, vertexCount-1, 1, 1, 0); + } else { + draw_lines(vertices, vertexCount-1, 1, 1, 3); + } + // then draw from vertex (n) to (n+2) + // incrementing n using the same as above + draw_lines(vertices, vertexCount-2, 2, increment, 0); + // changed this to vertexCount-2, because it seemed + // to be adding an extra (nonexistant) line + } + break; + + case QUADS: + case QUAD_STRIP: + //System.out.println("pooping out a quad"); + increment = (shape == QUADS) ? 4 : 2; + if (fill) { + fpolygon.vertexCount = 4; + for (int i = 0; i < vertexCount-3; i += increment) { + for (int j = 0; j < 4; j++) { + fpolygon.vertices[j][R] = vertices[i+j][R]; + fpolygon.vertices[j][G] = vertices[i+j][G]; + fpolygon.vertices[j][B] = vertices[i+j][B]; + fpolygon.vertices[j][A] = vertices[i+j][A]; + + fpolygon.vertices[j][X] = vertices[i+j][X]; + fpolygon.vertices[j][Y] = vertices[i+j][Y]; + fpolygon.vertices[j][Z] = vertices[i+j][Z]; + + if (polygon.interpUV) { + fpolygon.vertices[j][U] = vertices[i+j][U]; + fpolygon.vertices[j][V] = vertices[i+j][V]; + } + } + fpolygon.render(); + } + } + if (stroke) { + // first draw all vertices as a line strip + if (shape == QUAD_STRIP) { + draw_lines(vertices, vertexCount-1, 1, 1, 0); + } else { // skip every few for quads + draw_lines(vertices, vertexCount, 1, 1, 4); + } + // then draw from vertex (n) to (n+3) + // incrementing n by the same increment as above + draw_lines(vertices, vertexCount-2, 3, increment, 0); + } + break; + + case POLYGON: + if (isConvex()) { + if (fill) { + polygon.render(); + if (stroke) polygon.unexpand(); + } + + if (stroke) { + draw_lines(vertices, vertexCount-1, 1, 1, 0); + // draw the last line connecting back to the first point in poly + svertices[0] = vertices[vertexCount-1]; + svertices[1] = vertices[0]; + draw_lines(svertices, 1, 1, 1, 0); + } + } else { + if (fill) { + // the triangulator produces polygons that don't align + // when smoothing is enabled. but if there is a stroke around + // the polygon, then smoothing can be temporarily disabled. + boolean smoov = smooth; + //if (stroke && !hints[DISABLE_SMOOTH_HACK]) smooth = false; + if (stroke) smooth = false; + concaveRender(); + //if (stroke && !hints[DISABLE_SMOOTH_HACK]) smooth = smoov; + if (stroke) smooth = smoov; + } + + if (stroke) { + draw_lines(vertices, vertexCount-1, 1, 1, 0); + // draw the last line connecting back + // to the first point in poly + svertices[0] = vertices[vertexCount-1]; + svertices[1] = vertices[0]; + draw_lines(svertices, 1, 1, 1, 0); + } + } + break; + } + + // to signify no shape being drawn + shape = 0; + } + + + + ////////////////////////////////////////////////////////////// + + // CONCAVE/CONVEX POLYGONS + + + private boolean isConvex() { + float v[][] = polygon.vertices; + int n = polygon.vertexCount; + int j,k; + int flag = 0; + float z; + //float tol = 0.001f; + + if (n < 3) + // ERROR: this is a line or a point, render with CONVEX + return true; + + // iterate along border doing dot product. + // if the sign of the result changes, then is concave + for (int i=0;i 0) + flag |= 2; + if (flag == 3) + return false; // CONCAVE + } + if (flag != 0) + return true; // CONVEX + else + // ERROR: colinear points, self intersection + // treat as CONVEX + return true; + } + + + // triangulate the current polygon + private void concaveRender() { + // WARNING: code is not in optimum form + // local initiations of some variables are made to + // keep the code modular and easy to integrate + // restet triangle + float vertices[][] = polygon.vertices; + + if (tpolygon == null) { + // allocate on first use, rather than slowing + // the startup of the class. + tpolygon = new PPolygon(this); + tpolygon_vertex_order = new int[TPOLYGON_MAX_VERTICES]; + } + tpolygon.reset(3); + + // copy render parameters + + if (textureImage != null) { + tpolygon.texture(textureImage); //polygon.timage); + } + + tpolygon.interpX = polygon.interpX; + tpolygon.interpZ = polygon.interpZ; + tpolygon.interpUV = polygon.interpUV; + tpolygon.interpARGB = polygon.interpARGB; + + // simple ear clipping polygon triangulation + // addapted from code by john w. ratcliff (jratcliff@verant.com) + + // 1 - first we check if the polygon goes CW or CCW + // CW-CCW ordering adapted from code by + // Joseph O'Rourke orourke@cs.smith.edu + // 1A - we start by finding the lowest-right most vertex + + boolean ccw = false; // clockwise + + int n = polygon.vertexCount; + int mm; // postion for LR vertex + float min[] = new float[2]; + + min[X] = vertices[0][X]; + min[Y] = vertices[0][Y]; + mm = 0; + + for(int i = 0; i < n; i++ ) { + if( (vertices[i][Y] < min[Y]) || + ( (vertices[i][Y] == min[Y]) && (vertices[i][X] > min[X]) ) + ) { + mm = i; + min[X] = vertices[mm][X]; + min[Y] = vertices[mm][Y]; + } + } + + // 1B - now we compute the cross product of the edges of this vertex + float cp; + int mm1; + + // just for renaming + float a[] = new float[2]; + float b[] = new float[2]; + float c[] = new float[2]; + + mm1 = (mm + (n-1)) % n; + + // assign a[0] to point to poly[m1][0] etc. + for(int i = 0; i < 2; i++ ) { + a[i] = vertices[mm1][i]; + b[i] = vertices[mm][i]; + c[i] = vertices[(mm+1)%n][i]; + } + + cp = a[0] * b[1] - a[1] * b[0] + + a[1] * c[0] - a[0] * c[1] + + b[0] * c[1] - c[0] * b[1]; + + if ( cp > 0 ) + ccw = true; // CCW + else + ccw = false; // CW + + // 1C - then we sort the vertices so they + // are always in a counterclockwise order + //int j = 0; + if (!ccw) { + // keep the same order + for (int i = 0; i < n; i++) { + tpolygon_vertex_order[i] = i; + } + + } else { + // invert the order + for (int i = 0; i < n; i++) { + tpolygon_vertex_order[i] = (n - 1) - i; + } + } + + // 2 - begin triangulation + // resulting triangles are stored in the triangle array + // remove vc-2 Vertices, creating 1 triangle every time + int vc = n; + int count = 2*vc; // complex polygon detection + + for (int m = 0, v = vc - 1; vc > 2; ) { + boolean snip = true; + + // if we start over again, is a complex polygon + if (0 >= (count--)) { + break; // triangulation failed + } + + // get 3 consecutive vertices + int u = v ; if (vc <= u) u = 0; // previous + v = u+1; if (vc <= v) v = 0; // current + int w = v+1; if (vc <= w) w = 0; // next + + // triangle A B C + float Ax, Ay, Bx, By, Cx, Cy, Px, Py; + + Ax = -vertices[tpolygon_vertex_order[u]][X]; + Ay = vertices[tpolygon_vertex_order[u]][Y]; + Bx = -vertices[tpolygon_vertex_order[v]][X]; + By = vertices[tpolygon_vertex_order[v]][Y]; + Cx = -vertices[tpolygon_vertex_order[w]][X]; + Cy = vertices[tpolygon_vertex_order[w]][Y]; + + if ( EPSILON > (((Bx-Ax) * (Cy-Ay)) - ((By-Ay) * (Cx-Ax)))) { + continue; + } + + for (int p = 0; p < vc; p++) { + + // this part is a bit osbscure, basically what it does + // is test if this tree vertices are and ear or not, looking for + // intersections with the remaining vertices using a cross product + float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; + float cCROSSap, bCROSScp, aCROSSbp; + + if( (p == u) || (p == v) || (p == w) ) { + continue; + } + + Px = -vertices[tpolygon_vertex_order[p]][X]; + Py = vertices[tpolygon_vertex_order[p]][Y]; + + ax = Cx - Bx; ay = Cy - By; + bx = Ax - Cx; by = Ay - Cy; + cx = Bx - Ax; cy = By - Ay; + apx= Px - Ax; apy= Py - Ay; + bpx= Px - Bx; bpy= Py - By; + cpx= Px - Cx; cpy= Py - Cy; + + aCROSSbp = ax * bpy - ay * bpx; + cCROSSap = cx * apy - cy * apx; + bCROSScp = bx * cpy - by * cpx; + + if ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)) { + snip = false; + } + } + + if (snip) { + // yes, the trio is an ear, render it and cut it + + int triangle_vertices[] = new int[3]; + int s,t; + + // true names of the vertices + triangle_vertices[0] = tpolygon_vertex_order[u]; + triangle_vertices[1] = tpolygon_vertex_order[v]; + triangle_vertices[2] = tpolygon_vertex_order[w]; + + // create triangle + //render_triangle(triangle_vertices); + //private final void render_triangle(int[] triangle_vertices) { + // copy all fields of the triangle vertices + for (int i = 0; i < 3; i++) { + float[] src = polygon.vertices[triangle_vertices[i]]; + float[] dest = tpolygon.vertices[i]; + for (int k = 0; k < VERTEX_FIELD_COUNT; k++) { + dest[k] = src[k]; + } + } + // render triangle + tpolygon.render(); + //} + + m++; + + // remove v from remaining polygon + for( s = v, t = v + 1; t < vc; s++, t++) { + tpolygon_vertex_order[s] = tpolygon_vertex_order[t]; + } + + vc--; + + // resest error detection counter + count = 2 * vc; + } + } + } + + + + ////////////////////////////////////////////////////////////// + + // RECT + + + protected void rectImpl(float x1f, float y1f, float x2f, float y2f) { + + if (untransformed() && !fillAlpha) { + int x1 = (int) x1f; + int y1 = (int) y1f; + int x2 = (int) x2f; + int y2 = (int) y2f; + + rectImplFillUnRGB(x1, y1, x2, y2); + + if (stroke) { + if (strokeWeight == 1) { + thin_flat_line(x1, y1, x2, y1); + thin_flat_line(x2, y1, x2, y2); + thin_flat_line(x2, y2, x1, y2); + thin_flat_line(x1, y2, x1, y1); + + } else { + thick_flat_line(x1, y1, fillR, fillG, fillB, fillA, + x2, y1, fillR, fillG, fillB, fillA); + thick_flat_line(x2, y1, fillR, fillG, fillB, fillA, + x2, y2, fillR, fillG, fillB, fillA); + thick_flat_line(x2, y2, fillR, fillG, fillB, fillA, + x1, y2, fillR, fillG, fillB, fillA); + thick_flat_line(x1, y2, fillR, fillG, fillB, fillA, + x1, y1, fillR, fillG, fillB, fillA); + } + } + + } else { + beginShape(QUADS); + vertex(x1f, y1f); + vertex(x2f, y1f); + vertex(x2f, y2f); + vertex(x1f, y2f); + endShape(); + } + } + + + /** + * Draw an untransformed rectangle with no alpha. + */ + private void rectImplFillUnRGB(int x1, int y1, int x2, int y2) { + //System.out.println("flat quad"); + if (y2 < y1) { + int temp = y1; y1 = y2; y2 = temp; + } + if (x2 < x1) { + int temp = x1; x1 = x2; x2 = temp; + } + // checking to watch out for boogers + if ((x1 > width1) || (x2 < 0) || + (y1 > height1) || (y2 < 0)) return; + + if (fill) { + int fx1 = x1; + int fy1 = y1; + int fx2 = x2; + int fy2 = y2; + + // these only affect the fill, not the stroke + // (otherwise strange boogers at edges b/c frame changes shape) + if (fx1 < 0) fx1 = 0; + if (fx2 > width) fx2 = width; + if (fy1 < 0) fy1 = 0; + if (fy2 > height) fy2 = height; + + // [toxi 031223] + // on avg. 20-25% faster fill routine using System.arraycopy() + int ww = fx2 - fx1; + int hh = fy2 - fy1; + int[] row = new int[ww]; + for (int i = 0; i < ww; i++) row[i] = fillColor; + int idx = fy1 * width + fx1; + for (int y = 0; y < hh; y++) { + System.arraycopy(row, 0, pixels, idx, ww); + idx += width; + } + row = null; + } + } + + + + ////////////////////////////////////////////////////////////// + + // RECT + + + + + + ////////////////////////////////////////////////////////////// + + // RENDERING + + + // expects properly clipped coords, hence does + // NOT check if x/y are in bounds [toxi] + private void thin_pointAt(int x, int y, float z, int color) { + int index = y*width+x; // offset values are pre-calced in constructor + pixels[index] = color; + zbuffer[index] = z; + } + + // expects offset/index in pixelbuffer array instead of x/y coords + // used by optimized parts of thin_flat_line() [toxi] + private void thin_pointAtIndex(int offset, float z, int color) { + pixels[offset] = color; + zbuffer[offset] = z; + } + + // points are inherently flat, but always tangent + // to the screen surface. the z is only so that things + // get scaled properly if the pt is way in back + private void thick_point(float x, float y, float z, // note floats + float r, float g, float b, float a) { + spolygon.reset(4); + spolygon.interpARGB = false; // no changes for vertices of a point + + float strokeWidth2 = strokeWeight/2.0f; + + float svertex[] = spolygon.vertices[0]; + svertex[X] = x - strokeWidth2; + svertex[Y] = y - strokeWidth2; + svertex[Z] = z; + + svertex[R] = r; + svertex[G] = g; + svertex[B] = b; + svertex[A] = a; + + svertex = spolygon.vertices[1]; + svertex[X] = x + strokeWidth2; + svertex[Y] = y - strokeWidth2; + svertex[Z] = z; + + svertex = spolygon.vertices[2]; + svertex[X] = x + strokeWidth2; + svertex[Y] = y + strokeWidth2; + svertex[Z] = z; + + svertex = spolygon.vertices[3]; + svertex[X] = x - strokeWidth2; + svertex[Y] = y + strokeWidth2; + svertex[Z] = z; + + spolygon.render(); + } + + + // new bresenham clipping code, as old one was buggy [toxi] + private void thin_flat_line(int x1, int y1, int x2, int y2) { + int nx1,ny1,nx2,ny2; + + // get the "dips" for the points to clip + int code1 = thin_flat_lineClipCode(x1, y1); + int code2 = thin_flat_lineClipCode(x2, y2); + + if ((code1 & code2)!=0) { + return; + } else { + int dip = code1 | code2; + if (dip != 0) { + // now calculate the clipped points + float a1 = 0, a2 = 1, a = 0; + for (int i=0;i<4;i++) { + if (((dip>>i)%2)==1) { + a = thin_flat_lineSlope((float)x1, (float)y1, + (float)x2, (float)y2, i+1); + if (((code1>>i)%2)==1) { + a1 = (float)Math.max(a, a1); + } else { + a2 = (float)Math.min(a, a2); + } + } + } + if (a1>a2) return; + else { + nx1=(int) (x1+a1*(x2-x1)); + ny1=(int) (y1+a1*(y2-y1)); + nx2=(int) (x1+a2*(x2-x1)); + ny2=(int) (y1+a2*(y2-y1)); + } + // line is fully visible/unclipped + } else { + nx1=x1; nx2=x2; + ny1=y1; ny2=y2; + } + } + + // new "extremely fast" line code + // adapted from http://www.edepot.com/linee.html + + boolean yLonger=false; + int shortLen=ny2-ny1; + int longLen=nx2-nx1; + if (Math.abs(shortLen)>Math.abs(longLen)) { + int swap=shortLen; + shortLen=longLen; + longLen=swap; + yLonger=true; + } + int decInc; + if (longLen==0) decInc=0; + else decInc = (shortLen << 16) / longLen; + + if (nx1==nx2) { + // special case: vertical line + if (ny1>ny2) { int ty=ny1; ny1=ny2; ny2=ty; } + int offset=ny1*width+nx1; + for(int j=ny1; j<=ny2; j++) { + thin_pointAtIndex(offset,0,strokeColor); + offset+=width; + } + return; + } else if (ny1==ny2) { + // special case: horizontal line + if (nx1>nx2) { int tx=nx1; nx1=nx2; nx2=tx; } + int offset=ny1*width+nx1; + for(int j=nx1; j<=nx2; j++) thin_pointAtIndex(offset++,0,strokeColor); + return; + } else if (yLonger) { + if (longLen>0) { + longLen+=ny1; + for (int j=0x8000+(nx1<<16);ny1<=longLen;++ny1) { + thin_pointAt(j>>16, ny1, 0, strokeColor); + j+=decInc; + } + return; + } + longLen+=ny1; + for (int j=0x8000+(nx1<<16);ny1>=longLen;--ny1) { + thin_pointAt(j>>16, ny1, 0, strokeColor); + j-=decInc; + } + return; + } else if (longLen>0) { + longLen+=nx1; + for (int j=0x8000+(ny1<<16);nx1<=longLen;++nx1) { + thin_pointAt(nx1, j>>16, 0, strokeColor); + j+=decInc; + } + return; + } + longLen+=nx1; + for (int j=0x8000+(ny1<<16);nx1>=longLen;--nx1) { + thin_pointAt(nx1, j>>16, 0, strokeColor); + j-=decInc; + } + } + + private int thin_flat_lineClipCode(float x, float y) { + return ((y < 0 ? 8 : 0) | (y > height1 ? 4 : 0) | + (x < 0 ? 2 : 0) | (x > width1 ? 1 : 0)); + } + + private float thin_flat_lineSlope(float x1, float y1, + float x2, float y2, int border) { + switch (border) { + case 4: { + return (-y1)/(y2-y1); + } + case 3: { + return (height1-y1)/(y2-y1); + } + case 2: { + return (-x1)/(x2-x1); + } + case 1: { + return (width1-x1)/(x2-x1); + } + } + return -1f; + } + + + private boolean flat_line_retribution(float x1, float y1, + float x2, float y2, + float r1, float g1, float b1) { + /* + // assume that if it is/isn't big in one dir, then the + // other doesn't matter, cuz that's a weird case + float lwidth = m00*strokeWeight + m01*strokeWeight; + //float lheight = m10*strokeWeight + m11*strokeWeight; + // lines of stroke thickness 1 can be anywhere from -1.41 to 1.41 + if ((strokeWeight < TWO) && (!hints[SCALE_STROKE_WIDTH])) { + //if (abs(lwidth) < 1.5f) { + //System.out.println("flat line retribution " + r1 + " " + g1 + " " + b1); + int strokeSaved = strokeColor; + strokeColor = float_color(r1, g1, b1); + thin_flat_line((int)x1, (int)y1, (int)x2, (int)y2); + strokeColor = strokeSaved; + return true; + } + */ + return false; + } + + + private void thick_flat_line(float ox1, float oy1, + float r1, float g1, float b1, float a1, + float ox2, float oy2, + float r2, float g2, float b2, float a2) { + spolygon.interpARGB = (r1 != r2) || (g1 != g2) || (b1 != b2) || (a1 != a2); + spolygon.interpZ = false; + + if (!spolygon.interpARGB && + flat_line_retribution(ox1, oy1, ox2, oy2, r1, g1, b1)) { + return; + } + + float dX = ox2-ox1 + EPSILON; + float dY = oy2-oy1 + EPSILON; + float len = sqrt(dX*dX + dY*dY); + + // TODO strokeWidth should be transformed! + float rh = strokeWeight / len; + + float dx0 = rh * dY; + float dy0 = rh * dX; + float dx1 = rh * dY; + float dy1 = rh * dX; + + spolygon.reset(4); + + float svertex[] = spolygon.vertices[0]; + svertex[X] = ox1+dx0; + svertex[Y] = oy1-dy0; + svertex[R] = r1; + svertex[G] = g1; + svertex[B] = b1; + svertex[A] = a1; + + svertex = spolygon.vertices[1]; + svertex[X] = ox1-dx0; + svertex[Y] = oy1+dy0; + svertex[R] = r1; + svertex[G] = g1; + svertex[B] = b1; + svertex[A] = a1; + + svertex = spolygon.vertices[2]; + svertex[X] = ox2-dx1; + svertex[Y] = oy2+dy1; + svertex[R] = r2; + svertex[G] = g2; + svertex[B] = b2; + svertex[A] = a2; + + svertex = spolygon.vertices[3]; + svertex[X] = ox2+dx1; + svertex[Y] = oy2-dy1; + svertex[R] = r2; + svertex[G] = g2; + svertex[B] = b2; + svertex[A] = a2; + + spolygon.render(); + } + + + /* + // OPT version without z coords can save 8 multiplies and some other + private void spatial_line(float x1, float y1, + float r1, float g1, float b1, + float x2, float y2, + float r2, float g2, float b2) { + spatial_line(x1, y1, 0, r1, g1, b1, + x2, y2, 0, r2, g2, b2); + } + + + // the incoming values are transformed, + // and the colors have been calculated + + private void spatial_line(float x1, float y1, float z1, + float r1, float g1, float b1, + float x2, float y2, float z2, + float r2, float g2, float b2) { + spolygon.interpARGB = (r1 != r2) || (g1 != g2) || (b1 != b2); + if (!spolygon.interpARGB && + flat_line_retribution(x1, y1, x2, y2, r1, g1, b1)) { + return; + } + + spolygon.interpZ = true; + + float ox1 = x1; float oy1 = y1; float oz1 = z1; + float ox2 = x2; float oy2 = y2; float oz2 = z2; + + float dX = ox2-ox1 + 0.0001f; + float dY = oy2-oy1 + 0.0001f; + float len = sqrt(dX*dX + dY*dY); + + //float x0 = m00*0 + m01*0 + m03; + + float rh = strokeWeight / len; + + float dx0 = rh * dY; + float dy0 = rh * dX; + float dx1 = rh * dY; + float dy1 = rh * dX; + + spolygon.reset(4); + + float svertex[] = spolygon.vertices[0]; + svertex[X] = ox1+dx0; + svertex[Y] = oy1-dy0; + svertex[Z] = oz1; + svertex[R] = r1; //calcR1; + svertex[G] = g1; //calcG1; + svertex[B] = b1; //calcB1; + + svertex = spolygon.vertices[1]; + svertex[X] = ox1-dx0; + svertex[Y] = oy1+dy0; + svertex[Z] = oz1; + svertex[R] = r1; //calcR1; + svertex[G] = g1; //calcG1; + svertex[B] = b1; //calcB1; + + svertex = spolygon.vertices[2]; + svertex[X] = ox2-dx1; + svertex[Y] = oy2+dy1; + svertex[Z] = oz2; + svertex[R] = r2; //calcR2; + svertex[G] = g2; //calcG2; + svertex[B] = b2; //calcB2; + + svertex = spolygon.vertices[3]; + svertex[X] = ox2+dx1; + svertex[Y] = oy2-dy1; + svertex[Z] = oz2; + svertex[R] = r2; //calcR2; + svertex[G] = g2; //calcG2; + svertex[B] = b2; //calcB2; + + spolygon.render(); + } + */ + + + // max is what to count to + // offset is offset to the 'next' vertex + // increment is how much to increment in the loop + private void draw_lines(float vertices[][], int max, + int offset, int increment, int skip) { + + if (strokeWeight < 2) { + for (int i = 0; i < max; i += increment) { + if ((skip != 0) && (((i+offset) % skip) == 0)) continue; + + float a[] = vertices[i]; + float b[] = vertices[i+offset]; + + if (line == null) line = new PLine(this); + + line.reset(); + line.setIntensities(a[SR], a[SG], a[SB], a[SA], + b[SR], b[SG], b[SB], b[SA]); + line.setVertices(a[X], a[Y], a[Z], + b[X], b[Y], b[Z]); + line.draw(); + } + + } else { // use old line code for thickness > 1 + + if ((strokeWeight < TWO) && !strokeChanged) { + // need to set color at least once? + + // THIS PARTICULAR CASE SHOULD NO LONGER BE REACHABLE + + for (int i = 0; i < max; i += increment) { + if ((skip != 0) && (((i+offset) % skip) == 0)) continue; + thin_flat_line((int) vertices[i][X], + (int) vertices[i][Y], + (int) vertices[i+offset][X], + (int) vertices[i+offset][Y]); + } + } else { + for (int i = 0; i < max; i += increment) { + if ((skip != 0) && (((i+offset) % skip) == 0)) continue; + float v1[] = vertices[i]; + float v2[] = vertices[i+offset]; + thick_flat_line(v1[X], v1[Y], v1[SR], v1[SG], v1[SB], v1[SA], + v2[X], v2[Y], v2[SR], v2[SG], v2[SB], v2[SA]); + } + } + } + } + + + + ////////////////////////////////////////////////////////////// + + // UGLY RENDERING SHIT + + + private void thin_point(int x, int y, float z, int color) { + // necessary? [fry] yes! [toxi] + if (x<0 || x>width1 || y<0 || y>height1) return; + + int index = y*width + x; + if ((color & 0xff000000) == 0xff000000) { // opaque + pixels[index] = color; + + } else { // transparent + // couldn't seem to get this working correctly + + //pixels[index] = _blend(pixels[index], + // color & 0xffffff, (color >> 24) & 0xff); + + // a1 is how much of the orig pixel + int a2 = (color >> 24) & 0xff; + int a1 = a2 ^ 0xff; + + int p2 = strokeColor; + int p1 = pixels[index]; + + int r = (a1 * ((p1 >> 16) & 0xff) + a2 * ((p2 >> 16) & 0xff)) & 0xff00; + int g = (a1 * ((p1 >> 8) & 0xff) + a2 * ((p2 >> 8) & 0xff)) & 0xff00; + int b = (a1 * ( p1 & 0xff) + a2 * ( p2 & 0xff)) >> 8; + + pixels[index] = 0xff000000 | (r << 8) | g | b; + + //pixels[index] = _blend(pixels[index], + // color & 0xffffff, (color >> 24) & 0xff); + /* + pixels[index] = 0xff000000 | + ((((a1 * ((pixels[index] >> 16) & 0xff) + + a2 * ((color >> 16) & 0xff)) & 0xff00) << 24) << 8) | + (((a1 * ((pixels[index] >> 8) & 0xff) + + a2 * ((color >> 8) & 0xff)) & 0xff00) << 16) | + (((a1 * ( pixels[index] & 0xff) + + a2 * ( color & 0xff)) >> 8)); + */ + } + zbuffer[index] = z; + } + + + private void flat_circle(int centerX, int centerY, int radius) { + if (translateNoScale()) { + centerX = (int) screenX(centerX, centerY, 0); + centerY = (int) screenY(centerX, centerY, 0); + } + if (fill) flat_circle_fill(centerX, centerY, radius); + if (stroke) flat_circle_stroke(centerX, centerY, radius); + } + + + /** + * Draw the outline around a flat circle using a bresenham-style + * algorithm. Adapted from drawCircle function in "Computer Graphics + * for Java Programmers" by Leen Ammeraal, p. 110 + * + * This function is included because the quality is so much better, + * and the drawing significantly faster than with adaptive ellipses + * drawn using the sine/cosine tables. + * + * Circle quadrants break down like so: + * | + * \ NNW | NNE / + * \ | / + * WNW \ | / ENE + * ------------------- + * WSW / | \ ESE + * / | \ + * / SSW | SSE \ + * | + * + * @param xc x center + * @param yc y center + * @param r radius + */ + private void flat_circle_stroke(int xC, int yC, int r) { + int x = 0, y = r, u = 1, v = 2 * r - 1, E = 0; + while (x < y) { + thin_point(xC + x, yC + y, 0, strokeColor); // NNE + thin_point(xC + y, yC - x, 0, strokeColor); // ESE + thin_point(xC - x, yC - y, 0, strokeColor); // SSW + thin_point(xC - y, yC + x, 0, strokeColor); // WNW + + x++; E += u; u += 2; + if (v < 2 * E) { + y--; E -= v; v -= 2; + } + if (x > y) break; + + thin_point(xC + y, yC + x, 0, strokeColor); // ENE + thin_point(xC + x, yC - y, 0, strokeColor); // SSE + thin_point(xC - y, yC - x, 0, strokeColor); // WSW + thin_point(xC - x, yC + y, 0, strokeColor); // NNW + } + } + + /** + * Heavily adapted version of the above algorithm that handles + * filling the ellipse. Works by drawing from the center and + * outwards to the points themselves. Has to be done this way + * because the values for the points are changed halfway through + * the function, making it impossible to just store a series of + * left and right edges to be drawn more quickly. + * + * @param xc x center + * @param yc y center + * @param r radius + */ + private void flat_circle_fill(int xc, int yc, int r) { + int x = 0, y = r, u = 1, v = 2 * r - 1, E = 0; + while (x < y) { + for (int xx = xc; xx < xc + x; xx++) { // NNE + thin_point(xx, yc + y, 0, fillColor); + } + for (int xx = xc; xx < xc + y; xx++) { // ESE + thin_point(xx, yc - x, 0, fillColor); + } + for (int xx = xc - x; xx < xc; xx++) { // SSW + thin_point(xx, yc - y, 0, fillColor); + } + for (int xx = xc - y; xx < xc; xx++) { // WNW + thin_point(xx, yc + x, 0, fillColor); + } + + x++; E += u; u += 2; + if (v < 2 * E) { + y--; E -= v; v -= 2; + } + if (x > y) break; + + for (int xx = xc; xx < xc + y; xx++) { // ENE + thin_point(xx, yc + x, 0, fillColor); + } + for (int xx = xc; xx < xc + x; xx++) { // SSE + thin_point(xx, yc - y, 0, fillColor); + } + for (int xx = xc - y; xx < xc; xx++) { // WSW + thin_point(xx, yc - x, 0, fillColor); + } + for (int xx = xc - x; xx < xc; xx++) { // NNW + thin_point(xx, yc + y, 0, fillColor); + } + } + } + + // unfortunately this can't handle fill and stroke simultaneously, + // because the fill will later replace some of the stroke points + + private final void flat_ellipse_symmetry(int centerX, int centerY, + int ellipseX, int ellipseY, + boolean filling) { + if (filling) { + for (int i = centerX - ellipseX + 1; i < centerX + ellipseX; i++) { + thin_point(i, centerY - ellipseY, 0, fillColor); + thin_point(i, centerY + ellipseY, 0, fillColor); + } + } else { + thin_point(centerX - ellipseX, centerY + ellipseY, 0, strokeColor); + thin_point(centerX + ellipseX, centerY + ellipseY, 0, strokeColor); + thin_point(centerX - ellipseX, centerY - ellipseY, 0, strokeColor); + thin_point(centerX + ellipseX, centerY - ellipseY, 0, strokeColor); + } + } + + + /** + * Bresenham-style ellipse drawing function, adapted from a posting to + * comp.graphics.algortihms. + * + * This function is included because the quality is so much better, + * and the drawing significantly faster than with adaptive ellipses + * drawn using the sine/cosine tables. + * + * @param centerX x coordinate of the center + * @param centerY y coordinate of the center + * @param a horizontal radius + * @param b vertical radius + */ + private void flat_ellipse_internal(int centerX, int centerY, + int a, int b, boolean filling) { + int x, y, a2, b2, s, t; + + a2 = a*a; + b2 = b*b; + x = 0; + y = b; + s = a2*(1-2*b) + 2*b2; + t = b2 - 2*a2*(2*b-1); + flat_ellipse_symmetry(centerX, centerY, x, y, filling); + + do { + if (s < 0) { + s += 2*b2*(2*x+3); + t += 4*b2*(x+1); + x++; + } else if (t < 0) { + s += 2*b2*(2*x+3) - 4*a2*(y-1); + t += 4*b2*(x+1) - 2*a2*(2*y-3); + x++; + y--; + } else { + s -= 4*a2*(y-1); + t -= 2*a2*(2*y-3); + y--; + } + flat_ellipse_symmetry(centerX, centerY, x, y, filling); + + } while (y > 0); + } + + + private void flat_ellipse(int centerX, int centerY, int a, int b) { + if (translateNoScale()) { + centerX = (int) screenX(centerX, centerY, 0); + centerY = (int) screenY(centerX, centerY, 0); + } + if (fill) flat_ellipse_internal(centerX, centerY, a, b, true); + if (stroke) flat_ellipse_internal(centerX, centerY, a, b, false); + } + + + /** + * Image drawn in flat "screen space", with no scaling or warping. + * this is so common that a special routine is included for it, + * because the alternative is much slower. + * + * @param image image to be drawn + * @param sx1 x coordinate of upper-lefthand corner in screen space + * @param sy1 y coordinate of upper-lefthand corner in screen space + */ + public void flat_image(PImage image, int sx1, int sy1) { + int ix1 = 0; + int iy1 = 0; + int ix2 = image.width; + int iy2 = image.height; + + if (imageMode == CENTER) { + sx1 -= image.width / 2; + sy1 -= image.height / 2; + } + + int sx2 = sx1 + image.width; + int sy2 = sy1 + image.height; + + // don't draw if completely offscreen + // (without this check, ArrayIndexOutOfBoundsException) + if ((sx1 > width1) || (sx2 < 0) || + (sy1 > height1) || (sy2 < 0)) return; + + if (sx1 < 0) { // off left edge + ix1 -= sx1; + sx1 = 0; + } + if (sy1 < 0) { // off top edge + iy1 -= sy1; + sy1 = 0; + } + if (sx2 > width) { // off right edge + ix2 -= sx2 - width; + sx2 = width; + } + if (sy2 > height) { // off bottom edge + iy2 -= sy2 - height; + sy2 = height; + } + + int source = iy1 * image.width + ix1; + int target = sy1 * width; + + if (image.format == ARGB) { + for (int y = sy1; y < sy2; y++) { + int tx = 0; + + for (int x = sx1; x < sx2; x++) { + pixels[target + x] = + _blend(pixels[target + x], + image.pixels[source + tx], + image.pixels[source + tx++] >>> 24); + } + source += image.width; + target += width; + } + } else if (image.format == ALPHA) { + for (int y = sy1; y < sy2; y++) { + int tx = 0; + + for (int x = sx1; x < sx2; x++) { + pixels[target + x] = + _blend(pixels[target + x], + fillColor, + image.pixels[source + tx++]); + } + source += image.width; + target += width; + } + + } else if (image.format == RGB) { + target += sx1; + int tw = sx2 - sx1; + for (int y = sy1; y < sy2; y++) { + System.arraycopy(image.pixels, source, pixels, target, tw); + // should set z coordinate in here + // or maybe not, since dims=0, meaning no relevant z + source += image.width; + target += width; + } + } + } + + + + ////////////////////////////////////////////////////////////// + + // INTERNAL SCHIZZLE + + + private boolean untransformed() { + return ((m00 == 1) && (m01 == 0) && (m02 == 0) && + (m10 == 0) && (m11 == 1) && (m12 == 0)); + } + + private boolean translateNoScale() { + return ((m00 == 1) && (m01 == 0) && (m10 == 0) && (m11 == 1)); + } + + + + // doesn't really do lighting per se... + private void calc_lighting(float r, float g, float b, + float ix, float iy, float iz, + float nx, float ny, float nz, + float target[], int toffset) { + target[toffset + 0] = r; + target[toffset + 1] = g; + target[toffset + 2] = b; + } + + + static private final int float_color(float r, float g, float b) { + return (0xff000000 | + ((int) (255.0f * r)) << 16 | + ((int) (255.0f * g)) << 8 | + ((int) (255.0f * b))); + } + + public final static int _blend(int p1, int p2, int a2) { + // scale alpha by alpha of incoming pixel + a2 = (a2 * (p2 >>> 24)) >> 8; + + int a1 = a2 ^ 0xff; + int r = (a1 * ((p1 >> 16) & 0xff) + a2 * ((p2 >> 16) & 0xff)) & 0xff00; + int g = (a1 * ((p1 >> 8) & 0xff) + a2 * ((p2 >> 8) & 0xff)) & 0xff00; + int b = (a1 * ( p1 & 0xff) + a2 * ( p2 & 0xff)) >> 8; + + return 0xff000000 | (r << 8) | g | b; + } +} + + + + + + + + + + + + + diff --git a/core/src/processing/core/PGraphics3D.java b/core/src/processing/core/PGraphics3D.java index 9434d2589..bfce112d1 100644 --- a/core/src/processing/core/PGraphics3D.java +++ b/core/src/processing/core/PGraphics3D.java @@ -356,7 +356,7 @@ public class PGraphics3D extends PGraphics { public void endDraw() { // no need to z order and render // shapes were already rendered in endShape(); - // (but can't return, since needs to update memimgsrc + // (but can't return, since needs to update memimgsrc) if (hints[ENABLE_DEPTH_SORT]) { flush(); } @@ -488,21 +488,6 @@ public class PGraphics3D extends PGraphics { } - /** - * Set texture mode to either to use coordinates based on the IMAGE - * (more intuitive for new users) or NORMALIZED (better for advanced chaps) - */ - public void textureMode(int mode) { - this.textureMode = mode; - } - - - /** - * Set texture image for current shape - * needs to be called between @see beginShape and @see endShape - * - * @param image reference to a PImage object - */ public void texture(PImage image) { textureImage = image; @@ -527,7 +512,7 @@ public class PGraphics3D extends PGraphics { public void vertex(float x, float y, float u, float v) { - texture_vertex(u, v); + textureVertex(u, v); setup_vertex(x, y, 0); } @@ -539,7 +524,7 @@ public class PGraphics3D extends PGraphics { public void vertex(float x, float y, float z, float u, float v) { - texture_vertex(u, v); + textureVertex(u, v); setup_vertex(x, y, z); } @@ -610,107 +595,6 @@ public class PGraphics3D extends PGraphics { } - /** - * set UV coords for the next vertex in the current shape. - * this is ugly as its own fxn, and will almost always be - * coincident with a call to vertex, so it's being moved - * to be an optional param of and overloaded vertex() - * - * @param u U coordinate (X coord in image 0<=X<=image width) - * @param v V coordinate (Y coord in image 0<=Y<=image height) - */ - protected void texture_vertex(float u, float v) { - if (textureImage == null) { - throw new RuntimeException("need to set an image with texture() " + - "before using u and v coordinates"); - } - if (textureMode == IMAGE) { - u /= (float) textureImage.width; - v /= (float) textureImage.height; - } - - textureU = u; - textureV = v; - - if (textureU < 0) textureU = 0; - else if (textureU > ONE) textureU = ONE; - - if (textureV < 0) textureV = 0; - else if (textureV > ONE) textureV = ONE; - } - - - protected void spline_vertex(float x, float y, float z, boolean bezier) { - // allocate space for the spline vertices - // to improve processing applet load times, don't allocate until actual use - if (splineVertices == null) { - splineVertices = new float[DEFAULT_SPLINE_VERTICES][VERTEX_FIELD_COUNT]; - } - - // if more than 128 points, shift everything back to the beginning - if (splineVertexCount == DEFAULT_SPLINE_VERTICES) { - System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-3], 0, - splineVertices[0], 0, VERTEX_FIELD_COUNT); - System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-2], 0, - splineVertices[1], 0, VERTEX_FIELD_COUNT); - System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-1], 0, - splineVertices[2], 0, VERTEX_FIELD_COUNT); - splineVertexCount = 3; - } - - float vertex[] = splineVertices[splineVertexCount]; - - vertex[MX] = x; - vertex[MY] = y; - vertex[MZ] = z; - - if (fill) { - vertex[R] = fillR; - vertex[G] = fillG; - vertex[B] = fillB; - vertex[A] = fillA; - } - - if (stroke) { - vertex[SR] = strokeR; - vertex[SG] = strokeG; - vertex[SB] = strokeB; - vertex[SA] = strokeA; - vertex[SW] = strokeWeight; - } - - if (textureImage != null) { - vertex[U] = textureU; - vertex[V] = textureV; - } - - vertex[NX] = normalX; - vertex[NY] = normalY; - vertex[NZ] = normalZ; - - splineVertexCount++; - - // draw a segment if there are enough points - if (splineVertexCount > 3) { - if (bezier) { - if ((splineVertexCount % 4) == 0) { - if (!bezierInited) bezier_init(); - spline3_segment(splineVertexCount-4, - splineVertexCount-4, - bezier_draw, - bezierDetail); - } - } else { // catmull-rom curve (!bezier) - if (!curve_inited) curve_init(); - spline3_segment(splineVertexCount-4, - splineVertexCount-3, - curve_draw, - curveDetail); - } - } - } - - /** * See notes with the bezier() function. */ @@ -729,35 +613,20 @@ public class PGraphics3D extends PGraphics { float x4, float y4, float z4) { if (splineVertexCount > 0) { float vertex[] = splineVertices[splineVertexCount-1]; - spline_vertex(vertex[MX], vertex[MY], vertex[MZ], true); + splineVertex(vertex[MX], vertex[MY], vertex[MZ], true); } else if (vertexCount > 0) { // make sure there's at least a call to vertex() float vertex[] = vertices[vertexCount-1]; - spline_vertex(vertex[MX], vertex[MY], vertex[MZ], true); + splineVertex(vertex[MX], vertex[MY], vertex[MZ], true); } else { throw new RuntimeException("A call to vertex() must be used " + "before bezierVertex()"); } - spline_vertex(x2, y2, z2, true); - spline_vertex(x3, y3, z3, true); - spline_vertex(x4, y4, z4, true); - } - - - /** - * See notes with the curve() function. - */ - public void curveVertex(float x, float y) { - spline_vertex(x, y, 0, false); - } - - /** - * See notes with the curve() function. - */ - public void curveVertex(float x, float y, float z) { - spline_vertex(x, y, z, false); + splineVertex(x2, y2, z2, true); + splineVertex(x3, y3, z3, true); + splineVertex(x4, y4, z4, true); } @@ -3994,10 +3863,6 @@ public class PGraphics3D extends PGraphics { } */ - private final float sqrt(float a) { - return (float)Math.sqrt(a); - } - private final float pow(float a, float b) { return (float)Math.pow(a, b); } diff --git a/core/src/processing/core/PGraphicsJava2D.java b/core/src/processing/core/PGraphicsJava2D.java index 1bd5fd3b8..5690639a2 100644 --- a/core/src/processing/core/PGraphicsJava2D.java +++ b/core/src/processing/core/PGraphicsJava2D.java @@ -130,12 +130,7 @@ public class PGraphicsJava2D extends PGraphics { public void endDraw() { - // moving this back here (post-68) because of macosx thread problem - //mis.newPixels(pixels, cm, 0, width); - - // need to mark pixels as needing an update, without calling - // its own endPixels, since that's crazy slow - //endPixels(); + endPixels(); // mark pixels as changed } @@ -145,6 +140,31 @@ public class PGraphicsJava2D extends PGraphics { // SHAPES + public void beginShape(int kind) { + //super.beginShape(kind); + shape = kind; + vertexCount = 0; + splineVertexCount = 0; + + // set gpath to null, because when mixing curves and straight + // lines, vertexCount will be set back to zero, so vertexCount == 1 + // is no longer a good indicator of whether the shape is new. + // this way, just check to see if gpath is null, and if it isn't + // then just use it to continue the shape. + gpath = null; + } + + + public void textureMode(int mode) { + unavailableError("textureMode(mode)"); + } + + + public void texture(PImage image) { + unavailableError("texture(image)"); + } + + public void vertex(float x, float y) { splineVertexCount = 0; //float vertex[]; @@ -260,6 +280,21 @@ public class PGraphicsJava2D extends PGraphics { break; } } + + + public void vertex(float x, float y, float u, float v) { + unavailableError("vertex(x, y, u, v"); + } + + + public void vertex(float x, float y, float z) { + depthErrorXYZ("vertex"); + } + + + public void vertex(float x, float y, float z, float u, float v) { + depthErrorXYZ("vertex"); + } public void bezierVertex(float x1, float y1, @@ -348,18 +383,6 @@ public class PGraphicsJava2D extends PGraphics { } - public void beginShape(int kind) { - super.beginShape(kind); - - // set gpath to null, because when mixing curves and straight - // lines, vertexCount will be set back to zero, so vertexCount == 1 - // is no longer a good indicator of whether the shape is new. - // this way, just check to see if gpath is null, and if it isn't - // then just use it to continue the shape. - gpath = null; - } - - public void endShape() { if (gpath != null) { // make sure something has been drawn switch (shape) { diff --git a/core/src/processing/core/PLine.java b/core/src/processing/core/PLine.java index 3d4680198..983cfb42e 100644 --- a/core/src/processing/core/PLine.java +++ b/core/src/processing/core/PLine.java @@ -98,10 +98,10 @@ public class PLine implements PConstants private float db; private float da; - private PGraphics3D parent; + private PGraphics parent; - public PLine(PGraphics3D g) { + public PLine(PGraphics g) { INTERPOLATE_Z = false; x_array = new float[2]; diff --git a/core/todo.txt b/core/todo.txt index 21f4e563f..69ebc7c87 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -38,6 +38,12 @@ o right now the camera doesn't get set up unless you call depth() o box and sphere are broken in gl o what should the update image function be called? + +things before 1.0 +_ know internal vs. external lines, so that anti-aliasing can be shut off for internal + +_ is the texture[] array in PGraphics3D causing the problems with memory? + _ for a PGraphics2D, should its image cache object be the memoryimagesource? _ only call defaults() when it's part of a PApplet canvas