{"id":45,"date":"2011-05-07T16:36:58","date_gmt":"2011-05-07T20:36:58","guid":{"rendered":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/?p=45"},"modified":"2011-10-02T00:03:23","modified_gmt":"2011-10-02T04:03:23","slug":"i-gest-ure-gonna-like-this","status":"publish","type":"post","link":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/2011\/05\/07\/i-gest-ure-gonna-like-this\/","title":{"rendered":"I Gest-Ure Gonna Like This!"},"content":{"rendered":"<p>Back to implementing gestures.\u00a0 I&#8217;ve set up a general infrastructure to handle any sort of gestures the user might want to add in.\u00a0 You create a gesture processor and then add some listeners to the processor to find out when certain events occur.\u00a0 The important events are are for single occurrences, and ones for continuous events: start, continue, end, and cancel.\u00a0 This allows you to handle single tap events versus a continuous drag.\u00a0 But I want to extend things beyond just gestures.\u00a0 I&#8217;m going to want to have something that picks into the scenegraph, as well as handling raw touch events so I can signal to a button that it should highlight on the initial touch down for example.\u00a0 Well the cool thing about this system is that it simplifies the general code for trying to figure out what system should handle touch points.\u00a0 Everything I described can be considered a gesture.\u00a0 A picker gesture looks at any new touch downs and will pick into the scene to find relevant objects at that point.\u00a0 Then the picker can send a single occurrence event to listeners to tell them which object it found.\u00a0 Another gesture can just listen for raw touch events from the touch manager and then signal any listeners about what&#8217;s been heard.<br \/>\n<!--more--><\/p>\n<p>An important you may be asking is what order do you check the gestures in.\u00a0 You can give each gesture a priority, where higher priorities can accept the touch input first.\u00a0 So you can basically reorder your gestures in any order you&#8217;d like.\u00a0 This is helpful for quickly and easily saying that tap gestures should happen before drag gestures.\u00a0 And since we&#8217;re talking about full gesture units, we can easily add\/remove them to the touch manager on a per context basis like when touching certain objects or in different states. No having to fiddle with the mix of\u00a0 touch handling code and actions to get what you want.<\/p>\n<p>Well that&#8217;s all structure, so now we get into algorithms.\u00a0 Let&#8217;s just say I don&#8217;t like gesture algorithms!\u00a0 What a pain to try and keep track of all the possibilities when you&#8217;re dealing with 11 possible touch points at the same time.\u00a0 It would probably be a lot simpler if I wasn&#8217;t trying to be so minimalistic with things, but from experience I can tell you that your input system has to be quick and efficient in every way possible.\u00a0 The user cannot feel any sort of lag when they&#8217;re trying to do something or else it distracts from what they&#8217;re experience.\u00a0 Immediate gratification is something we&#8217;ve all gotten used to these days.\u00a0 So my goal is to have touches handled and gestures recognized in as few ops as possible.\u00a0 That means a lot of saving of state, and absolutely no creating big objects on the fly (either new\/delete or trying to pass non reference objects through function calls).<\/p>\n<p>I&#8217;ve just done the simple drag and tap gestures and pinch rotates so far.\u00a0 I&#8217;m pretty happy with things and everything works well and quick.\u00a0 Nothing really special here though, just a lot of state handling and computation of distances and angles.\u00a0 However, while going into the math for rotations I recalled an old idea I had years ago.\u00a0 I wanted to talk about the angles of rotation and related values, but without the trigonometry.\u00a0 With a little google-fu I found an old article I had remembered when I went searching for the same thing before.\u00a0 Enter Rational Trigonometry!\u00a0 *cue ominous sounds*<\/p>\n<p>The whole idea behind Rational Trigonometry is that they throw away the notion of angles in place of spread, and distance for quadrance.\u00a0 Actually quadrance is just the distance squared and spread is sin(theta) squared, so there&#8217;s really no magic here in the math.\u00a0 But by just talking in these measurements some niceties start to appear.\u00a0 Your answers are now exact rational values.\u00a0 And the big part for me is that you can usually minimize the use of sqrt and sinf\/cosf calls, which can be costly sometimes depending on your implementation.\u00a0 If you still want the distance then you still have to take the sqrt of the quadrance, there&#8217;s no difference here.\u00a0 I believe the point is to change what you&#8217;re asking for though.\u00a0 Ask for minimum quandrances and minimum spreads rather than distance and angles when you can.\u00a0 Then you can use these &#8216;optimal&#8217; versions to do what&#8217;s needed.<\/p>\n<p>Some problem spaces will still require distances and angles or signed values that can be lost by working in higher dimension polynomials here.\u00a0 So you can&#8217;t always get the benefits of just dealing with the intermediaries here.\u00a0 You have to be aware of what inputs and outputs you&#8217;ll need to the system.\u00a0 Sometimes some tools just aren&#8217;t meant for the job.\u00a0 Also, in general you need to careful if you&#8217;re planning on changing the way others may interact with these calls.\u00a0 Remember most people (myself included) know how to envision sin\/cos geometrically and what their ranges are etc., but what exactly is the geometric interpretation of the spread (sin(theta)^2).\u00a0 I don&#8217;t think that concept comes quite as easily as just an angle.\u00a0 However, I have been taught regular trig all my life, and I&#8217;ve only really looked into this rational trig stuff and considering these relationships in different ways for a couple days now.\u00a0 It&#8217;s no different than a little bit of algebra really, but I see its merits in certain problems and I think it can be quite useful.\u00a0 It at least made my rotation code look much more elegant and run a little bit faster.<\/p>\n<p>If you&#8217;d like to learn more about it then please check out the massive series of videos that the &#8216;creator&#8217; has posted on the subject, starting with <a title=\"Why Trig is Hard\" href=\"http:\/\/www.youtube.com\/user\/njwildberger#p\/u\/6\/ZYWHfvij94U\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/www.youtube.com']);\" target=\"_blank\"><em>Why Trig is Hard<\/em><\/a>.<\/p>\n<p>Unfortunately school starts up again in a couple of days so it&#8217;s back to the books instead of the code.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Back to implementing gestures.\u00a0 I&#8217;ve set up a general infrastructure to handle any sort of gestures the user might want to add in.\u00a0 You create a gesture processor and then add some listeners to the processor to find out when certain events occur.\u00a0 The important events are are for single occurrences, and ones for continuous [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-45","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/posts\/45","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/comments?post=45"}],"version-history":[{"count":4,"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/posts\/45\/revisions"}],"predecessor-version":[{"id":135,"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/posts\/45\/revisions\/135"}],"wp:attachment":[{"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/media?parent=45"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/categories?post=45"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/GetOffMyLawnEntertainment.com\/blog\/wp-json\/wp\/v2\/tags?post=45"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}