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):
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!
fonte
Respostas:
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.
fonte
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 )
fonte
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:
fonte