Visualizzazione dei risultati da 1 a 3 su 3
  1. #1

    modifica algoritmo acqua (2d side view)

    Ho un algoritmo per generare onde su una riga orizzontale che rappresenta un piano d'acqua.
    L'effetto è ben noto e qui ce n'è un esempio: http://www.ultrashock.com/tutorials/flash8/wave.php

    Il cuore dell'algoritmo che uso è questo:
    codice:
    static inline float
    diffuse(float diff, float damp, float prev, float curr, float next){
    	return (curr*diff + ((prev + next)*0.5f)*(1.0f - diff))*damp;
    }
    La funzione viene applicata a tutti i punti che formano la linea in modo che il punto correntemente analizzato venga valorizzato in base al precedente e al successivo.

    Ho bisogno di cambiare l'algoritmo in modo che le onde generate scorrino verso sinistra o verso destra come se si stesse guardando un flusso d'acqua in movimento. Se generiamo un'onda in un fiume che scorre veloce buttando un sasso davanti a noi questa si propagherà intorno al punto d'impatto del sasso ma, nel suo insieme, si sposterà velocemente in direzione del corso del fiume.

    Io ho bisogno di simulare questo spostamento delle onde potendone anche controllare la velocità, che dovrà aderire alla velocità dell'acqua in quel particolare momento.

    Ho provato a spostare i valori dei punti dell'array in modo che la loro posizione all'interno di esso segua la direzione delle onde, funziona ma non mi da la possibilità di regolarne la velocità vsto che questa è determinata solo dalla posizione che il vertice dell'onda ha, via via, nell'array.

    Cerco un qualunque consiglio! Grazie!
    Satori, l'accendiamo?

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,304

    Moderazione

    Linguaggio usato?
    Letto il Regolamento interno riguardo al fatto che qui non si sviluppa software?

    Posta il codice dell'algoritmo che hai sviluppato con le modifiche che hai provato ad apportare e i problemi che ne sono nati...

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Ok grazie, il linguaggio è [obj-c] e posto un po' di codice. Questa è la versione originale dell'autore della classe, la mia differisce solo nell'esporre come proprietà le altezze delle onde in modo da farle interagire con il motore fisico (box2d) e nel rendeering di una texture al posto di un poligono trasparente. Anche la mia versione funziona perfettamente, quindi posto l'originale perché è più pulita e comprensibile:
    codice:
    //
    //  Waves1DNode.h
    //  Waves1D
    //
    //  Created by Scott Lembcke on 12/10/11.
    //  Copyright Howling Moon Software 2011. All rights reserved.
    //
    
    
    #import "cocos2d.h"
    
    @interface Waves1DNode : CCNode {
    	CGRect _bounds;
    	
    	float _diffusion;
    	float _damping;
    	
    	int _count;
    	// Heightfields that the simulation vertlet integrates between.
    	float *_h1, *_h2;
    }
    
    // 'bounds' are the rectangle to draw for the water. The top of the bounds is the rest height for the water, it wil wave above and below it.
    // 'count' is the number of slices to simulate. One per 10-20 pixels is usually sufficient.
    // 'damping' is how fast the water settles back to rest. 1.0 is never (bad), 0.0 is immediately (also bad). 0.99 is a decent damping amount.
    // 'diffusion' is how fast the waves spread to neighbors. Values outside of 0.6 - 0.9 can become unstable.
    -(id)initWithBounds:(CGRect)bounds count:(int)count damping:(float)damping diffusion:(float)diffusion;
    
    -(void)makeSplashAt:(float)x;
    
    @end
    codice:
    //
    //  Waves1DNode.m
    //  Waves1D
    //
    //  Created by Scott Lembcke on 12/10/11.
    //  Copyright Howling Moon Software 2011. All rights reserved.
    //
    
    
    #import "Waves1DNode.h"
    
    @implementation Waves1DNode
    
    -(id)initWithBounds:(CGRect)bounds count:(int)count damping:(float)damping diffusion:(float)diffusion;
    {
    	if((self = [super init])){
    		_bounds = bounds;
    		_count = count;
    		_damping = damping;
    		_diffusion = diffusion;
    		
    		_h1 = calloc(_count, sizeof(float));
    		_h2 = calloc(_count, sizeof(float));
    	}
    	
    	return self;
    }
    
    - (void) dealloc
    {
    	free(_h1);
    	free(_h2);
    	
    	[super dealloc];
    }
    
    
    -(void)vertlet {
    	for(int i=0; i<_count; i++) _h1[i] = 2.0*_h2[i] - _h1[i];
    	
    	float *temp = _h2;
    	_h2 = _h1;
    	_h1 = temp;
    }
    
    static inline float
    diffuse(float diff, float damp, float prev, float curr, float next){
    	return (curr*diff + ((prev + next)*0.5f)*(1.0f - diff))*damp;
    }
    
    -(void)diffuse {
    	float prev = _h2[0];
    	float curr = _h2[0];
    	float next = _h2[1];
    
    	_h2[0] = diffuse(_diffusion, _damping, prev, curr, next);
    
    	for(int i=1; i<(_count - 1); ++i){
    		prev = curr;
    		curr = next;
    		next = _h2[i + 1];
    
    		_h2[i] = diffuse(_diffusion, _damping, prev, curr, next);
    	}
    	
    	prev = curr;
    	curr = next;
    	_h2[_count - 1] = diffuse(_diffusion, _damping, prev, curr, next);
    }
    
    -(float)dx{return _bounds.size.width/(GLfloat)(_count - 1);}
    
    - (void)draw {
    	// It would be better to run these on a fixed timestep.
    	// As an GFX only effect it doesn't really matter though.
    	[self vertlet];
    	[self diffuse];
    	
    	GLfloat dx = [self dx];
    	GLfloat top = _bounds.size.height;
    	
    	// Build a vertex array and render it.
    	struct Vertex{GLfloat x,y;};
    	struct Vertex verts[_count*2];
    	for(int i=0; i<_count; i++){
    		GLfloat x = i*dx;
    		verts[2*i + 0] = (struct Vertex){x, 0};
    		verts[2*i + 1] = (struct Vertex){x, top + _h2[i]};
    	}
    	
    	glDisableClientState(GL_COLOR_ARRAY);
    	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    	
    	glDisable(GL_TEXTURE_2D);
    	
    	GLfloat r = 105.0f/255.0f;
    	GLfloat g = 193.0f/255.0f;
    	GLfloat b = 212.0f/255.0f;
    	GLfloat a = 0.3f;
    	glColor4f(r*a, g*a, b*a, a);
    	
    	glVertexPointer(2, GL_FLOAT, 0, verts);
    	
    	glPushMatrix(); {
    		glScalef(CC_CONTENT_SCALE_FACTOR(), CC_CONTENT_SCALE_FACTOR(), 1.0);
    		glTranslatef(_bounds.origin.x, _bounds.origin.y, 0.0);
    		
    		glDrawArrays(GL_TRIANGLE_STRIP, 0, _count*2);
    	} glPopMatrix();
    	
    	glEnableClientState(GL_COLOR_ARRAY);
    	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    	glEnable(GL_TEXTURE_2D);
    	
    	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
    }
    
    -(void)makeSplashAt:(float)x;
    {
    	// Changing the values of heightfield in h2 will make the waves move.
    	// Here I only change one column, but you get the idea.
    	// Change a bunch of the heights using a nice smoothing function for a better effect.
    	
    	int index = MAX(0, MIN((int)(x/[self dx]), _count - 1));
    	_h2[index] += CCRANDOM_MINUS1_1()*20.0;
    }
    
    @end
    
    /**
    -Ideas to make it better:
     * Add clamping to avoid giant, crappy looking waves.
     * Make it run on a fixed timestep.
     * Add texturing to give the surface a nice (and anti-aliased) look.
     * Fancier makeSplash method that does more than a single point.
    */
    Per realizzare l'acqua che scorre(scrolla in 2d sullo schermo) ho usato il solito trucchetto dei due elementi che si inseguono rimpiazzandosi come nell'immagine qua sotto:


    Le mie 2 acque si inseguono sostituendosi l'una all'altra e passandosi le altezze del primo e dell'ultimo vertice al fine di creare una continuità fra le onde la dove le acque si uniscono :Mosè:

    Non sono soddisfatto perché si nota sempre una piccola cresta aggiuntiva sulle onde che passano in prossimità del punto di giunzione delle acque e oltretutto trovo dispendioso avere due acque al posto di una che resta fissa sullo schermo e che accetta come parametro la velocità di scorrimento.

    Quindi ho provato a modificare la classe in modo che gli elementi dell'array delle altezze scalassero verso l'inizio o la fine dello stesso a seconda della direzione di scorrimento dell'acqua. Funziona nel senso che fa scorrere le onde nella direzione giusta ma è ovvio che non ne posso controllare la velocità perché questa è data solo dallo scalare di posizione degli elementi del vettore e che quindi non è possibile fare interpolazioni perché non ci sono posizioni intermedie(il piano d'acqua è costituito da un numero di punti limitato così come l'array che li contiene)

    A me servirebbe di riuscire a interpolare i valori della formula in modo che questi tendano a propagarsi in direzione dell'inizio o della fine dell'array in base a una velocità variabile...

    Edit: in realtà non necessito di consigli scritti in objective-c, va benissimo pseudo codice o anche solo una mezza idea! ;)
    Satori, l'accendiamo?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.