Colisões de objetos pequenos e de alta velocidade: evitando o encapsulamento


13

EDIT / UPDATE: Minha maior pergunta agora é se a equação "t = ..." da etapa 3 é uma boa idéia ou se há uma maneira melhor de fazê-lo. A maioria das outras questões foi parcial ou totalmente abordada, mas nenhum comentário ou resposta foi realmente abordado. Novamente, provavelmente é necessária uma solução analítica, as velocidades e as distâncias são muito grandes e os objetos são muito pequenos para qualquer solução iterativa / recursiva (algumas são sugeridas abaixo nos comentários) que eu possa pensar (embora haja uma solução iterativa / recursiva especial que lidará bem com esses tipos de situações, então eu definitivamente estou aberto a isso). Muito obrigado por sua ajuda até agora, todos vocês são incríveis e eu realmente aprecio seus pensamentos e ajuda!

Estou tentando detectar colisões entre objetos pequenos e de alta velocidade. É uma situação em que o tunelamento pode ocorrer com muita facilidade, mesmo em velocidades relativamente baixas.

A projeção de raios não funcionará, pois isso está detectando uma colisão entre dois objetos de alta velocidade, não entre um objeto e uma parede estacionária. (A menos que eu esteja entendendo mal o casting de raios?) O desempenho é MUITO considerado; se possível, quero evitar um grande impacto no desempenho. Eu já tenho um quadtree funcional e muito eficaz ( http://en.wikipedia.org/wiki/Quadtree ) implementado, portanto, devo modificá-lo e usá-lo conforme descrito abaixo.

Editar: Reduzir o intervalo de tempo não funcionará. As velocidades são muito altas para esta solução, o que significa que os resultados do desempenho seriam muito grandes, enquanto ainda falta a grande maioria das colisões de túneis . (Por exemplo, eu posso ter um objeto com um tamanho de cerca de 1 unidade a uma velocidade medida em milhões de unidades por intervalo de tempo ...)

SOLUÇÃO PROPOSTA:

Passo 1:

Crie uma caixa em torno do movimento de cada objeto e alimente essas caixas no quadtree para gerar uma lista inicial de possíveis colisões. Veja a imagem a seguir (esta imagem mostra um objeto circular movendo-se de uma posição para outra, e o movimento gerando um retângulo, que será alimentado no quadtree):Retângulo gerado pelo movimento

Etapa 2: (talvez você queira pular esta etapa?)

Percorra a lista de possíveis colisões geradas pelo quadtree. Veja se os retângulos se cruzam em cada colisão possível. Nesse caso, continue na etapa 3.

EDIT: Abaixo, Sean Middleditch sugeriu o uso de volumes varridos / a interseção de cápsulas (se os objetos forem círculos). Isso deixa três opções: 1) pule completamente a etapa 2. 2) Faça o passo 2 do meu jeito. 3) Faça do jeito de Sean. O jeito de Sean será mais computacionalmente caro do que a minha ideia de caixa, mas eliminará mais falsos positivos do que o meu, impedindo-os de chegar à etapa final.

Alguém pode falar por experiência própria sobre qual dessas três opções é a melhor? (Pretendo usar esse mecanismo de física para outras coisas, por isso estou procurando a solução "geralmente melhor" que funcione mais rápido na maior variedade de situações, não apenas um caso de teste específico no qual eu possa medir facilmente qual solução é o mais rápido).

Etapa 3:

Use a equação t = abaixo, se o discriminante (ou seja, a parte sob a raiz quadrada) for negativo ou 0, sem colisão, se positivo, use o valor t como o tempo de colisão (após o qual é fácil ajustar as posições de acordo. ..se os dois objetos continuarem a existir após a colisão). Equação:

Qual é o valor de x na equação x2 + x + 2 = 0 - Brainly.com.brMatemática Qual é a raiz quadrada de 2 (2) = (2) = (2) = (1) r ss ^ 2)) - a w + a xb y + b z + c wc x + d yd z) / (w ^ 2-2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2 ) .

Onde (1 e 2 são usados ​​para denotar objetos 1 e 2):

t é um valor de tempo negativo entre 0 e -1, onde 0 é o quadro atual e -1 é o quadro anterior;

a = x posição 1;

b = posição y 1;

c = x posição 2;

d = posição y 2;

w = x velocidade 1;

x = x velocidade 2;

y = y velocidade 1;

z = velocidade y 2;

r = raio 1;

s = raio 2;

Derivação: (^ 2 significa quadrado)

Pegue equações paramétricas (por exemplo, newxpos1 = a + t w) para os movimentos dos objetos e conecte-os à fórmula da distância (ao quadrado dos dois lados): fórmula da distância ao quadrado = (a + t w - (c + t x)) ^ 2 + (b + t y - (d + t * z)) ^ 2. Lembre-se, t será negativo. Para encontrar o tempo de colisão para dois objetos circulares, definimos o lado esquerdo igual a (r + s) ^ 2. Resolvendo para t usando a equação quadrática (e uma grande quantidade de álgebra muito tediosa), obtemos a equação "t = ..." acima.

Minhas perguntas:

1) Essa é uma boa maneira de fazer isso? Será que vai funcionar? Vou encontrar problemas imprevistos? (Eu sei que terei problemas quando mais de 2 objetos por vez colidirem, mas não me importo, pois o único caso em que realmente me oponho é quando eles têm velocidades relativas baixas (se as velocidades relativas forem altas então a solução "pateta" que o algoritmo fornece será "boa o suficiente" e será impossível para um ser humano ver o erro) e, se mais de 2 colidirem com velocidades relativas baixas no mesmo intervalo de tempo, a maioria das soluções será de qualquer maneira, já que não pretendo ter um monte de colisões inelásticas)

2) Meu desempenho sofrerá muito? Acho que não, mas se houver, existe uma maneira melhor de fazê-lo?

3) Devo pular o passo 2 e ir direto do passo 1 ao 3? Obviamente, a etapa 2 não é vital, mas pode ajudar no desempenho (OU pode custar mais tempo de CPU do que economiza).

Todos os outros comentários, sugestões ou críticas são bem-vindos. Obrigado pela ajuda!


1
Christer Ericson tem algumas informações sobre testes de esferas / esferas em seu livro laranja. Existem algumas maneiras de resolver o problema, mas imagino que você goste mais do intervalo pela metade. É bom tentar derivar essas coisas por conta própria, mas você realmente deve simplesmente olhar o livro laranja e comparar para obter uma rotina de detecção realmente boa e aprender mais.
RandyGaul 18/09/2013

Parece que você já tem um plano. Experimente e veja como funciona?
precisa saber é o seguinte

Eu acho que a maneira "usual" é ter um pequeno intervalo máximo no seu tempo delta. Portanto, se você tiver 1000ms decorridos, simule 10x 100ms (ou 100x 10ms ou 33x 30ms ou algo semelhante).
ashes999

@RandyGaul Examinei o algoritmo descrito na página 215-218, especialmente na página 218 (visualização do Google). É bastante elegante, embora ainda não tenha pensado em todas as suas implicações, pontos fortes e fracos. Será muito mais rápido que o meu? Em caso afirmativo, qual parte do meu algoritmo é lenta em comparação com a recursão de Ericson? A equação na etapa 3 será muito lenta? A recursão me faz hesitar, pois alguns objetos podem estar se movendo MUITO rápido e, portanto, uma grande quantidade de recursão pode ser necessária em alguns casos. (Também, ai, US $ 70 para que o livro ...)
MindSeeker

1
@MindSeeker Não tenho tempo para examinar sua derivação, mas tenho certeza de que os algoritmos do livro de Ericson, qualquer um deles, funcionarão muito bem e provavelmente serão mais rápidos e mais robustos que suas coisas. Você pode encontrar versões em PDF on-line gratuitamente, se quiser demonstrar as outras páginas. Além disso, se você estiver fazendo a detecção de colisões com frequência, o livro laranja é um item básico.
precisa saber é o seguinte

Respostas:


9

Você criou essencialmente uma versão um pouco entusiasmada dos volumes varridos .

Pegue as duas posições do objeto. "Varrer" o objeto do início ao fim. Para uma esfera, isso criaria uma cápsula. Para uma caixa, isso criaria um hexágono (ou uma caixa mais longa é o movimento ao longo de um único eixo). Para polígonos convexos gerais, isso criaria um polígono convexo diferente.

Agora você pode fazer testes de interseção (incluindo consultas em quadtree) usando esse volume varrido. Você pode calcular quando a colisão ocorreu, avançar a simulação do tempo inicial para o tempo da colisão e repetir.

Outra opção, um pouco mais simples, é fazer o que @ ashes999 declarou e simplesmente usar um intervalo de tempo menor ou velocidades menores. Existe uma velocidade máxima ideal derivada do intervalo em que nenhum objeto pode se mover além do seu lado mais estreito em uma única interação física. Para objetos particularmente pequenos ou particularmente rápidos, talvez você não consiga encontrar um intervalo razoavelmente pequeno com bom desempenho.

Consulte Detecção de colisão em tempo real para obter um dos melhores livros introdutórios / intermediários sobre o tópico de detecção de colisões.


Obrigado pela contribuição impressionante! Quebrando sua resposta para que eu possa fazer perguntas sobre ela: "" Varra "o objeto do início ao fim". Até agora estou rastreando; definitivamente uma melhoria em relação ao meu método de caixa. Vou alimentar essas formas por quadtree e depois verificar se há colisões mais exatas. "Você pode calcular quando a colisão ocorreu." Haha é mais fácil falar do que fazer :) Você está recomendando que eu fique com a minha equação do passo 3 para o passo? Ou há um jeito melhor? Esta é a parte realmente crítica.
MindSeeker 18/09/2013

[continuação] "Outra opção ..." Pensei nessa opção, mas infelizmente as velocidades são muito altas. Veja minha resposta ao comentário em @ ashes999 e edite acima para obter mais informações. Muito obrigado pela sua ajuda!
MindSeeker

A única maneira de saber sobre desempenho é experimentá-lo, medi-lo e ver. Eu já vi algum código "obviamente" ineficiente ter desempenho maciço nas versões eficientes antes, geralmente por razões não intuitivas. Não pergunte o que é mais rápido; teste e descubra.
Sean Middleditch

É justo, vou seguir em frente e tentar meu método, modificado como você sugeriu. Minha pergunta no comentário ainda permanece: "Você pode calcular quando a colisão ocorreu". Você está recomendando que eu fique com a minha equação do passo 3 para esse passo? Ou há um jeito melhor? Esta é a parte mais difícil do problema, eu acho. Os volumes varridos, se os estou entendendo corretamente, podem me dizer que os caminhos dos objetos se cruzam, mas não podem me dizer se / quando os próprios objetos colidem.
MindSeeker

1
A geometria varrida pelo @MindSeeker é radiodifusão, exceto que você está moldando a forma em vez de um raio. Portanto, o método deve ser semelhante ao uso da conversão de raios com "raios" para todos os objetos em movimento rápido, em vez de apenas um raio versus um objeto estacionário. Depois de determinar possíveis colisões dos "raios", é necessário resolver o tempo nos dois "raios" para garantir que eles estavam no mesmo local ao mesmo tempo.
Stonemetal 19/09/2013

2

O algoritmo proposto na pergunta funciona muito bem: é rápido e é completamente preciso , mesmo quando os objetos estão indo a velocidades extremas. Eu tenho um quadtree implementado; portanto, depois de alimentar as caixas da etapa 1 no quadtree, achei a etapa 2 desnecessária: meu programa estava sendo executado quase tão rápido quanto antes.

Estou usando esse algoritmo há alguns meses e parece ser perfeitamente preciso na determinação de t, o tempo da colisão. Como parece não haver nada melhor na Web, recomendo o uso deste. (Algumas das respostas das outras respostas e comentários acima são ótimas, mas elas não atendem completamente às necessidades, conforme declarado na pergunta, ou o autor era muito ambíguo sobre alguma coisa e nunca voltava a responder quando questionado sobre a ambiguidade )


1

Ainda não tenho reputação suficiente para comentar, mas gostaria de acrescentar que o uso do que Sean Middleditch mencionado acima torna possível calcular seu "t". Pelo menos se eu entendi a resposta dele e você pergunta corretamente.

Aqui está um link para uma resposta impressionante de sam hocevar que fornece a melhor explicação sobre isso que eu já encontrei (ele também desenhou fotos, viva!)

/gamedev//a/55991/112940

Se isso é mais rápido que o seu próprio método, não posso dizer, mas ele com certeza fornece tudo o que você precisa para implementá-lo e comparar com o seu.

Apenas para evitar deixar uma "resposta apenas ao link", fornecerei um resumo rápido de sua ideia:

  1. calcular a diferença de Minkowski entre as duas caixas delimitadoras
  2. usando a velocidade relativa entre então, projete um segmento de raio / linha da origem para a caixa criada pela diferença de Minkowski para obter o ponto de interseção
  3. Se o raio atingir, divida a distância percorrida pelo raio pelo comprimento do vetor que representa a velocidade relativa e você terá seu "t"
  4. clique no link que forneci acima e veja uma bela explicação de tudo isso, com muitas fotos. Isso é incrível.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.